PKHeX/PKHeX.Avalonia/ViewModels/Subforms/QRDialogViewModel.cs
montanon 807007ad8a Fix bitmap memory leaks, load concurrency, money clamp
Bitmap disposal (6 files):
- SlotModel.SetImage: dispose old Avalonia Bitmap + input SKBitmap
- PKMEditorVM: dispose old SpriteImage, LegalityImage, BallSprite
  and intermediate SKBitmaps on every update
- SAVEditorVM: dispose old BoxWallpaper + SKBitmap on box navigation
- WondercardVM: dispose old GiftSlotModel.Sprite on refresh
- QRDialogVM: dispose intermediate SKBitmaps during QR generation
- Added ToAvaloniaBitmapAndDispose helper for owned SKBitmap conversion

Concurrency:
- MainWindowVM: add _isLoading guard to prevent concurrent LoadFileAsync
  calls from drag-drop or rapid Open clicks

Money clamp:
- Trainer8/8a/8b/9/9a: clamp Money to sav.MaxMoney on save
  (was allowing values exceeding game maximums)
2026-03-18 15:32:37 -03:00

63 lines
1.7 KiB
C#

using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel;
using PKHeX.Avalonia.Converters;
using PKHeX.Core;
using PKHeX.Drawing.Misc.Avalonia;
using PKHeX.Drawing.PokeSprite.Avalonia;
using SkiaSharp;
namespace PKHeX.Avalonia.ViewModels.Subforms;
/// <summary>
/// ViewModel for the QR Code dialog. Generates and displays a QR code for a PKM entity.
/// </summary>
public partial class QRDialogViewModel : ObservableObject
{
[ObservableProperty]
private Bitmap? _qrImage;
[ObservableProperty]
private string _summaryText = string.Empty;
/// <summary>
/// The composed QR code as an SKBitmap, retained for copy/save operations.
/// </summary>
private SKBitmap? _qrBitmap;
public QRDialogViewModel(PKM pk)
{
GenerateQR(pk);
}
private void GenerateQR(PKM pk)
{
var qr = QREncode.GenerateQRCode(pk);
var sprite = pk.Sprite();
var composed = QRImageUtil.GetQRImage(qr, sprite);
qr.Dispose();
sprite.Dispose();
_qrBitmap?.Dispose();
_qrBitmap = composed;
var old = QrImage;
QrImage = SKBitmapToAvaloniaBitmapConverter.ToAvaloniaBitmap(composed);
old?.Dispose();
var lines = pk.GetQRLines();
SummaryText = string.Join("\n", lines);
}
/// <summary>
/// Gets the raw PNG bytes of the QR image for clipboard/save operations.
/// </summary>
public byte[]? GetQRImageBytes()
{
if (_qrBitmap is null)
return null;
using var image = SKImage.FromBitmap(_qrBitmap);
using var data = image.Encode(SKEncodedImageFormat.Png, 100);
return data.ToArray();
}
}