Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Conceição <Tiago_caza@hotmail.com>2021-12-03 01:28:14 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2021-12-03 01:28:14 +0300
commit40a89a71d1a920d330e25350f113eb5b1bf9f97e (patch)
tree32ead8eeb7303ba602342d70b341703abeb68030
parent2d1f205c75062b6b2c6b6004536114e8028bda4b (diff)
v2.25.3v2.25.3
- **File - Send to:** - (Add) Icons to distinguish each send type - (Add) Allow to configure processes to open the file with (#352) - (Improvement) CXDLP: When encoding the file, only attempt to change the machine name if not starts with 'CL-' (#351) - (Improvement) UI: Remove the "0/?" and just show the title on the progress bar - (Change) CTBv4: Remove the following validation to be compatible with lychee and CTB SDK: "Malformed file, PrintParametersV4 found invalid validation values, expected (4, 4) got (x, y)" (#354)
-rw-r--r--CHANGELOG.md9
-rw-r--r--CREDITS.md3
-rw-r--r--Scripts/010 Editor/cxdlp_v2.bt12
-rw-r--r--UVtools.Core/FileFormats/CXDLPFile.cs64
-rw-r--r--UVtools.Core/FileFormats/ChituboxFile.cs4
-rw-r--r--UVtools.Core/Objects/MappedProcess.cs173
-rw-r--r--UVtools.Core/Operations/OperationProgress.cs21
-rw-r--r--UVtools.Core/UVtools.Core.csproj4
-rw-r--r--UVtools.WPF/Assets/Icons/cog-16x16.pngbin0 -> 190 bytes
-rw-r--r--UVtools.WPF/Assets/Icons/folder-16x16.pngbin0 -> 97 bytes
-rw-r--r--UVtools.WPF/Assets/Icons/network-wired-16x16.pngbin0 -> 133 bytes
-rw-r--r--UVtools.WPF/Assets/Icons/usb-16x16.pngbin0 -> 164 bytes
-rw-r--r--UVtools.WPF/MainWindow.axaml.cs111
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj4
-rw-r--r--UVtools.WPF/UserSettings.cs178
-rw-r--r--UVtools.WPF/Windows/SettingsWindow.axaml78
-rw-r--r--UVtools.WPF/Windows/SettingsWindow.axaml.cs31
-rw-r--r--build/CreateRelease.WPF.ps12
18 files changed, 644 insertions, 50 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99e5d79..44e3855 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 02/12/2021 - v2.25.3
+
+- **File - Send to:**
+ - (Add) Icons to distinguish each send type
+ - (Add) Allow to configure processes to open the file with (#352)
+- (Improvement) CXDLP: When encoding the file, only attempt to change the machine name if not starts with 'CL-' (#351)
+- (Improvement) UI: Remove the "0/?" and just show the title on the progress bar
+- (Change) CTBv4: Remove the following validation to be compatible with lychee and CTB SDK: "Malformed file, PrintParametersV4 found invalid validation values, expected (4, 4) got (x, y)" (#354)
+
## 25/11/2021 - v2.25.2
- **About box:**
diff --git a/CREDITS.md b/CREDITS.md
index 1b8e220..faaf159 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -64,4 +64,5 @@
- Peter Csaki
- Chris Luginbuhl
- Tim Savage
-- Peopoly Inc \ No newline at end of file
+- Peopoly Inc
+- Riccardo Kocmann \ No newline at end of file
diff --git a/Scripts/010 Editor/cxdlp_v2.bt b/Scripts/010 Editor/cxdlp_v2.bt
index 5c6171b..180d7fa 100644
--- a/Scripts/010 Editor/cxdlp_v2.bt
+++ b/Scripts/010 Editor/cxdlp_v2.bt
@@ -88,6 +88,18 @@ struct LAYER_DEF {
ubyte rn3[2] <fgcolor=cBlack, bgcolor=cRed>;
} layerDefs;
+if(header.version >= 3){
+ struct SLICER_INFO {
+ uint32 SoftwareNameSize;
+ char SoftwareName[SoftwareNameSize];
+ uint32 MaterialNameSize;
+ char MaterialName[MaterialNameSize];
+ ubyte offset[67-SoftwareNameSize-MaterialNameSize];
+ ubyte rn0[2] <fgcolor=cBlack, bgcolor=cRed>;
+ } slicerInfo;
+}
+
+
struct LAYERS {
local int i;
for( i = 0; i < header.totalLayers; i++ ){
diff --git a/UVtools.Core/FileFormats/CXDLPFile.cs b/UVtools.Core/FileFormats/CXDLPFile.cs
index ff39673..32e1768 100644
--- a/UVtools.Core/FileFormats/CXDLPFile.cs
+++ b/UVtools.Core/FileFormats/CXDLPFile.cs
@@ -18,7 +18,6 @@ using System.Threading.Tasks;
using BinarySerialization;
using Emgu.CV;
using Emgu.CV.Structure;
-using MoreLinq;
using UVtools.Core.Extensions;
using UVtools.Core.Layers;
using UVtools.Core.Operations;
@@ -82,7 +81,7 @@ namespace UVtools.Core.FileFormats
[FieldOrder(4)]
[FieldLength(nameof(PrinterModelSize))]
- public byte[] PrinterModelArray { get; set; } = { 0x43, 0x4C, 0x2D, 0x38, 0x39, 0x0 }; // CL-89
+ public byte[] PrinterModelArray { get; set; } = Array.Empty<byte>(); // CL-89 { 0x43, 0x4C, 0x2D, 0x38, 0x39, 0x0 }
[Ignore]
public string PrinterModel
@@ -215,7 +214,7 @@ namespace UVtools.Core.FileFormats
}
#endregion
- #region Layer Def
+ #region PreLayer
public sealed class PreLayer
{
@@ -233,6 +232,27 @@ namespace UVtools.Core.FileFormats
}
}
+ #endregion
+
+ #region SlicerInfoV3
+
+ public sealed class SlicerInfoV3
+ {
+ [FieldOrder(0)] [FieldEndianness(Endianness.Big)] public uint SoftwareNameSize { get; set; } = (uint)About.SoftwareWithVersion.Length;
+
+ [FieldOrder(1)] [FieldLength(nameof(SoftwareNameSize))] public string SoftwareName { get; set; } = About.SoftwareWithVersion;
+
+ [FieldOrder(2)] [FieldEndianness(Endianness.Big)] public uint MaterialNameSize { get; set; }
+
+ [FieldOrder(3)] [FieldLength(nameof(MaterialNameSize))] public string MaterialName { get; set; }
+
+ //[FieldOrder(4)] [FieldOffset(67 - SoftwareNameSize - MaterialNameSize)] public PageBreak PageBreak { get; set; } = new();
+ }
+
+ #endregion
+
+ #region Layer Def
+
public sealed class LayerDef
{
[FieldOrder(0)] [FieldEndianness(Endianness.Big)] public uint LayerArea { get; set; }
@@ -355,6 +375,7 @@ namespace UVtools.Core.FileFormats
public Header HeaderSettings { get; protected internal set; } = new();
public SlicerInfo SlicerInfoSettings { get; protected internal set; } = new();
+ public SlicerInfoV3 SlicerInfoV3Settings { get; protected internal set; } = new();
public Footer FooterSettings { get; protected internal set; } = new();
public override FileFormatType FileType => FileFormatType.Binary;
@@ -556,6 +577,12 @@ namespace UVtools.Core.FileFormats
set => base.MachineName = HeaderSettings.PrinterModel = value;
}
+ public override string MaterialName
+ {
+ get => SlicerInfoV3Settings.MaterialName;
+ set => base.MaterialName = SlicerInfoV3Settings.MaterialName = value;
+ }
+
public override object[] Configs => new object[] { HeaderSettings, SlicerInfoSettings, FooterSettings };
#endregion
@@ -574,21 +601,24 @@ namespace UVtools.Core.FileFormats
{
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.ReadWrite);
- if (ResolutionX == 1620 && ResolutionY == 2560)
- {
- MachineName = "CL-60";
- }
- else if (ResolutionX == 3840 && ResolutionY == 2400)
- {
- MachineName = "CL-89";
- }
- else if (ResolutionX == 3840 && ResolutionY == 2160)
- {
- MachineName = "CL-133";
- }
- else if (!MachineName.StartsWith("CL-"))
+ if (!MachineName.StartsWith("CL-"))
{
- throw new Exception("Unable to detect the printer model from resolution, check if resolution is well defined on slicer for your printer model.");
+ if (ResolutionX == 1620 && ResolutionY == 2560)
+ {
+ MachineName = "CL-60"; // One
+ }
+ else if (ResolutionX == 3840 && ResolutionY == 2400) // Sky or lite
+ {
+ MachineName = "CL-89"; // Sky
+ }
+ else if (ResolutionX == 3840 && ResolutionY == 2160)
+ {
+ MachineName = "CL-133"; // Max
+ }
+ else
+ {
+ throw new InvalidDataException("Unable to detect the printer model from resolution, check if resolution is well defined on slicer for your printer model.");
+ }
}
SanitizeProperties();
diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs
index f032d6d..213b50a 100644
--- a/UVtools.Core/FileFormats/ChituboxFile.cs
+++ b/UVtools.Core/FileFormats/ChituboxFile.cs
@@ -2038,13 +2038,13 @@ namespace UVtools.Core.FileFormats
Debug.Write("Print Parameters V4 -> ");
Debug.WriteLine(PrintParametersV4Settings);
- if (PrintParametersV4Settings.Four1 != 4 && PrintParametersV4Settings.Four2 != 4)
+ /*if (PrintParametersV4Settings.Four1 != 4 && PrintParametersV4Settings.Four2 != 4)
{
throw new FileLoadException(
$"Malformed file, PrintParametersV4 found invalid validation values, expected (4, 4) " +
$"but got ({PrintParametersV4Settings.Four1}, {PrintParametersV4Settings.Four2})",
FileFullPath);
- }
+ }*/
}
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
diff --git a/UVtools.Core/Objects/MappedProcess.cs b/UVtools.Core/Objects/MappedProcess.cs
new file mode 100644
index 0000000..6060097
--- /dev/null
+++ b/UVtools.Core/Objects/MappedProcess.cs
@@ -0,0 +1,173 @@
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using UVtools.Core.FileFormats;
+using UVtools.Core.Objects;
+
+namespace UVtools.Core.Objects
+{
+ public class MappedProcess : BindableBase
+ {
+ #region Constants
+
+ public const string DefaultArgument = "\"{0}\"";
+ #endregion
+
+ #region Members
+
+ private bool _isEnabled = true;
+ private string _applicationPath;
+ private string _name;
+ private string _arguments = DefaultArgument;
+ private string _compatibleExtensions;
+ private bool _waitForExit;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets if this device is enabled
+ /// </summary>
+ public bool IsEnabled
+ {
+ get => _isEnabled;
+ set => RaiseAndSetIfChanged(ref _isEnabled, value);
+ }
+
+ /// <summary>
+ /// Gets or sets the full path for the application
+ /// </summary>
+ public string ApplicationPath
+ {
+ get => _applicationPath;
+ set => RaiseAndSetIfChanged(ref _applicationPath, value);
+ }
+
+ /// <summary>
+ /// Gets or sets the path name alias
+ /// </summary>
+ public string Name
+ {
+ get => _name;
+ set => RaiseAndSetIfChanged(ref _name, value);
+ }
+
+ /// <summary>
+ /// Gets or sets the arguments for the application
+ /// </summary>
+ public string Arguments
+ {
+ get => _arguments;
+ set => RaiseAndSetIfChanged(ref _arguments, value);
+ }
+
+ /// <summary>
+ /// Gets or sets the compatible extensions with this device.
+ /// Empty or null to be compatible with everything
+ /// </summary>
+ public string CompatibleExtensions
+ {
+ get => _compatibleExtensions;
+ set => RaiseAndSetIfChanged(ref _compatibleExtensions, value);
+ }
+
+ public bool WaitForExit
+ {
+ get => _waitForExit;
+ set => RaiseAndSetIfChanged(ref _waitForExit, value);
+ }
+
+ #endregion
+
+ #region Contructors
+
+ public MappedProcess() { }
+
+ public MappedProcess(bool isEnabled, string applicationPath, string name = null, string arguments = DefaultArgument)
+ {
+ _isEnabled = isEnabled;
+ _applicationPath = applicationPath;
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ name = Path.GetFileNameWithoutExtension(applicationPath);
+ }
+ _name = name;
+
+ if (string.IsNullOrWhiteSpace(arguments))
+ {
+ arguments = DefaultArgument;
+ }
+
+ _arguments = arguments;
+ }
+
+ public MappedProcess(string applicationPath, string name = null, string arguments = DefaultArgument) : this(true, applicationPath, name, arguments)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ public bool IsValid()
+ {
+ return File.Exists(_applicationPath);
+ }
+
+ public async Task StartProcess(FileFormat slicerFile, CancellationToken cancellationToken = default)
+ {
+ await StartProcess(slicerFile.FileFullPath, cancellationToken);
+ }
+
+ public async Task StartProcess(string slicerFile, CancellationToken cancellationToken = default)
+ {
+ var arguments = string.IsNullOrWhiteSpace(_arguments) ? $"\"{slicerFile}\"" : string.Format(_arguments, slicerFile);
+ using var process = Process.Start(_applicationPath, arguments);
+ if (process is null) return;
+ if (_waitForExit)
+ {
+ await process.WaitForExitAsync(cancellationToken);
+ }
+ }
+
+ public override string ToString()
+ {
+ return $"{_applicationPath} {Arguments}";
+ }
+
+ protected bool Equals(MappedProcess other)
+ {
+ return _applicationPath == other._applicationPath && _name == other._name && _arguments == other._arguments && _compatibleExtensions == other._compatibleExtensions;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != this.GetType()) return false;
+ return Equals((MappedProcess)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(_applicationPath, _name, _arguments, _compatibleExtensions);
+ }
+
+ public MappedProcess Clone()
+ {
+ return MemberwiseClone() as MappedProcess;
+ }
+
+ #endregion
+ }
+}
diff --git a/UVtools.Core/Operations/OperationProgress.cs b/UVtools.Core/Operations/OperationProgress.cs
index a1a418f..480b75a 100644
--- a/UVtools.Core/Operations/OperationProgress.cs
+++ b/UVtools.Core/Operations/OperationProgress.cs
@@ -95,7 +95,11 @@ namespace UVtools.Core.Operations
public string ItemName
{
get => _itemName;
- set => RaiseAndSetIfChanged(ref _itemName, value);
+ set
+ {
+ if(!RaiseAndSetIfChanged(ref _itemName, value)) return;
+ RaisePropertyChanged(nameof(Description));
+ }
}
/// <summary>
@@ -201,9 +205,20 @@ namespace UVtools.Core.Operations
public override string ToString()
{
- return _itemCount == 0 ?
+ if (_itemCount == 0 && _processedItems == 0)
+ {
+ return $"{_itemName}";
+ }
+
+ if (_itemCount == 0 && _processedItems > 0)
+ {
+ return $"{_processedItems} {_itemName}";
+ }
+
+ return $"{_processedItems.ToString().PadLeft(_itemCount.ToString().Length, '0')}/{_itemCount} {_itemName} | {ProgressPercent:F2}%";
+ /*return _itemCount == 0 ?
$"{_processedItems}/? {_itemName}" :
-$"{_processedItems.ToString().PadLeft(_itemCount.ToString().Length, '0')}/{_itemCount} {_itemName} | {ProgressPercent:F2}%";
+$"{_processedItems.ToString().PadLeft(_itemCount.ToString().Length, '0')}/{_itemCount} {_itemName} | {ProgressPercent:F2}%";*/
}
public void TriggerRefresh()
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 5fc06b9..949e014 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
- <Version>2.25.2</Version>
+ <Version>2.25.3</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
@@ -52,7 +52,7 @@
<PackageReference Include="BinarySerializer" Version="8.6.1.2" />
<PackageReference Include="Emgu.CV" Version="4.5.4.4788" />
<PackageReference Include="KdTree" Version="1.4.1" />
- <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.0.1" />
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.1.0-1.final" />
<PackageReference Include="Microsoft.Win32.Registry" Version="6.0.0-preview.5.21301.5" />
<PackageReference Include="morelinq" Version="3.3.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
diff --git a/UVtools.WPF/Assets/Icons/cog-16x16.png b/UVtools.WPF/Assets/Icons/cog-16x16.png
new file mode 100644
index 0000000..b8a242f
--- /dev/null
+++ b/UVtools.WPF/Assets/Icons/cog-16x16.png
Binary files differ
diff --git a/UVtools.WPF/Assets/Icons/folder-16x16.png b/UVtools.WPF/Assets/Icons/folder-16x16.png
new file mode 100644
index 0000000..fb7a5b4
--- /dev/null
+++ b/UVtools.WPF/Assets/Icons/folder-16x16.png
Binary files differ
diff --git a/UVtools.WPF/Assets/Icons/network-wired-16x16.png b/UVtools.WPF/Assets/Icons/network-wired-16x16.png
new file mode 100644
index 0000000..567f2cd
--- /dev/null
+++ b/UVtools.WPF/Assets/Icons/network-wired-16x16.png
Binary files differ
diff --git a/UVtools.WPF/Assets/Icons/usb-16x16.png b/UVtools.WPF/Assets/Icons/usb-16x16.png
new file mode 100644
index 0000000..03e109d
--- /dev/null
+++ b/UVtools.WPF/Assets/Icons/usb-16x16.png
Binary files differ
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index d96b89d..182ee9c 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -30,6 +30,7 @@ using UVtools.Core.FileFormats;
using UVtools.Core.Layers;
using UVtools.Core.Managers;
using UVtools.Core.Network;
+using UVtools.Core.Objects;
using UVtools.Core.Operations;
using UVtools.Core.SystemOS;
using UVtools.WPF.Controls;
@@ -620,27 +621,35 @@ namespace UVtools.WPF
var drives = DriveInfo.GetDrives();
- foreach (var drive in drives)
+ if (drives.Length > 0)
{
- if(drive.DriveType != DriveType.Removable || !drive.IsReady) continue; // Not our target, skip
- if (SlicerFile.FileFullPath.StartsWith(drive.Name)) continue; // File already on this device, skip
-
- var header = drive.Name;
- if (!string.IsNullOrWhiteSpace(drive.VolumeLabel))
+ foreach (var drive in drives)
{
- header += $" {drive.VolumeLabel}";
- }
+ if (drive.DriveType != DriveType.Removable || !drive.IsReady) continue; // Not our target, skip
+ if (SlicerFile.FileFullPath.StartsWith(drive.Name))
+ continue; // File already on this device, skip
- header += $" ({SizeExtensions.SizeSuffix(drive.AvailableFreeSpace)}) [{drive.DriveFormat}]";
+ var header = drive.Name;
+ if (!string.IsNullOrWhiteSpace(drive.VolumeLabel))
+ {
+ header += $" {drive.VolumeLabel}";
+ }
- var menuItem = new MenuItem
- {
- Header = header,
- Tag = drive,
- };
- menuItem.Click += FileSendToItemClick;
+ header += $" ({SizeExtensions.SizeSuffix(drive.AvailableFreeSpace)}) [{drive.DriveFormat}]";
+
+ var menuItem = new MenuItem
+ {
+ Header = header,
+ Tag = drive,
+ Icon = new Image
+ {
+ Source = new Bitmap(App.GetAsset("/Assets/Icons/usb-16x16.png"))
+ }
+ };
+ menuItem.Click += FileSendToItemClick;
- menuItems.Add(menuItem);
+ menuItems.Add(menuItem);
+ }
}
if (Settings.General.SendToCustomLocations is not null && Settings.General.SendToCustomLocations.Count > 0)
@@ -666,6 +675,10 @@ namespace UVtools.WPF
{
Header = location.ToString(),
Tag = location,
+ Icon = new Image
+ {
+ Source = new Bitmap(App.GetAsset("/Assets/Icons/folder-16x16.png"))
+ }
};
menuItem.Click += FileSendToItemClick;
@@ -696,6 +709,44 @@ namespace UVtools.WPF
{
Header = remotePrinter.ToString(),
Tag = remotePrinter,
+ Icon = new Image
+ {
+ Source = new Bitmap(App.GetAsset("/Assets/Icons/network-wired-16x16.png"))
+ }
+ };
+ menuItem.Click += FileSendToItemClick;
+
+ menuItems.Add(menuItem);
+ }
+ }
+
+ if (Settings.General.SendToProcess is not null && Settings.General.SendToProcess.Count > 0)
+ {
+ foreach (var application in Settings.General.SendToProcess)
+ {
+ if (!application.IsEnabled ) continue;
+
+ if (!string.IsNullOrWhiteSpace(application.CompatibleExtensions))
+ {
+ var extensions = application.CompatibleExtensions.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+
+ var found = false;
+ foreach (var ext in extensions)
+ {
+ found = SlicerFile.FileFullPath.EndsWith($".{ext}");
+ if (found) break;
+ }
+ if (!found) continue;
+ }
+
+ var menuItem = new MenuItem
+ {
+ Header = application.Name,
+ Tag = application,
+ Icon = new Image
+ {
+ Source = new Bitmap(App.GetAsset("/Assets/Icons/cog-16x16.png"))
+ }
};
menuItem.Click += FileSendToItemClick;
@@ -735,6 +786,10 @@ namespace UVtools.WPF
{
path = preRemotePrinter.HostUrl;
}
+ else if (menuItem.Tag is MappedProcess process)
+ {
+ path = process.Name;
+ }
else
{
return;
@@ -757,8 +812,8 @@ namespace UVtools.WPF
}
}
- ShowProgressWindow($"Copying: {SlicerFile.Filename} to {path}", true);
- Progress.ItemName = "Copying";
+ ShowProgressWindow($"Sending: {SlicerFile.Filename} to {path}");
+ Progress.ItemName = "Sending";
if (menuItem.Tag is RemotePrinter remotePrinter)
@@ -839,6 +894,20 @@ namespace UVtools.WPF
}
}
}
+ else if (menuItem.Tag is MappedProcess process)
+ {
+ Progress.ItemName = "Waiting for completion";
+ try
+ {
+ await process.StartProcess(SlicerFile, Progress.Token);
+ }
+ catch (OperationCanceledException){}
+ catch (Exception ex)
+ {
+ await this.MessageBoxError(ex.Message, $"Unable to start the process {process.Name}");
+ }
+
+ }
else
{
/*var copyResult = await Task.Factory.StartNew(() =>
@@ -914,7 +983,7 @@ namespace UVtools.WPF
}
catch (Exception exception)
{
- await this.MessageBoxError(exception.ToString(), "Unable to copy the file");
+ await this.MessageBoxError(exception.Message, "Unable to copy the file");
}
if(copyResult && menuItem.Tag is DriveInfo removableDrive && OperatingSystem.IsWindows() && Settings.General.SendToPromptForRemovableDeviceEject)
@@ -934,7 +1003,7 @@ namespace UVtools.WPF
catch (Exception exception)
{
Dispatcher.UIThread.InvokeAsync(async () =>
- await this.MessageBoxError(exception.ToString(), $"Unable to eject the drive {removableDrive.Name}"));
+ await this.MessageBoxError(exception.Message, $"Unable to eject the drive {removableDrive.Name}"));
}
return false;
@@ -1891,7 +1960,7 @@ namespace UVtools.WPF
}
Dispatcher.UIThread.InvokeAsync(async () =>
- await this.MessageBoxError($"Convertion was not successful! Maybe not implemented...\n{extraMessage}{ex}", "Convertion unsuccessful"));
+ await this.MessageBoxError($"{extraMessage}{ex}", "Convertion unsuccessful"));
}
return false;
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index 7b76ea0..e04e08c 100644
--- a/UVtools.WPF/UVtools.WPF.csproj
+++ b/UVtools.WPF/UVtools.WPF.csproj
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
- <Version>2.25.2</Version>
+ <Version>2.25.3</Version>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
@@ -40,7 +40,7 @@
<PackageReference Include="Avalonia.Desktop" Version="0.10.8" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.8" />
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.4.4788" />
- <PackageReference Include="MessageBox.Avalonia" Version="1.5.5" />
+ <PackageReference Include="MessageBox.Avalonia" Version="1.6.0" />
<PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.8" />
</ItemGroup>
<ItemGroup>
diff --git a/UVtools.WPF/UserSettings.cs b/UVtools.WPF/UserSettings.cs
index 7332940..9532110 100644
--- a/UVtools.WPF/UserSettings.cs
+++ b/UVtools.WPF/UserSettings.cs
@@ -7,6 +7,7 @@
*/
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
@@ -15,6 +16,7 @@ using Avalonia.Media;
using JetBrains.Annotations;
using UVtools.Core;
using UVtools.Core.Extensions;
+using UVtools.Core.FileFormats;
using UVtools.Core.Network;
using UVtools.Core.Objects;
using Color=UVtools.WPF.Structures.Color;
@@ -56,6 +58,7 @@ namespace UVtools.WPF
private string _fileSaveNameSuffix = "_copy";
private bool _sendToPromptForRemovableDeviceEject = true;
private RangeObservableCollection<MappedDevice> _sendToCustomLocations = new();
+ private RangeObservableCollection<MappedProcess> _sendToProcess = new();
public bool StartMaximized
@@ -188,6 +191,12 @@ namespace UVtools.WPF
set => RaiseAndSetIfChanged(ref _sendToCustomLocations, value);
}
+ public RangeObservableCollection<MappedProcess> SendToProcess
+ {
+ get => _sendToProcess;
+ set => RaiseAndSetIfChanged(ref _sendToProcess, value);
+ }
+
public GeneralUserSettings() { }
public GeneralUserSettings Clone()
@@ -1717,6 +1726,175 @@ namespace UVtools.WPF
}*/
});
}
+
+ if (_instance.General.SendToProcess.Count == 0)
+ {
+ if (OperatingSystem.IsWindows())
+ {
+ var findDirectories = new List<string>
+ {
+ Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)
+ };
+ if (Environment.Is64BitOperatingSystem)
+ {
+ findDirectories.Add(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86));
+ }
+
+ foreach (var path in findDirectories)
+ {
+ var directories = Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles));
+ foreach (var directory in directories)
+ {
+ /*if (directory.StartsWith($"{path}\\Prusa3D", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var executable = $"{directory}\\PrusaSlicer\\prusa-slicer.exe";
+ if (File.Exists(executable))
+ {
+ var application = new MappedApplication(executable, "Slicer: PrusaSlicer");
+ foreach (var slicerFile in FileFormat.AvailableFormats)
+ {
+ if (slicerFile is not SL1File) continue;
+ application.CompatibleExtensions += slicerFile.GetFileExtensions(string.Empty, ";");
+ }
+
+ _instance.General.SendToApplications.Add(application);
+ }
+
+ continue;
+ }*/
+
+ if (directory.StartsWith($"{path}\\Chitubox", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var executable = $"{directory}\\CHITUBOX.exe";
+ //var executablePro = $"{directory}\\CHITUBOXPro.exe";
+ if (File.Exists(executable))
+ {
+ _instance.General.SendToProcess.Add(new MappedProcess(executable, "Slicer: Chitubox")
+ {
+ CompatibleExtensions = "cbddlp;ctb;phz;photon;photons;fdg"
+ });
+ }
+ /*else if (File.Exists(executablePro))
+ {
+ _instance.General.SendToApplications.Add(new MappedApplication(executablePro, "Slicer: Chitubox Pro")
+ {
+ CompatibleExtensions = "cbddlp;ctb;phz;photon;photons;fdg"
+ });
+ }*/
+ continue;
+ }
+
+ if (directory.StartsWith($"{path}\\Photon_WorkShop", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var directoryName = Path.GetFileName(directory);
+ var executable = $"{directory}\\{directoryName}.exe";
+ if (File.Exists(executable))
+ {
+ var application = new MappedProcess(executable, $"Slicer: {directoryName.Replace('_', ' ')}")
+ {
+ CompatibleExtensions = "photon;photons;"
+ };
+ foreach (var slicerFile in FileFormat.AvailableFormats)
+ {
+ if (slicerFile is not PhotonWorkshopFile) continue;
+ application.CompatibleExtensions += slicerFile.GetFileExtensions(string.Empty, ";");
+ }
+
+
+ _instance.General.SendToProcess.Add(application);
+ }
+ continue;
+ }
+
+ if (directory.StartsWith($"{path}\\UNIZ", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var executable = $"{directory}\\UnizMaker\\UnizMaker.exe";
+ if (File.Exists(executable))
+ {
+ _instance.General.SendToProcess.Add(new MappedProcess(executable, "Slicer: UnizMaker")
+ {
+ CompatibleExtensions = "zcode"
+ });
+ }
+ continue;
+ }
+
+ if (directory.StartsWith($"{path}\\Zortrax", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var executable = $"{directory}\\Z-Suite\\Z-SUITE.exe";
+ if (File.Exists(executable))
+ {
+ _instance.General.SendToProcess.Add(new MappedProcess(executable, "Slicer: Z-SUITE")
+ {
+ CompatibleExtensions = "zcodex"
+ });
+ }
+ continue;
+ }
+
+ if (directory.StartsWith($"{path}\\WinRAR", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var executable = $"{directory}\\WinRAR.exe";
+ if (File.Exists(executable))
+ {
+ var application = new MappedProcess(executable, "Open archive: WinRAR")
+ {
+ CompatibleExtensions = "zip;sl1;sl1s;cws;zcode;zcodex;vdt;uvt"
+ };
+ _instance.General.SendToProcess.Add(application);
+ }
+
+ continue;
+ }
+
+ if (directory.StartsWith($"{path}\\7-Zip", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var executable = $"{directory}\\7zFM.exe";
+ if (File.Exists(executable))
+ {
+ var application = new MappedProcess(executable, "Open archive: 7-Zip")
+ {
+ CompatibleExtensions = "zip;sl1;sl1s;cws;zcode;zcodex;vdt;uvt"
+ };
+ _instance.General.SendToProcess.Add(application);
+ }
+
+ continue;
+ }
+
+
+ if (directory.StartsWith($"{path}\\010 Editor", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var executable = $"{directory}\\010Editor.exe";
+ if (File.Exists(executable))
+ {
+ var application = new MappedProcess(true, executable, "Hex editor: 010");
+ _instance.General.SendToProcess.Add(application);
+ }
+
+ continue;
+ }
+
+ if (directory.StartsWith($"{path}\\HxD", StringComparison.InvariantCultureIgnoreCase))
+ {
+ var executable = $"{directory}\\HxD.exe";
+ if (File.Exists(executable))
+ {
+ var application = new MappedProcess(false, executable, "Hex editor: HxD");
+ _instance.General.SendToProcess.Add(application);
+ }
+
+ continue;
+ }
+ }
+ }
+
+ if (_instance.General.SendToProcess.Count > 0)
+ {
+ _instance.General.SendToProcess.Sort((process, mappedProcess) => string.Compare(process.Name, mappedProcess.Name, StringComparison.Ordinal));
+ }
+ }
+ }
}
catch (Exception e)
{
diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml b/UVtools.WPF/Windows/SettingsWindow.axaml
index ad97d67..93de17a 100644
--- a/UVtools.WPF/Windows/SettingsWindow.axaml
+++ b/UVtools.WPF/Windows/SettingsWindow.axaml
@@ -332,7 +332,7 @@
<Grid RowDefinitions="Auto" ColumnDefinitions="*,Auto" Background="LightBlue">
<TextBlock Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
- Padding="10" FontWeight="Bold" Text="Send to - Custom locations"/>
+ Padding="10" FontWeight="Bold" Text="Send to - Custom location"/>
<StackPanel Grid.Row="0" Grid.Column="1"
HorizontalAlignment="Right" Orientation="Horizontal" Spacing="2">
@@ -363,6 +363,7 @@
CanUserSortColumns="True"
GridLinesVisibility="Horizontal"
IsReadOnly="False"
+ MinHeight="100"
SelectionMode="Extended"
ClipboardCopyMode="IncludeHeader"
Items="{Binding Settings.General.SendToCustomLocations}">
@@ -391,6 +392,81 @@
</StackPanel>
</Border>
+ <Border
+ Classes="GroupBox"
+ Margin="5">
+
+ <StackPanel Orientation="Vertical">
+ <Grid RowDefinitions="Auto" ColumnDefinitions="*,Auto" Background="LightBlue">
+ <TextBlock Grid.Row="0" Grid.Column="0"
+ ToolTip.Tip="Allow to open a new process with arguments and pass the current file.&#x0a;
+&#x0a;Wait exit: Interrupt the UI and wait for process completion/exit.
+&#x0a;Arguments: Use &quot;{0}&quot; to indicate the current loaded file path, when empty, it will pass &quot;{0}&quot; by default."
+ VerticalAlignment="Center"
+ Padding="10" FontWeight="Bold" Text="Send to - Process"/>
+
+ <StackPanel Grid.Row="0" Grid.Column="1"
+ HorizontalAlignment="Right" Orientation="Horizontal" Spacing="2">
+ <Button ToolTip.Tip="Add location" VerticalAlignment="Center"
+ Command="{Binding SendToAddProcess}">
+ <Image Source="/Assets/Icons/plus-16x16.png"/>
+ </Button>
+
+ <Button ToolTip.Tip="Remove selected process(es)" VerticalAlignment="Center"
+ IsEnabled="{Binding #SendToProcessGrid.SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}"
+ Command="{Binding SendToRemoveProcess}">
+ <Image Source="/Assets/Icons/trash-16x16.png"/>
+ </Button>
+ </StackPanel>
+
+ </Grid>
+
+ <StackPanel Margin="10" Orientation="Vertical" Spacing="10">
+
+ <DataGrid
+ Name="SendToProcessGrid"
+ CanUserReorderColumns="True"
+ CanUserResizeColumns="True"
+ CanUserSortColumns="True"
+ GridLinesVisibility="Horizontal"
+ IsReadOnly="False"
+ SelectionMode="Extended"
+ ClipboardCopyMode="IncludeHeader"
+ MinHeight="100"
+ Items="{Binding Settings.General.SendToProcess}">
+ <DataGrid.Columns>
+ <DataGridCheckBoxColumn Header="Enabled"
+ Binding="{Binding IsEnabled}"
+ IsReadOnly="False"
+ Width="Auto" />
+ <DataGridCheckBoxColumn Header="Wait exit"
+ Binding="{Binding WaitForExit}"
+ IsReadOnly="False"
+ Width="Auto" />
+ <DataGridTextColumn Header="Alias name"
+ Binding="{Binding Name}"
+ IsReadOnly="False"
+ Width="150" />
+ <DataGridTextColumn Header="Process path"
+ Binding="{Binding ApplicationPath}"
+ IsReadOnly="True"
+ Width="*" />
+ <DataGridTextColumn Header="Arguments"
+ Binding="{Binding Arguments}"
+ IsReadOnly="False"
+ Width="110" />
+ <DataGridTextColumn Header="Extensions"
+ Binding="{Binding CompatibleExtensions}"
+ IsReadOnly="False"
+ Width="150" />
+ </DataGrid.Columns>
+
+ </DataGrid>
+ </StackPanel>
+
+ </StackPanel>
+ </Border>
+
</StackPanel>
</ScrollViewer>
diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml.cs b/UVtools.WPF/Windows/SettingsWindow.axaml.cs
index 8f61d2c..e4e3675 100644
--- a/UVtools.WPF/Windows/SettingsWindow.axaml.cs
+++ b/UVtools.WPF/Windows/SettingsWindow.axaml.cs
@@ -10,6 +10,7 @@ using Avalonia.Threading;
using MessageBox.Avalonia.Enums;
using UVtools.Core.FileFormats;
using UVtools.Core.Network;
+using UVtools.Core.Objects;
using UVtools.WPF.Controls;
using UVtools.WPF.Extensions;
using Color = UVtools.WPF.Structures.Color;
@@ -21,6 +22,7 @@ namespace UVtools.WPF.Windows
private double _scrollViewerMaxHeight;
private int _selectedTabIndex;
private DataGrid _sendToCustomLocationsGrid;
+ private DataGrid _sendToProcessGrid;
private ComboBox _networkRemotePrinterComboBox;
public int MaxProcessorCount => Environment.ProcessorCount;
@@ -83,6 +85,7 @@ namespace UVtools.WPF.Windows
InitializeComponent();
_sendToCustomLocationsGrid = this.FindControl<DataGrid>("SendToCustomLocationsGrid");
+ _sendToProcessGrid = this.FindControl<DataGrid>("SendToProcessGrid");
_networkRemotePrinterComboBox = this.FindControl<ComboBox>("NetworkRemotePrinterComboBox");
}
@@ -202,6 +205,34 @@ namespace UVtools.WPF.Windows
Settings.General.SendToCustomLocations.RemoveRange(_sendToCustomLocationsGrid.SelectedItems.Cast<MappedDevice>());
}
+ public async void SendToAddProcess()
+ {
+ var openFolder = new OpenFileDialog();
+ var result = await openFolder.ShowAsync(this);
+
+ if (result is null || result.Length == 0) return;
+ var file = new MappedProcess(result[0]);
+ if (Settings.General.SendToProcess.Contains(file))
+ {
+ await this.MessageBoxError("The selected process already exists on the list:\n" +
+ $"{result}");
+ return;
+ }
+
+ Settings.General.SendToProcess.Add(file);
+ }
+
+ public async void SendToRemoveProcess()
+ {
+ if (_sendToProcessGrid.SelectedItems.Count == 0) return;
+
+ if (await this.MessageBoxQuestion(
+ $"Are you sure you want to remove the {_sendToProcessGrid.SelectedItems.Count} selected entries?") !=
+ ButtonResult.Yes) return;
+
+ Settings.General.SendToProcess.RemoveRange(_sendToProcessGrid.SelectedItems.Cast<MappedProcess>());
+ }
+
public async void SelectColor(string property)
{
foreach (var packObject in UserSettings.PackObjects)
diff --git a/build/CreateRelease.WPF.ps1 b/build/CreateRelease.WPF.ps1
index 9fd1628..ed1ced5 100644
--- a/build/CreateRelease.WPF.ps1
+++ b/build/CreateRelease.WPF.ps1
@@ -36,7 +36,7 @@ $enableMSI = $true
#$buildOnly = 'win-x64'
#$buildOnly = 'linux-x64'
#$buildOnly = 'osx-x64'
-#$enableNugetPublish = $true
+$enableNugetPublish = $true
# Profilling
$stopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
$deployStopWatch = New-Object -TypeName System.Diagnostics.Stopwatch