mirror of
https://github.com/kwsch/PKHeX
synced 2024-12-18 16:33:24 +00:00
1d4e815689
all common strings in forms used by multiple generations would rather rework the individual generation strings to be unnecessary with better interaction instead (if possible), as translating hundreds of limited exposure strings is a drag.
194 lines
7.8 KiB
C#
194 lines
7.8 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Web;
|
|
using System.Windows.Forms;
|
|
using PKHeX.Core;
|
|
using QRCoder;
|
|
|
|
using static PKHeX.Core.MessageStrings;
|
|
|
|
namespace PKHeX.WinForms
|
|
{
|
|
public partial class QR : Form
|
|
{
|
|
private readonly PKM pkm;
|
|
private readonly Image icon;
|
|
private Image qr;
|
|
|
|
private readonly string[] Lines;
|
|
private string extraText;
|
|
|
|
public QR(Image qr, Image icon, PKM pk, params string[] lines)
|
|
{
|
|
InitializeComponent();
|
|
pkm = pk;
|
|
|
|
// Layer on Text
|
|
const int stretch = 50;
|
|
Height += stretch;
|
|
|
|
if (pkm != null && pkm.Format == 7)
|
|
Height += 40;
|
|
|
|
this.qr = qr;
|
|
this.icon = icon;
|
|
Lines = lines;
|
|
|
|
if (pkm != null && pkm.Format == 7)
|
|
UpdateBoxSlotCopies(null, null);
|
|
else
|
|
RefreshImage();
|
|
}
|
|
|
|
private void RefreshImage()
|
|
{
|
|
Font font = !Main.Unicode ? FontLabel.Font : FontUtil.GetPKXFont((float)8.25);
|
|
Image preview = new Bitmap(45, 45);
|
|
using (Graphics gfx = Graphics.FromImage(preview))
|
|
{
|
|
gfx.FillRectangle(new SolidBrush(Color.White), 0, 0, preview.Width, preview.Height);
|
|
gfx.DrawImage(icon, preview.Width / 2 - icon.Width / 2, preview.Height / 2 - icon.Height / 2);
|
|
}
|
|
// Layer on Preview Image
|
|
Image pic = ImageUtil.LayerImage(qr, preview, qr.Width / 2 - preview.Width / 2, qr.Height / 2 - preview.Height / 2, 1);
|
|
|
|
Image newpic = new Bitmap(PB_QR.Width, PB_QR.Height);
|
|
using (Graphics g = Graphics.FromImage(newpic))
|
|
{
|
|
g.FillRectangle(new SolidBrush(Color.White), 0, 0, newpic.Width, newpic.Height);
|
|
g.DrawImage(pic, 0, 0);
|
|
|
|
g.DrawString(GetLine(0), font, Brushes.Black, new PointF(18, qr.Height - 5));
|
|
g.DrawString(GetLine(1), font, Brushes.Black, new PointF(18, qr.Height + 8));
|
|
g.DrawString(GetLine(2).Replace(Environment.NewLine, "/").Replace("//", " ").Replace(":/", ": "), font, Brushes.Black, new PointF(18, qr.Height + 20));
|
|
g.DrawString(GetLine(3) + extraText, font, Brushes.Black, new PointF(18, qr.Height + 32));
|
|
}
|
|
PB_QR.BackgroundImage = newpic;
|
|
}
|
|
|
|
private string GetLine(int line) => Lines.Length <= line ? string.Empty : Lines[line];
|
|
|
|
private void PB_QR_Click(object sender, EventArgs e)
|
|
{
|
|
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgQRClipboardImage)) return;
|
|
try { Clipboard.SetImage(PB_QR.BackgroundImage); }
|
|
catch { WinFormsUtil.Alert(MsgQRClipboardFail); }
|
|
}
|
|
|
|
// QR Utility
|
|
private const string QR6PathBad = "null/#"; // prefix to prevent URL from loading
|
|
private const string QR6Path = @"http://lunarcookies.github.io/b1s1.html#";
|
|
private const string DecodeAPI = "http://api.qrserver.com/v1/read-qr-code/?fileurl=";
|
|
private const int QRSize = 365;
|
|
private static readonly string EncodeAPI = $"http://chart.apis.google.com/chart?chs={QRSize}x{QRSize}&cht=qr&chl=";
|
|
|
|
internal static byte[] GetQRData(string address)
|
|
{
|
|
// Fetch data from QR code...
|
|
try { if (address.Length < 4 || !address.StartsWith("http")) { WinFormsUtil.Alert(MsgQRUrlFailPath, address); return null; } }
|
|
catch { WinFormsUtil.Alert(MsgQRUrlFailPath, address); return null; }
|
|
string webURL = DecodeAPI + HttpUtility.UrlEncode(address);
|
|
string data;
|
|
try
|
|
{
|
|
data = NetUtil.GetStringFromURL(webURL);
|
|
if (data.Contains("could not find")) { WinFormsUtil.Alert(MsgQRUrlFailImage); return null; }
|
|
if (data.Contains("filetype not supported")) { WinFormsUtil.Alert(MsgQRUrlFailType, address); return null; }
|
|
}
|
|
catch { WinFormsUtil.Alert(MsgQRUrlFailConnection); return null; }
|
|
|
|
// Quickly convert the json response to a data string
|
|
try { return DecodeQRJson(data); }
|
|
catch (Exception e) { WinFormsUtil.Alert(MsgQRUrlFailConvert, e.Message); return null; }
|
|
}
|
|
private static byte[] DecodeQRJson(string data)
|
|
{
|
|
const string cap = "\",\"error\":null}]}]";
|
|
const string intro = "[{\"type\":\"qrcode\",\"symbol\":[{\"seq\":0,\"data\":\"";
|
|
const string qrcode = "nQR-Code:";
|
|
if (!data.StartsWith(intro))
|
|
throw new FormatException();
|
|
|
|
string pkstr = data.Substring(intro.Length);
|
|
if (pkstr.Contains(qrcode)) // Remove multiple QR codes in same image
|
|
pkstr = pkstr.Substring(0, pkstr.IndexOf(qrcode, StringComparison.Ordinal));
|
|
pkstr = pkstr.Substring(0, pkstr.IndexOf(cap, StringComparison.Ordinal)); // Trim outro
|
|
|
|
if (!pkstr.StartsWith("http") && !pkstr.StartsWith(QR6PathBad)) // G7
|
|
{
|
|
string fstr = Regex.Unescape(pkstr);
|
|
byte[] raw = Encoding.Unicode.GetBytes(fstr);
|
|
// Remove 00 interstitials and retrieve from offset 0x30, take PK7 Stored Size (always)
|
|
return raw.ToList().Where((c, i) => i % 2 == 0).Skip(0x30).Take(0xE8).ToArray();
|
|
}
|
|
// All except G7
|
|
pkstr = pkstr.Substring(pkstr.IndexOf("#", StringComparison.Ordinal) + 1); // Trim URL
|
|
pkstr = pkstr.Replace("\\", ""); // Rectify response
|
|
|
|
return Convert.FromBase64String(pkstr);
|
|
}
|
|
|
|
internal static Image GetQRImage(byte[] data, string server)
|
|
{
|
|
string qrdata = Convert.ToBase64String(data);
|
|
string message = server + qrdata;
|
|
string webURL = EncodeAPI + HttpUtility.UrlEncode(message);
|
|
|
|
try
|
|
{
|
|
return NetUtil.GetImageFromURL(webURL);
|
|
}
|
|
catch
|
|
{
|
|
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgQRUrlFailConnection, MsgQRClipboardUrl))
|
|
return null;
|
|
try { Clipboard.SetText(webURL); }
|
|
catch { WinFormsUtil.Alert(MsgClipboardFailWrite); }
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void UpdateBoxSlotCopies(object sender, EventArgs e)
|
|
{
|
|
if (pkm == null || pkm.Format != 7)
|
|
throw new ArgumentException("Can't update QR7 if pkm isn't a PK7!");
|
|
var box = (int) NUD_Box.Value - 1;
|
|
var slot = (int) NUD_Slot.Value - 1;
|
|
var copies = (int) NUD_Copies.Value;
|
|
var new_qr = GenerateQRCode7((PK7)pkm, box, slot, copies);
|
|
qr = new_qr;
|
|
SuspendLayout();
|
|
extraText = $" (Box {box+1}, Slot {slot+1}, {copies} cop{(copies > 1 ? "ies" : "y")})";
|
|
RefreshImage();
|
|
ResumeLayout();
|
|
}
|
|
|
|
// QR7 Utility
|
|
public static Image GenerateQRCode7(PK7 pk7, int box = 0, int slot = 0, int num_copies = 1)
|
|
{
|
|
byte[] data = QR7.GenerateQRData(pk7, box, slot, num_copies);
|
|
return GenerateQRCode(data, ppm: 4);
|
|
}
|
|
private static Image GenerateQRCode(byte[] data, int ppm = 4)
|
|
{
|
|
using (var generator = new QRCodeGenerator())
|
|
using (var qr_data = generator.CreateQRCode(data))
|
|
using (var qr_code = new QRCode(qr_data))
|
|
return qr_code.GetGraphic(ppm);
|
|
}
|
|
|
|
public static string GetQRServer(int format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case 6:
|
|
return QR6Path;
|
|
default:
|
|
return QR6PathBad;
|
|
}
|
|
}
|
|
}
|
|
}
|