mirror of
https://github.com/cyanfish/naps2.git
synced 2024-09-17 18:58:11 +03:00
Split up some DesktopController functionality into sub-controllers
This commit is contained in:
parent
607f76cf8d
commit
c77f5b30f9
@ -12,9 +12,9 @@ namespace NAPS2.Update;
|
||||
|
||||
public class UpdateOperation : OperationBase
|
||||
{
|
||||
private readonly ImageContext _imageContext;
|
||||
private readonly ErrorOutput _errorOutput;
|
||||
private readonly DesktopController _desktopController;
|
||||
private readonly DesktopFormProvider _desktopFormProvider;
|
||||
|
||||
private readonly ManualResetEvent _waitHandle = new ManualResetEvent(false);
|
||||
private WebClient? _client;
|
||||
@ -35,11 +35,12 @@ public class UpdateOperation : OperationBase
|
||||
}
|
||||
}
|
||||
|
||||
public UpdateOperation(ImageContext imageContext, ErrorOutput errorOutput, DesktopController desktopController)
|
||||
public UpdateOperation(ErrorOutput errorOutput, DesktopController desktopController,
|
||||
DesktopFormProvider desktopFormProvider)
|
||||
{
|
||||
_imageContext = imageContext;
|
||||
_errorOutput = errorOutput;
|
||||
_desktopController = desktopController;
|
||||
_desktopFormProvider = desktopFormProvider;
|
||||
|
||||
ProgressTitle = MiscResources.UpdateProgress;
|
||||
AllowBackground = true;
|
||||
@ -56,7 +57,8 @@ public class UpdateOperation : OperationBase
|
||||
_update = updateInfo;
|
||||
_tempFolder = Path.Combine(Paths.Temp, Path.GetRandomFileName());
|
||||
Directory.CreateDirectory(_tempFolder);
|
||||
_tempPath = Path.Combine(_tempFolder, updateInfo.DownloadUrl.Substring(updateInfo.DownloadUrl.LastIndexOf('/') + 1));
|
||||
_tempPath = Path.Combine(_tempFolder,
|
||||
updateInfo.DownloadUrl.Substring(updateInfo.DownloadUrl.LastIndexOf('/') + 1));
|
||||
|
||||
_client = new WebClient();
|
||||
_client.DownloadProgressChanged += DownloadProgress;
|
||||
@ -119,12 +121,8 @@ public class UpdateOperation : OperationBase
|
||||
InvokeFinished();
|
||||
_waitHandle.Set();
|
||||
}
|
||||
var desktop = Application.OpenForms.OfType<FDesktop>().FirstOrDefault();
|
||||
if (desktop != null)
|
||||
{
|
||||
_desktopController.SkipRecoveryCleanup = true;
|
||||
desktop.Close();
|
||||
}
|
||||
_desktopController.SkipRecoveryCleanup = true;
|
||||
_desktopFormProvider.DesktopForm.Close();
|
||||
}
|
||||
|
||||
private void InstallExe()
|
||||
@ -181,14 +179,14 @@ public class UpdateOperation : OperationBase
|
||||
private bool VerifySignature()
|
||||
{
|
||||
var cert = new X509Certificate2(ClientCreds.naps2_public);
|
||||
var csp = (RSACryptoServiceProvider)cert.PublicKey.Key;
|
||||
var csp = (RSACryptoServiceProvider) cert.PublicKey.Key;
|
||||
return csp.VerifyHash(_update.Sha1, CryptoConfig.MapNameToOID("SHA1"), _update.Signature);
|
||||
}
|
||||
|
||||
private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
|
||||
{
|
||||
Status.CurrentProgress = (int)e.BytesReceived;
|
||||
Status.MaxProgress = (int)e.TotalBytesToReceive;
|
||||
Status.CurrentProgress = (int) e.BytesReceived;
|
||||
Status.MaxProgress = (int) e.TotalBytesToReceive;
|
||||
InvokeStatusChanged();
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.ImportExport;
|
||||
using NAPS2.ImportExport.Images;
|
||||
using NAPS2.Platform.Windows;
|
||||
@ -8,7 +7,6 @@ using NAPS2.Recovery;
|
||||
using NAPS2.Remoting;
|
||||
using NAPS2.Scan;
|
||||
using NAPS2.Update;
|
||||
using NAPS2.Wia;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
@ -28,24 +26,26 @@ public class DesktopController
|
||||
private readonly Naps2Config _config;
|
||||
private readonly IOperationFactory _operationFactory;
|
||||
private readonly StillImage _stillImage;
|
||||
private readonly IFormFactory _formFactory;
|
||||
private readonly IProfileManager _profileManager;
|
||||
private readonly IScanPerformer _scanPerformer;
|
||||
private readonly UpdateChecker _updateChecker;
|
||||
private readonly NotificationManager _notify;
|
||||
private readonly ImageTransfer _imageTransfer;
|
||||
private readonly ImageClipboard _imageClipboard;
|
||||
private readonly ImageListActions _imageListActions;
|
||||
private readonly WinFormsExportHelper _exportHelper;
|
||||
private readonly DesktopImagesController _desktopImagesController;
|
||||
private readonly DesktopScanController _desktopScanController;
|
||||
private readonly DesktopFormProvider _desktopFormProvider;
|
||||
|
||||
private bool _closed;
|
||||
|
||||
public DesktopController(ScanningContext scanningContext, UiImageList imageList,
|
||||
RecoveryStorageManager recoveryStorageManager, ThumbnailRenderQueue thumbnailRenderQueue,
|
||||
OperationProgress operationProgress, Naps2Config config, IOperationFactory operationFactory,
|
||||
StillImage stillImage, IFormFactory formFactory, IProfileManager profileManager, IScanPerformer scanPerformer,
|
||||
StillImage stillImage,
|
||||
UpdateChecker updateChecker, NotificationManager notify, ImageTransfer imageTransfer,
|
||||
ImageClipboard imageClipboard, ImageListActions imageListActions, WinFormsExportHelper exportHelper)
|
||||
ImageClipboard imageClipboard, ImageListActions imageListActions, WinFormsExportHelper exportHelper,
|
||||
DesktopImagesController desktopImagesController, DesktopScanController desktopScanController,
|
||||
DesktopFormProvider desktopFormProvider)
|
||||
{
|
||||
_scanningContext = scanningContext;
|
||||
_imageList = imageList;
|
||||
@ -55,21 +55,17 @@ public class DesktopController
|
||||
_config = config;
|
||||
_operationFactory = operationFactory;
|
||||
_stillImage = stillImage;
|
||||
_formFactory = formFactory;
|
||||
_profileManager = profileManager;
|
||||
_scanPerformer = scanPerformer;
|
||||
_updateChecker = updateChecker;
|
||||
_notify = notify;
|
||||
_imageTransfer = imageTransfer;
|
||||
_imageClipboard = imageClipboard;
|
||||
_imageListActions = imageListActions;
|
||||
_exportHelper = exportHelper;
|
||||
_desktopImagesController = desktopImagesController;
|
||||
_desktopScanController = desktopScanController;
|
||||
_desktopFormProvider = desktopFormProvider;
|
||||
}
|
||||
|
||||
public Form Form { get; set; }
|
||||
|
||||
public Action<Action> SafeInvoke { get; set; }
|
||||
|
||||
public bool SkipRecoveryCleanup { get; set; }
|
||||
|
||||
public async Task Initialize()
|
||||
@ -124,7 +120,7 @@ public class DesktopController
|
||||
var update = task.Result;
|
||||
if (update != null)
|
||||
{
|
||||
SafeInvoke(() => _notify.UpdateAvailable(_updateChecker, update));
|
||||
_notify.UpdateAvailable(_updateChecker, update);
|
||||
}
|
||||
}).AssertNoAwait();
|
||||
}
|
||||
@ -147,7 +143,7 @@ public class DesktopController
|
||||
// If NAPS2 was started by the scanner button, do the appropriate actions automatically
|
||||
if (_stillImage.ShouldScan)
|
||||
{
|
||||
await ScanWithDevice(_stillImage.DeviceID!);
|
||||
await _desktopScanController.ScanWithDevice(_stillImage.DeviceID!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,8 +212,8 @@ public class DesktopController
|
||||
if (_operationProgress.ActiveOperations.Any())
|
||||
{
|
||||
_operationProgress.ActiveOperations.ForEach(op => op.Cancel());
|
||||
Form.Hide();
|
||||
Form.ShowInTaskbar = false;
|
||||
_desktopFormProvider.DesktopForm.Hide();
|
||||
_desktopFormProvider.DesktopForm.ShowInTaskbar = false;
|
||||
Task.Run(() =>
|
||||
{
|
||||
var timeoutCts = new CancellationTokenSource();
|
||||
@ -230,7 +226,7 @@ public class DesktopController
|
||||
{
|
||||
}
|
||||
_closed = true;
|
||||
SafeInvoke(Form.Close);
|
||||
_desktopFormProvider.DesktopForm.SafeInvoke(_desktopFormProvider.DesktopForm.Close);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -245,18 +241,19 @@ public class DesktopController
|
||||
{
|
||||
if (msg.StartsWith(Pipes.MSG_SCAN_WITH_DEVICE, StringComparison.InvariantCulture))
|
||||
{
|
||||
SafeInvoke(async () => await ScanWithDevice(msg.Substring(Pipes.MSG_SCAN_WITH_DEVICE.Length)));
|
||||
_desktopFormProvider.DesktopForm.SafeInvoke(async () =>
|
||||
await _desktopScanController.ScanWithDevice(msg.Substring(Pipes.MSG_SCAN_WITH_DEVICE.Length)));
|
||||
}
|
||||
if (msg.Equals(Pipes.MSG_ACTIVATE))
|
||||
{
|
||||
SafeInvoke(() =>
|
||||
_desktopFormProvider.DesktopForm.SafeInvoke(() =>
|
||||
{
|
||||
var form = Application.OpenForms.Cast<Form>().Last();
|
||||
if (form.WindowState == FormWindowState.Minimized)
|
||||
var formOnTop = Application.OpenForms.Cast<Form>().Last();
|
||||
if (formOnTop.WindowState == FormWindowState.Minimized)
|
||||
{
|
||||
Win32.ShowWindow(form.Handle, Win32.ShowWindowCommands.Restore);
|
||||
Win32.ShowWindow(formOnTop.Handle, Win32.ShowWindowCommands.Restore);
|
||||
}
|
||||
form.Activate();
|
||||
formOnTop.Activate();
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -277,7 +274,7 @@ public class DesktopController
|
||||
{
|
||||
// Allow scanned images to be recovered in case of an unexpected close
|
||||
var op = _operationFactory.Create<RecoveryOperation>();
|
||||
if (op.Start(ReceiveScannedImage(),
|
||||
if (op.Start(_desktopImagesController.ReceiveScannedImage(),
|
||||
new RecoveryParams { ThumbnailSize = _config.Get(c => c.ThumbnailSize) }))
|
||||
{
|
||||
_operationProgress.ShowProgress(op);
|
||||
@ -290,145 +287,10 @@ public class DesktopController
|
||||
_thumbnailRenderQueue.StartRendering(_imageList);
|
||||
}
|
||||
|
||||
private ScanParams DefaultScanParams() =>
|
||||
new ScanParams
|
||||
{
|
||||
NoAutoSave = _config.Get(c => c.DisableAutoSave),
|
||||
DoOcr = _config.Get(c => c.EnableOcr) && _config.Get(c => c.OcrAfterScanning),
|
||||
ThumbnailSize = _config.Get(c => c.ThumbnailSize)
|
||||
};
|
||||
|
||||
private async Task ScanWithDevice(string deviceID)
|
||||
{
|
||||
Form.Activate();
|
||||
ScanProfile profile;
|
||||
if (_profileManager.DefaultProfile?.Device?.ID == deviceID)
|
||||
{
|
||||
// Try to use the default profile if it has the right device
|
||||
profile = _profileManager.DefaultProfile;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise just pick any old profile with the right device
|
||||
// Not sure if this is the best way to do it, but it's hard to prioritize profiles
|
||||
profile = _profileManager.Profiles.FirstOrDefault(x => x.Device != null && x.Device.ID == deviceID);
|
||||
}
|
||||
if (profile == null)
|
||||
{
|
||||
if (_config.Get(c => c.NoUserProfiles) && _profileManager.Profiles.Any(x => x.IsLocked))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// No profile for the device we're scanning with, so prompt to create one
|
||||
var editSettingsForm = _formFactory.Create<FEditProfile>();
|
||||
editSettingsForm.ScanProfile = _config.Get(c => c.DefaultProfileSettings);
|
||||
try
|
||||
{
|
||||
// Populate the device field automatically (because we can do that!)
|
||||
using var deviceManager = new WiaDeviceManager();
|
||||
using var device = deviceManager.FindDevice(deviceID);
|
||||
editSettingsForm.CurrentDevice = new ScanDevice(deviceID, device.Name());
|
||||
}
|
||||
catch (WiaException)
|
||||
{
|
||||
}
|
||||
editSettingsForm.ShowDialog();
|
||||
if (!editSettingsForm.Result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
profile = editSettingsForm.ScanProfile;
|
||||
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(profile),
|
||||
ListSelection.Empty<ScanProfile>());
|
||||
_profileManager.DefaultProfile = profile;
|
||||
}
|
||||
if (profile != null)
|
||||
{
|
||||
// We got a profile, yay, so we can actually do the scan now
|
||||
var source = await _scanPerformer.PerformScan(profile, DefaultScanParams(), Form.Handle);
|
||||
await source.ForEach(ReceiveScannedImage());
|
||||
Form.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ScanDefault()
|
||||
{
|
||||
if (_profileManager.DefaultProfile != null)
|
||||
{
|
||||
var source =
|
||||
await _scanPerformer.PerformScan(_profileManager.DefaultProfile, DefaultScanParams(), Form.Handle);
|
||||
await source.ForEach(ReceiveScannedImage());
|
||||
Form.Activate();
|
||||
}
|
||||
else if (_profileManager.Profiles.Count == 0)
|
||||
{
|
||||
await ScanWithNewProfile();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowProfilesForm();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ScanWithNewProfile()
|
||||
{
|
||||
var editSettingsForm = _formFactory.Create<FEditProfile>();
|
||||
editSettingsForm.ScanProfile = _config.Get(c => c.DefaultProfileSettings);
|
||||
editSettingsForm.ShowDialog();
|
||||
if (!editSettingsForm.Result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(editSettingsForm.ScanProfile),
|
||||
ListSelection.Empty<ScanProfile>());
|
||||
_profileManager.DefaultProfile = editSettingsForm.ScanProfile;
|
||||
|
||||
var source = await _scanPerformer.PerformScan(editSettingsForm.ScanProfile, DefaultScanParams(), Form.Handle);
|
||||
await source.ForEach(ReceiveScannedImage());
|
||||
Form.Activate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a receiver for scanned images.
|
||||
/// This keeps images from the same source together, even if multiple sources are providing images at the same time.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private Action<ProcessedImage> ReceiveScannedImage()
|
||||
{
|
||||
UiImage? last = null;
|
||||
return scannedImage =>
|
||||
{
|
||||
SafeInvoke(() =>
|
||||
{
|
||||
lock (_imageList)
|
||||
{
|
||||
var uiImage = new UiImage(scannedImage);
|
||||
_imageList.Mutate(new ImageListMutation.InsertAfter(uiImage, last));
|
||||
last = uiImage;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public void ShowProfilesForm()
|
||||
{
|
||||
var form = _formFactory.Create<ProfilesForm>();
|
||||
form.ImageCallback = ReceiveScannedImage();
|
||||
form.ShowModal();
|
||||
}
|
||||
|
||||
public void ShowBatchScanForm()
|
||||
{
|
||||
var form = _formFactory.Create<FBatchScan>();
|
||||
form.ImageCallback = ReceiveScannedImage();
|
||||
form.ShowDialog();
|
||||
}
|
||||
|
||||
public void ImportFiles(IEnumerable<string> files)
|
||||
{
|
||||
var op = _operationFactory.Create<ImportOperation>();
|
||||
if (op.Start(OrderFiles(files), ReceiveScannedImage(),
|
||||
if (op.Start(OrderFiles(files), _desktopImagesController.ReceiveScannedImage(),
|
||||
new ImportParams { ThumbnailSize = _config.Get(c => c.ThumbnailSize) }))
|
||||
{
|
||||
_operationProgress.ShowProgress(op);
|
||||
@ -446,22 +308,13 @@ public class DesktopController
|
||||
public void ImportDirect(ImageTransferData data, bool copy)
|
||||
{
|
||||
var op = _operationFactory.Create<DirectImportOperation>();
|
||||
if (op.Start(data, copy, ReceiveScannedImage(),
|
||||
if (op.Start(data, copy, _desktopImagesController.ReceiveScannedImage(),
|
||||
new DirectImportParams { ThumbnailSize = _config.Get(c => c.ThumbnailSize) }))
|
||||
{
|
||||
_operationProgress.ShowProgress(op);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ScanWithProfile(ScanProfile profile)
|
||||
{
|
||||
_profileManager.DefaultProfile = profile;
|
||||
|
||||
var source = await _scanPerformer.PerformScan(profile, DefaultScanParams(), Form.Handle);
|
||||
await source.ForEach(ReceiveScannedImage());
|
||||
Form.Activate();
|
||||
}
|
||||
|
||||
public void Paste()
|
||||
{
|
||||
if (_imageTransfer.IsInClipboard())
|
||||
@ -503,28 +356,6 @@ public class DesktopController
|
||||
}
|
||||
}
|
||||
|
||||
public void PreviewImage()
|
||||
{
|
||||
if (_imageList.Selection.Any())
|
||||
{
|
||||
using var viewer = _formFactory.Create<FViewer>();
|
||||
viewer.ImageList = _imageList;
|
||||
// TODO: Fix this
|
||||
// viewer.ImageIndex = SelectedIndices.First();
|
||||
// viewer.DeleteCallback = UpdateThumbnails;
|
||||
viewer.SelectCallback = i =>
|
||||
{
|
||||
if (_imageList.Selection.Count <= 1)
|
||||
{
|
||||
// TODO: Fix this
|
||||
// SelectedIndices = new[] { i };
|
||||
//thumbnailList1.Items[i].EnsureVisible();
|
||||
}
|
||||
};
|
||||
viewer.ShowDialog();
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetImage()
|
||||
{
|
||||
if (_imageList.Selection.Any())
|
||||
@ -538,16 +369,6 @@ public class DesktopController
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenAbout()
|
||||
{
|
||||
_formFactory.Create<AboutForm>().ShowModal();
|
||||
}
|
||||
|
||||
public void OpenSettings()
|
||||
{
|
||||
// FormFactory.Create<FSettings>().ShowDialog();
|
||||
}
|
||||
|
||||
public async Task SavePDF(List<UiImage> images)
|
||||
{
|
||||
using var imagesToSave = images.Select(x => x.GetClonedImage()).ToDisposableList();
|
||||
@ -555,10 +376,7 @@ public class DesktopController
|
||||
{
|
||||
if (_config.Get(c => c.DeleteAfterSaving))
|
||||
{
|
||||
SafeInvoke(() =>
|
||||
{
|
||||
_imageList.Mutate(new ImageListMutation.DeleteSelected(), ListSelection.From(images));
|
||||
});
|
||||
_imageList.Mutate(new ImageListMutation.DeleteSelected(), ListSelection.From(images));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -587,6 +405,7 @@ public class DesktopController
|
||||
{
|
||||
Multiselect = true,
|
||||
CheckFileExists = true,
|
||||
// TODO: Move filter logic somewhere common
|
||||
Filter = MiscResources.FileTypeAllFiles + @"|*.*|" +
|
||||
MiscResources.FileTypePdf + @"|*.pdf|" +
|
||||
MiscResources.FileTypeImageFiles +
|
||||
|
6
NAPS2.Lib.WinForms/WinForms/DesktopFormProvider.cs
Normal file
6
NAPS2.Lib.WinForms/WinForms/DesktopFormProvider.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class DesktopFormProvider
|
||||
{
|
||||
public FormBase DesktopForm { get; set; }
|
||||
}
|
31
NAPS2.Lib.WinForms/WinForms/DesktopImagesController.cs
Normal file
31
NAPS2.Lib.WinForms/WinForms/DesktopImagesController.cs
Normal file
@ -0,0 +1,31 @@
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class DesktopImagesController
|
||||
{
|
||||
private readonly UiImageList _imageList;
|
||||
|
||||
public DesktopImagesController(UiImageList imageList)
|
||||
{
|
||||
_imageList = imageList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a receiver for scanned images.
|
||||
/// This keeps images from the same source together, even if multiple sources are providing images at the same time.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Action<ProcessedImage> ReceiveScannedImage()
|
||||
{
|
||||
var lockObj = new object();
|
||||
UiImage? last = null;
|
||||
return scannedImage =>
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
var uiImage = new UiImage(scannedImage);
|
||||
_imageList.Mutate(new ImageListMutation.InsertAfter(uiImage, last));
|
||||
last = uiImage;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
134
NAPS2.Lib.WinForms/WinForms/DesktopScanController.cs
Normal file
134
NAPS2.Lib.WinForms/WinForms/DesktopScanController.cs
Normal file
@ -0,0 +1,134 @@
|
||||
using NAPS2.Scan;
|
||||
using NAPS2.Wia;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class DesktopScanController
|
||||
{
|
||||
private readonly Naps2Config _config;
|
||||
private readonly IProfileManager _profileManager;
|
||||
private readonly IFormFactory _formFactory;
|
||||
private readonly IScanPerformer _scanPerformer;
|
||||
private readonly DesktopImagesController _desktopImagesController;
|
||||
private readonly DesktopSubFormController _desktopSubFormController;
|
||||
private readonly DesktopFormProvider _desktopFormProvider;
|
||||
|
||||
public DesktopScanController(Naps2Config config, IProfileManager profileManager, IFormFactory formFactory,
|
||||
IScanPerformer scanPerformer, DesktopImagesController desktopImagesController,
|
||||
DesktopSubFormController desktopSubFormController, DesktopFormProvider desktopFormProvider)
|
||||
{
|
||||
_config = config;
|
||||
_profileManager = profileManager;
|
||||
_formFactory = formFactory;
|
||||
_scanPerformer = scanPerformer;
|
||||
_desktopImagesController = desktopImagesController;
|
||||
_desktopSubFormController = desktopSubFormController;
|
||||
_desktopFormProvider = desktopFormProvider;
|
||||
}
|
||||
|
||||
private ScanParams DefaultScanParams() =>
|
||||
new()
|
||||
{
|
||||
NoAutoSave = _config.Get(c => c.DisableAutoSave),
|
||||
DoOcr = _config.Get(c => c.EnableOcr) && _config.Get(c => c.OcrAfterScanning),
|
||||
ThumbnailSize = _config.Get(c => c.ThumbnailSize)
|
||||
};
|
||||
|
||||
public async Task ScanWithDevice(string deviceID)
|
||||
{
|
||||
_desktopFormProvider.DesktopForm.Activate();
|
||||
ScanProfile? profile;
|
||||
if (_profileManager.DefaultProfile?.Device?.ID == deviceID)
|
||||
{
|
||||
// Try to use the default profile if it has the right device
|
||||
profile = _profileManager.DefaultProfile;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise just pick any old profile with the right device
|
||||
// Not sure if this is the best way to do it, but it's hard to prioritize profiles
|
||||
profile = _profileManager.Profiles.FirstOrDefault(x => x.Device != null && x.Device.ID == deviceID);
|
||||
}
|
||||
if (profile == null)
|
||||
{
|
||||
if (_config.Get(c => c.NoUserProfiles) && _profileManager.Profiles.Any(x => x.IsLocked))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// No profile for the device we're scanning with, so prompt to create one
|
||||
var editSettingsForm = _formFactory.Create<FEditProfile>();
|
||||
editSettingsForm.ScanProfile = _config.Get(c => c.DefaultProfileSettings);
|
||||
try
|
||||
{
|
||||
// Populate the device field automatically (because we can do that!)
|
||||
using var deviceManager = new WiaDeviceManager();
|
||||
using var device = deviceManager.FindDevice(deviceID);
|
||||
editSettingsForm.CurrentDevice = new ScanDevice(deviceID, device.Name());
|
||||
}
|
||||
catch (WiaException)
|
||||
{
|
||||
}
|
||||
editSettingsForm.ShowDialog();
|
||||
if (!editSettingsForm.Result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
profile = editSettingsForm.ScanProfile;
|
||||
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(profile),
|
||||
ListSelection.Empty<ScanProfile>());
|
||||
_profileManager.DefaultProfile = profile;
|
||||
}
|
||||
if (profile != null)
|
||||
{
|
||||
// We got a profile, yay, so we can actually do the scan now
|
||||
await DoScan(profile);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ScanDefault()
|
||||
{
|
||||
if (_profileManager.DefaultProfile != null)
|
||||
{
|
||||
await DoScan(_profileManager.DefaultProfile);
|
||||
}
|
||||
else if (_profileManager.Profiles.Count == 0)
|
||||
{
|
||||
await ScanWithNewProfile();
|
||||
}
|
||||
else
|
||||
{
|
||||
_desktopSubFormController.ShowProfilesForm();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ScanWithNewProfile()
|
||||
{
|
||||
var editSettingsForm = _formFactory.Create<FEditProfile>();
|
||||
editSettingsForm.ScanProfile = _config.Get(c => c.DefaultProfileSettings);
|
||||
editSettingsForm.ShowDialog();
|
||||
if (!editSettingsForm.Result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_profileManager.Mutate(new ListMutation<ScanProfile>.Append(editSettingsForm.ScanProfile),
|
||||
ListSelection.Empty<ScanProfile>());
|
||||
_profileManager.DefaultProfile = editSettingsForm.ScanProfile;
|
||||
|
||||
await DoScan(editSettingsForm.ScanProfile);
|
||||
}
|
||||
|
||||
public async Task ScanWithProfile(ScanProfile profile)
|
||||
{
|
||||
_profileManager.DefaultProfile = profile;
|
||||
await DoScan(profile);
|
||||
}
|
||||
|
||||
private async Task DoScan(ScanProfile profile)
|
||||
{
|
||||
var source =
|
||||
await _scanPerformer.PerformScan(profile, DefaultScanParams(), _desktopFormProvider.DesktopForm.Handle);
|
||||
await source.ForEach(_desktopImagesController.ReceiveScannedImage());
|
||||
_desktopFormProvider.DesktopForm.Activate();
|
||||
}
|
||||
}
|
76
NAPS2.Lib.WinForms/WinForms/DesktopSubFormController.cs
Normal file
76
NAPS2.Lib.WinForms/WinForms/DesktopSubFormController.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using NAPS2.EtoForms.Ui;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class DesktopSubFormController
|
||||
{
|
||||
private readonly IFormFactory _formFactory;
|
||||
private readonly UiImageList _imageList;
|
||||
private readonly DesktopImagesController _desktopImagesController;
|
||||
|
||||
public DesktopSubFormController(IFormFactory formFactory, UiImageList imageList,
|
||||
DesktopImagesController desktopImagesController)
|
||||
{
|
||||
_formFactory = formFactory;
|
||||
_imageList = imageList;
|
||||
_desktopImagesController = desktopImagesController;
|
||||
}
|
||||
|
||||
public void ShowImageForm<T>() where T : ImageForm
|
||||
{
|
||||
var selection = _imageList.Selection.ToList();
|
||||
if (selection.Any())
|
||||
{
|
||||
var form = _formFactory.Create<T>();
|
||||
form.Image = selection.First();
|
||||
form.SelectedImages = selection.ToList();
|
||||
form.ShowDialog();
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowProfilesForm()
|
||||
{
|
||||
var form = _formFactory.Create<ProfilesForm>();
|
||||
form.ImageCallback = _desktopImagesController.ReceiveScannedImage();
|
||||
form.ShowModal();
|
||||
}
|
||||
|
||||
public void ShowBatchScanForm()
|
||||
{
|
||||
var form = _formFactory.Create<FBatchScan>();
|
||||
form.ImageCallback = _desktopImagesController.ReceiveScannedImage();
|
||||
form.ShowDialog();
|
||||
}
|
||||
|
||||
public void ShowViewerForm()
|
||||
{
|
||||
if (_imageList.Selection.Any())
|
||||
{
|
||||
using var viewer = _formFactory.Create<FViewer>();
|
||||
viewer.ImageList = _imageList;
|
||||
// TODO: Fix this
|
||||
// viewer.ImageIndex = SelectedIndices.First();
|
||||
// viewer.DeleteCallback = UpdateThumbnails;
|
||||
viewer.SelectCallback = i =>
|
||||
{
|
||||
if (_imageList.Selection.Count <= 1)
|
||||
{
|
||||
// TODO: Fix this
|
||||
// SelectedIndices = new[] { i };
|
||||
//thumbnailList1.Items[i].EnsureVisible();
|
||||
}
|
||||
};
|
||||
viewer.ShowDialog();
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowAboutForm()
|
||||
{
|
||||
_formFactory.Create<AboutForm>().ShowModal();
|
||||
}
|
||||
|
||||
public void ShowSettingsForm()
|
||||
{
|
||||
// FormFactory.Create<FSettings>().ShowDialog();
|
||||
}
|
||||
}
|
@ -29,7 +29,10 @@ namespace NAPS2.WinForms
|
||||
private readonly ThumbnailRenderQueue _thumbnailRenderQueue;
|
||||
private readonly UiThumbnailProvider _thumbnailProvider;
|
||||
private readonly DesktopController _desktopController;
|
||||
private readonly DesktopScanController _desktopScanController;
|
||||
private readonly ImageListActions _imageListActions;
|
||||
private readonly DesktopFormProvider _desktopFormProvider;
|
||||
private readonly DesktopSubFormController _desktopSubFormController;
|
||||
|
||||
private WinFormsListView<UiImage> _listView;
|
||||
private ImageListSyncer? _imageListSyncer;
|
||||
@ -51,7 +54,9 @@ namespace NAPS2.WinForms
|
||||
ThumbnailRenderQueue thumbnailRenderQueue,
|
||||
UiThumbnailProvider thumbnailProvider,
|
||||
DesktopController desktopController,
|
||||
ImageListActions imageListActions)
|
||||
DesktopScanController desktopScanController,
|
||||
ImageListActions imageListActions,
|
||||
DesktopFormProvider desktopFormProvider, DesktopSubFormController desktopSubFormController)
|
||||
{
|
||||
_toolbarFormatter = toolbarFormatter;
|
||||
_tesseractLanguageManager = tesseractLanguageManager;
|
||||
@ -66,7 +71,10 @@ namespace NAPS2.WinForms
|
||||
_thumbnailRenderQueue = thumbnailRenderQueue;
|
||||
_thumbnailProvider = thumbnailProvider;
|
||||
_desktopController = desktopController;
|
||||
_desktopScanController = desktopScanController;
|
||||
_imageListActions = imageListActions;
|
||||
_desktopFormProvider = desktopFormProvider;
|
||||
_desktopSubFormController = desktopSubFormController;
|
||||
InitializeComponent();
|
||||
|
||||
notify.ParentForm = this;
|
||||
@ -82,6 +90,7 @@ namespace NAPS2.WinForms
|
||||
});
|
||||
};
|
||||
_profileManager.ProfilesUpdated += (_, _) => UpdateScanButton();
|
||||
_desktopFormProvider.DesktopForm = this;
|
||||
}
|
||||
|
||||
protected override void OnLoad(object sender, EventArgs args) => PostInitializeComponent();
|
||||
@ -213,8 +222,6 @@ namespace NAPS2.WinForms
|
||||
new Eto.Forms.Application(Eto.Platforms.WinForms).Attach();
|
||||
|
||||
UpdateToolbar();
|
||||
_desktopController.Form = this;
|
||||
_desktopController.SafeInvoke = SafeInvoke;
|
||||
await _desktopController.Initialize();
|
||||
}
|
||||
|
||||
@ -304,7 +311,7 @@ namespace NAPS2.WinForms
|
||||
ImageScaling = ToolStripItemImageScaling.None
|
||||
};
|
||||
AssignProfileShortcut(i, item);
|
||||
item.Click += async (_, _) => await _desktopController.ScanWithProfile(profile);
|
||||
item.Click += async (_, _) => await _desktopScanController.ScanWithProfile(profile);
|
||||
tsScan.DropDownItems.Insert(tsScan.DropDownItems.Count - staticButtonCount, item);
|
||||
|
||||
i++;
|
||||
@ -353,7 +360,7 @@ namespace NAPS2.WinForms
|
||||
_ksm.Assign("Ctrl+Down", _imageListActions.MoveDown);
|
||||
_ksm.Assign("Ctrl+Right", _imageListActions.MoveDown);
|
||||
_ksm.Assign("Ctrl+Shift+Del", tsClear);
|
||||
_ksm.Assign("F1", _desktopController.OpenAbout);
|
||||
_ksm.Assign("F1", _desktopSubFormController.ShowAboutForm);
|
||||
_ksm.Assign("Ctrl+OemMinus", btnZoomOut);
|
||||
_ksm.Assign("Ctrl+Oemplus", btnZoomIn);
|
||||
_ksm.Assign("Del", ctxDelete);
|
||||
@ -365,7 +372,7 @@ namespace NAPS2.WinForms
|
||||
|
||||
var ks = Config.Get(c => c.KeyboardShortcuts);
|
||||
|
||||
_ksm.Assign(ks.About, _desktopController.OpenAbout);
|
||||
_ksm.Assign(ks.About, _desktopSubFormController.ShowAboutForm);
|
||||
_ksm.Assign(ks.BatchScan, tsBatchScan);
|
||||
_ksm.Assign(ks.Clear, tsClear);
|
||||
_ksm.Assign(ks.Delete, tsDelete);
|
||||
@ -478,13 +485,13 @@ namespace NAPS2.WinForms
|
||||
|
||||
#region Event Handlers - Toolbar
|
||||
|
||||
private async void tsScan_ButtonClick(object sender, EventArgs e) => await _desktopController.ScanDefault();
|
||||
private async void tsScan_ButtonClick(object sender, EventArgs e) => await _desktopScanController.ScanDefault();
|
||||
|
||||
private async void tsNewProfile_Click(object sender, EventArgs e) => await _desktopController.ScanWithNewProfile();
|
||||
private async void tsNewProfile_Click(object sender, EventArgs e) =>
|
||||
await _desktopScanController.ScanWithNewProfile();
|
||||
|
||||
private void tsBatchScan_Click(object sender, EventArgs e) => _desktopController.ShowBatchScanForm();
|
||||
|
||||
private void tsProfiles_Click(object sender, EventArgs e) => _desktopController.ShowProfilesForm();
|
||||
private void tsBatchScan_Click(object sender, EventArgs e) => _desktopSubFormController.ShowBatchScanForm();
|
||||
private void tsProfiles_Click(object sender, EventArgs e) => _desktopSubFormController.ShowProfilesForm();
|
||||
|
||||
private void tsOcr_Click(object sender, EventArgs e)
|
||||
{
|
||||
@ -580,19 +587,25 @@ namespace NAPS2.WinForms
|
||||
|
||||
private void tsClear_Click(object sender, EventArgs e) => _desktopController.Clear();
|
||||
|
||||
private void tsAbout_Click(object sender, EventArgs e) => _desktopController.OpenAbout();
|
||||
private void tsAbout_Click(object sender, EventArgs e) => _desktopSubFormController.ShowAboutForm();
|
||||
|
||||
private void tsSettings_Click(object sender, EventArgs e) => _desktopController.OpenSettings();
|
||||
private void tsSettings_Click(object sender, EventArgs e) => _desktopSubFormController.ShowSettingsForm();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers - Save/Email Menus
|
||||
|
||||
private async void tsSavePDFAll_Click(object sender, EventArgs e) => await _desktopController.SavePDF(_imageList.Images);
|
||||
private async void tsSavePDFSelected_Click(object sender, EventArgs e) => await _desktopController.SavePDF(_imageList.Selection.ToList());
|
||||
private async void tsPDFSettings_Click(object sender, EventArgs e) => FormFactory.Create<FPdfSettings>().ShowDialog();
|
||||
private async void tsSavePDFAll_Click(object sender, EventArgs e) =>
|
||||
await _desktopController.SavePDF(_imageList.Images);
|
||||
|
||||
private async void tsSaveImagesAll_Click(object sender, EventArgs e) => await _desktopController.SaveImages(_imageList.Images);
|
||||
private async void tsSavePDFSelected_Click(object sender, EventArgs e) =>
|
||||
await _desktopController.SavePDF(_imageList.Selection.ToList());
|
||||
|
||||
private async void tsPDFSettings_Click(object sender, EventArgs e) =>
|
||||
FormFactory.Create<FPdfSettings>().ShowDialog();
|
||||
|
||||
private async void tsSaveImagesAll_Click(object sender, EventArgs e) =>
|
||||
await _desktopController.SaveImages(_imageList.Images);
|
||||
|
||||
private async void tsSaveImagesSelected_Click(object sender, EventArgs e) =>
|
||||
await _desktopController.SaveImages(_imageList.Selection.ToList());
|
||||
@ -600,8 +613,11 @@ namespace NAPS2.WinForms
|
||||
private void tsImageSettings_Click(object sender, EventArgs e) =>
|
||||
FormFactory.Create<FImageSettings>().ShowDialog();
|
||||
|
||||
private async void tsEmailPDFAll_Click(object sender, EventArgs e) => await _desktopController.EmailPDF(_imageList.Images);
|
||||
private async void tsEmailPDFSelected_Click(object sender, EventArgs e) => await _desktopController.EmailPDF(_imageList.Selection.ToList());
|
||||
private async void tsEmailPDFAll_Click(object sender, EventArgs e) =>
|
||||
await _desktopController.EmailPDF(_imageList.Images);
|
||||
|
||||
private async void tsEmailPDFSelected_Click(object sender, EventArgs e) =>
|
||||
await _desktopController.EmailPDF(_imageList.Selection.ToList());
|
||||
|
||||
private void tsPdfSettings2_Click(object sender, EventArgs e) =>
|
||||
FormFactory.Create<FPdfSettings>().ShowDialog();
|
||||
@ -613,25 +629,19 @@ namespace NAPS2.WinForms
|
||||
|
||||
#region Event Handlers - Image Menu
|
||||
|
||||
private void tsView_Click(object sender, EventArgs e) => _desktopController.PreviewImage();
|
||||
private void tsView_Click(object sender, EventArgs e) => _desktopSubFormController.ShowViewerForm();
|
||||
private void tsCrop_Click(object sender, EventArgs e) => _desktopSubFormController.ShowImageForm<FCrop>();
|
||||
|
||||
private void ShowImageForm<T>() where T : ImageForm
|
||||
{
|
||||
var selection = _imageList.Selection.ToList();
|
||||
if (selection.Any())
|
||||
{
|
||||
var form = FormFactory.Create<T>();
|
||||
form.Image = selection.First();
|
||||
form.SelectedImages = selection.ToList();
|
||||
form.ShowDialog();
|
||||
}
|
||||
}
|
||||
private void tsBrightnessContrast_Click(object sender, EventArgs e) =>
|
||||
_desktopSubFormController.ShowImageForm<FBrightnessContrast>();
|
||||
|
||||
private void tsCrop_Click(object sender, EventArgs e) => ShowImageForm<FCrop>();
|
||||
private void tsBrightnessContrast_Click(object sender, EventArgs e) => ShowImageForm<FBrightnessContrast>();
|
||||
private void tsHueSaturation_Click(object sender, EventArgs e) => ShowImageForm<FHueSaturation>();
|
||||
private void tsBlackWhite_Click(object sender, EventArgs e) => ShowImageForm<FBlackWhite>();
|
||||
private void tsSharpen_Click(object sender, EventArgs e) => ShowImageForm<FSharpen>();
|
||||
private void tsHueSaturation_Click(object sender, EventArgs e) =>
|
||||
_desktopSubFormController.ShowImageForm<FHueSaturation>();
|
||||
|
||||
private void tsBlackWhite_Click(object sender, EventArgs e) =>
|
||||
_desktopSubFormController.ShowImageForm<FBlackWhite>();
|
||||
|
||||
private void tsSharpen_Click(object sender, EventArgs e) => _desktopSubFormController.ShowImageForm<FSharpen>();
|
||||
private void tsReset_Click(object sender, EventArgs e) => _desktopController.ResetImage();
|
||||
|
||||
#endregion
|
||||
@ -642,7 +652,7 @@ namespace NAPS2.WinForms
|
||||
private async void tsRotateRight_Click(object sender, EventArgs e) => await _imageListActions.RotateRight();
|
||||
private async void tsFlip_Click(object sender, EventArgs e) => await _imageListActions.Flip();
|
||||
private void tsDeskew_Click(object sender, EventArgs e) => _imageListActions.Deskew();
|
||||
private void tsCustomRotation_Click(object sender, EventArgs e) => ShowImageForm<FRotate>();
|
||||
private void tsCustomRotation_Click(object sender, EventArgs e) => _desktopSubFormController.ShowImageForm<FRotate>();
|
||||
|
||||
#endregion
|
||||
|
||||
@ -669,7 +679,7 @@ namespace NAPS2.WinForms
|
||||
}
|
||||
|
||||
private void ctxSelectAll_Click(object sender, EventArgs e) => _imageListActions.SelectAll();
|
||||
private void ctxView_Click(object sender, EventArgs e) => _desktopController.PreviewImage();
|
||||
private void ctxView_Click(object sender, EventArgs e) => _desktopSubFormController.ShowViewerForm();
|
||||
private void ctxDelete_Click(object sender, EventArgs e) => _desktopController.Delete();
|
||||
|
||||
private async void ctxCopy_Click(object sender, EventArgs e) => await _desktopController.Copy();
|
||||
@ -735,7 +745,7 @@ namespace NAPS2.WinForms
|
||||
|
||||
#region Drag/Drop
|
||||
|
||||
private void ListViewItemClicked(object? sender, EventArgs e) => _desktopController.PreviewImage();
|
||||
private void ListViewItemClicked(object? sender, EventArgs e) => _desktopSubFormController.ShowViewerForm();
|
||||
|
||||
private void ListViewSelectionChanged(object? sender, EventArgs e)
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ using Timer = System.Threading.Timer;
|
||||
|
||||
namespace NAPS2.WinForms
|
||||
{
|
||||
partial class ImageForm : FormBase
|
||||
public partial class ImageForm : FormBase
|
||||
{
|
||||
private readonly ImageContext _imageContext;
|
||||
|
||||
|
@ -17,6 +17,7 @@ public class WinFormsDialogHelper : DialogHelper
|
||||
{
|
||||
OverwritePrompt = false,
|
||||
AddExtension = true,
|
||||
// TODO: Move filter logic somewhere common
|
||||
Filter = MiscResources.FileTypePdf + @"|*.pdf|" +
|
||||
MiscResources.FileTypeBmp + @"|*.bmp|" +
|
||||
MiscResources.FileTypeEmf + @"|*.emf|" +
|
||||
@ -62,6 +63,7 @@ public class WinFormsDialogHelper : DialogHelper
|
||||
{
|
||||
OverwritePrompt = false,
|
||||
AddExtension = true,
|
||||
// TODO: Move filter logic somewhere common
|
||||
Filter = MiscResources.FileTypeBmp + @"|*.bmp|" +
|
||||
MiscResources.FileTypeEmf + @"|*.emf|" +
|
||||
MiscResources.FileTypeExif + @"|*.exif|" +
|
||||
|
@ -6,6 +6,7 @@ using NAPS2.ImportExport.Pdf;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
// TODO: Rename this ImageExportController or something
|
||||
public class WinFormsExportHelper
|
||||
{
|
||||
private readonly DialogHelper _dialogHelper;
|
||||
|
@ -1,5 +1,6 @@
|
||||
namespace NAPS2.Threading;
|
||||
|
||||
// TODO: Can we get rid of this static context?
|
||||
/// <summary>
|
||||
/// Synchronized access to the UI thread.
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user