2024-09-08 22:37:06 +02:00
|
|
|
using Gtk;
|
|
|
|
using Adw;
|
|
|
|
using System.Text;
|
2024-09-14 17:49:20 +02:00
|
|
|
using GLib;
|
2024-09-08 22:37:06 +02:00
|
|
|
|
|
|
|
namespace Photomator.Views;
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
public partial class MainWindow : Adw.ApplicationWindow {
|
2024-09-08 22:37:06 +02:00
|
|
|
private readonly Adw.Application _application;
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
public MainWindow(Adw.Application application) : base() {
|
2024-09-08 22:37:06 +02:00
|
|
|
_application = application;
|
|
|
|
|
|
|
|
SetTitle(AppInfo.ApplicationName);
|
|
|
|
SetIconName(AppInfo.IconName);
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
PreferencesPage pageSingle = InitPageSingle();
|
|
|
|
PreferencesPage pageFolder = InitPageFolder();
|
2024-09-08 22:37:06 +02:00
|
|
|
|
|
|
|
ViewStack viewStack = ViewStack.New();
|
2024-09-14 17:49:20 +02:00
|
|
|
viewStack.AddTitledWithIcon(pageSingle, "page-single", "Einzelne Datei", "image-x-generic-symbolic");
|
|
|
|
viewStack.AddTitledWithIcon(pageFolder, "page-folder", "Ordner", "folder-symbolic");
|
2024-09-08 22:37:06 +02:00
|
|
|
|
|
|
|
ViewSwitcher viewSwitcher = ViewSwitcher.New();
|
|
|
|
viewSwitcher.SetStack(viewStack);
|
|
|
|
viewSwitcher.SetPolicy(ViewSwitcherPolicy.Wide);
|
|
|
|
|
|
|
|
SetDefaultSize(600, 800);
|
|
|
|
|
|
|
|
Adw.AboutDialog aboutDialog = InitAboutDialog();
|
|
|
|
|
|
|
|
Adw.HeaderBar headerBar = Adw.HeaderBar.New();
|
|
|
|
Button btnAbout = Button.NewFromIconName("help-about-symbolic");
|
|
|
|
btnAbout.OnClicked += (_, _) => aboutDialog.Present(this);
|
|
|
|
headerBar.SetTitleWidget(viewSwitcher);
|
|
|
|
headerBar.PackEnd(btnAbout);
|
|
|
|
|
|
|
|
ToolbarView view = ToolbarView.New();
|
|
|
|
view.AddTopBar(headerBar);
|
|
|
|
|
|
|
|
view.SetContent(viewStack);
|
|
|
|
|
|
|
|
SetContent(view);
|
|
|
|
}
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
public void Start() {
|
2024-09-08 22:37:06 +02:00
|
|
|
_application.AddWindow(this);
|
|
|
|
Present();
|
|
|
|
}
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
public PreferencesPage InitPageSingle() {
|
2024-09-08 22:37:06 +02:00
|
|
|
PreferencesPage page = PreferencesPage.New();
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
PreferencesGroup pgSource = PreferencesGroup.New();
|
|
|
|
pgSource.SetTitle("Bild");
|
|
|
|
pgSource.SetDescription("Als Eingabeformate werden BMP, GIF, JPEG, PBM, PNG, TIFF, TGA und WebP unterstützt.");
|
|
|
|
EntryRow erSource = EntryRow.New();
|
|
|
|
erSource.SetTitle("Zu konvertierendes Bild");
|
|
|
|
erSource.SetEditable(false);
|
2024-09-08 22:37:06 +02:00
|
|
|
|
|
|
|
PreferencesGroup pgOptions = PreferencesGroup.New();
|
|
|
|
pgOptions.SetTitle("Optionen");
|
|
|
|
pgOptions.SetDescription("Diese Parameter beeinflussen die Qualität und Größe der Bilder.");
|
|
|
|
|
|
|
|
ComboRow crRes = ComboRow.New();
|
|
|
|
crRes.SetTitle("Auflösung");
|
|
|
|
crRes.SetSubtitle("Länge der kurzen Seite in Pixel");
|
|
|
|
StringList resOptions = StringList.New(["720", "1080", "1440", "2160"]);
|
|
|
|
crRes.SetModel(resOptions);
|
|
|
|
crRes.SetSelected(2);
|
|
|
|
pgOptions.Add(crRes);
|
|
|
|
|
|
|
|
ComboRow crFormat = ComboRow.New();
|
|
|
|
crFormat.SetTitle("Konvertierungsart");
|
|
|
|
crFormat.SetModel(StringList.New(["Verlustbehaftet", "Verlustfrei"]));
|
|
|
|
crFormat.SetSelected(0);
|
|
|
|
pgOptions.Add(crFormat);
|
|
|
|
|
|
|
|
PreferencesGroup pgBtn = PreferencesGroup.New();
|
|
|
|
pgBtn.SetValign(Align.Center);
|
|
|
|
pgBtn.SetHalign(Align.Center);
|
|
|
|
Button btnConvert = Button.NewWithLabel("Konvertieren");
|
2024-09-14 17:49:20 +02:00
|
|
|
btnConvert.OnClicked += async (_, _) => {
|
2024-09-08 22:37:06 +02:00
|
|
|
FileDialog fileDialog = FileDialog.New();
|
|
|
|
Gio.ListStore listStore = Gio.ListStore.New(FileFilter.GetGType());
|
|
|
|
FileFilter filter = FileFilter.New();
|
|
|
|
filter.SetName("WebP (*.webp)");
|
|
|
|
filter.AddPattern("*.webp");
|
|
|
|
filter.AddPattern("*.WEBP");
|
|
|
|
listStore.Append(filter);
|
|
|
|
fileDialog.SetFilters(listStore);
|
|
|
|
Gio.File? file;
|
2024-09-14 17:49:20 +02:00
|
|
|
try {
|
2024-09-08 22:37:06 +02:00
|
|
|
file = await fileDialog.SaveAsync(this);
|
2024-09-14 17:49:20 +02:00
|
|
|
} catch {
|
2024-09-08 22:37:06 +02:00
|
|
|
file = null;
|
|
|
|
}
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
if (file != null && file.GetPath() != null) {
|
2024-09-08 22:37:06 +02:00
|
|
|
ConvertOptions options = new(resOptions.GetString(crRes.GetSelected()), crFormat.GetSelected());
|
2024-09-14 17:49:20 +02:00
|
|
|
await Lib.Convert(erSource.GetText(), file.GetPath()!, options);
|
|
|
|
} else
|
2024-09-08 22:37:06 +02:00
|
|
|
InitInfoAlert("Kein Ziel ausgewählt", "Es wurde keine Zieldatei ausgewählt. Konvertierung wird abgebrochen.");
|
|
|
|
};
|
|
|
|
btnConvert.SetCssClasses(["pill", "suggested-action", "long"]);
|
|
|
|
btnConvert.SetSensitive(false);
|
|
|
|
pgBtn.Add(btnConvert);
|
|
|
|
|
|
|
|
Button btnSelect = Button.New();
|
|
|
|
btnSelect.SetValign(Align.Center);
|
|
|
|
btnSelect.AddCssClass("flat");
|
|
|
|
btnSelect.SetIconName("document-open-symbolic");
|
2024-09-14 17:49:20 +02:00
|
|
|
btnSelect.OnClicked += async (_, _) => {
|
2024-09-08 22:37:06 +02:00
|
|
|
FileDialog fileDialog = FileDialog.New();
|
2024-09-14 17:49:20 +02:00
|
|
|
fileDialog.SetFilters(GetSourceFileFilter());
|
2024-09-08 22:37:06 +02:00
|
|
|
Gio.File? file;
|
2024-09-14 17:49:20 +02:00
|
|
|
try {
|
2024-09-08 22:37:06 +02:00
|
|
|
file = await fileDialog.OpenAsync(this);
|
2024-09-14 17:49:20 +02:00
|
|
|
} catch {
|
2024-09-08 22:37:06 +02:00
|
|
|
file = null;
|
|
|
|
}
|
2024-09-14 17:49:20 +02:00
|
|
|
if (file != null && file.GetPath() != null) {
|
|
|
|
erSource.SetText(file.GetPath()!);
|
2024-09-08 22:37:06 +02:00
|
|
|
btnConvert.SetSensitive(true);
|
2024-09-14 17:49:20 +02:00
|
|
|
} else if (erSource.GetText() == "")
|
2024-09-08 22:37:06 +02:00
|
|
|
btnConvert.SetSensitive(false);
|
|
|
|
};
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
erSource.AddSuffix(btnSelect);
|
|
|
|
pgSource.Add(erSource);
|
2024-09-08 22:37:06 +02:00
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
page.Add(pgSource);
|
2024-09-08 22:37:06 +02:00
|
|
|
page.Add(pgOptions);
|
|
|
|
page.Add(pgBtn);
|
|
|
|
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
public PreferencesPage InitPageFolder() {
|
2024-09-08 22:37:06 +02:00
|
|
|
EntryRow erSource = EntryRow.New();
|
|
|
|
erSource.SetTitle("Quellordner");
|
|
|
|
erSource.SetEditable(false);
|
|
|
|
|
|
|
|
EntryRow erDest = EntryRow.New();
|
|
|
|
erDest.SetTitle("Zielordner");
|
|
|
|
erDest.SetEditable(false);
|
|
|
|
|
|
|
|
PreferencesGroup pgOptions = PreferencesGroup.New();
|
|
|
|
pgOptions.SetTitle("Optionen");
|
|
|
|
pgOptions.SetDescription("Diese Parameter beeinflussen die Qualität und Größe der Bilder.");
|
|
|
|
|
|
|
|
ComboRow crRes = ComboRow.New();
|
|
|
|
crRes.SetTitle("Auflösung");
|
|
|
|
crRes.SetSubtitle("Länge der kurzen Seite in Pixel");
|
|
|
|
StringList resOptions = StringList.New(["720", "1080", "1440", "2160"]);
|
|
|
|
crRes.SetModel(resOptions);
|
|
|
|
crRes.SetSelected(2);
|
|
|
|
pgOptions.Add(crRes);
|
|
|
|
|
|
|
|
ComboRow crFormat = ComboRow.New();
|
|
|
|
crFormat.SetTitle("Konvertierungsart");
|
|
|
|
crFormat.SetModel(StringList.New(["Verlustbehaftet", "Verlustfrei"]));
|
|
|
|
crFormat.SetSelected(0);
|
|
|
|
pgOptions.Add(crFormat);
|
|
|
|
|
|
|
|
PreferencesGroup pgBtn = PreferencesGroup.New();
|
|
|
|
pgBtn.SetValign(Align.Center);
|
|
|
|
pgBtn.SetHalign(Align.Center);
|
|
|
|
Button btnConvert = Button.NewWithLabel("Konvertieren");
|
2024-09-14 17:49:20 +02:00
|
|
|
btnConvert.OnClicked += async (_, _) => {
|
|
|
|
string[] filesSource;
|
|
|
|
if (Directory.Exists(erSource.GetText()))
|
|
|
|
filesSource = Directory.GetFiles(erSource.GetText());
|
|
|
|
else {
|
|
|
|
InitInfoAlert("Quellordner existiert nicht", "Der ausgewählte Quellordner ist nicht im Dateisystem vorhanden. Die Konvertierung wurde abgebrochen.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (filesSource.Length == 0) {
|
|
|
|
InitInfoAlert("Quellordner ist leer", "Im ausgewählten Quellordner befinden sich keine Dateien. Die Konvertierung wurde abgebrochen.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
string dest = erDest.GetText();
|
|
|
|
Directory.CreateDirectory(dest);
|
|
|
|
StatusDialog statusDialog = new(_application, this);
|
|
|
|
statusDialog.Start();
|
|
|
|
try {
|
|
|
|
ConvertOptions options = new(resOptions.GetString(crRes.GetSelected()), crFormat.GetSelected());
|
|
|
|
ConvertError[] convertErrors = await Lib.ConvertList(filesSource, dest, options, statusDialog.SetProgress);
|
|
|
|
if (convertErrors.Length > 0)
|
|
|
|
statusDialog.Partial(filesSource.Length, dest, convertErrors);
|
2024-09-08 22:37:06 +02:00
|
|
|
else
|
2024-09-14 17:49:20 +02:00
|
|
|
statusDialog.Success(filesSource.Length, dest);
|
|
|
|
} catch (Exception e) {
|
|
|
|
statusDialog.Error(e.Message);
|
2024-09-08 22:37:06 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
btnConvert.SetCssClasses(["pill", "suggested-action", "long"]);
|
|
|
|
btnConvert.SetSensitive(false);
|
|
|
|
pgBtn.Add(btnConvert);
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
void checkButtonState() {
|
2024-09-08 22:37:06 +02:00
|
|
|
if (erSource.GetText() != "" && erDest.GetText() != "") btnConvert.SetSensitive(true);
|
|
|
|
else btnConvert.SetSensitive(false);
|
|
|
|
}
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
erSource.AddSuffix(InitButtonSelectFolder(erSource, checkButtonState));
|
|
|
|
erDest.AddSuffix(InitButtonSelectFolder(erDest, checkButtonState));
|
2024-09-08 22:37:06 +02:00
|
|
|
|
|
|
|
PreferencesPage page = PreferencesPage.New();
|
|
|
|
|
|
|
|
PreferencesGroup pgFolders = PreferencesGroup.New();
|
|
|
|
pgFolders.SetTitle("Ordner");
|
|
|
|
pgFolders.SetDescription("Wähle einen Quell- und einen Zielordner. Es werden alle Dateien im Ordner konvertiert, jedoch keine Unterordner.");
|
|
|
|
pgFolders.Add(erSource);
|
|
|
|
pgFolders.Add(erDest);
|
|
|
|
page.Add(pgFolders);
|
|
|
|
page.Add(pgOptions);
|
|
|
|
page.Add(pgBtn);
|
|
|
|
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
public void InitInfoAlert(string title, string body) {
|
2024-09-08 22:37:06 +02:00
|
|
|
Adw.AlertDialog alert = Adw.AlertDialog.New(title, body);
|
|
|
|
alert.AddResponse("ok", "OK");
|
|
|
|
alert.SetResponseAppearance("ok", ResponseAppearance.Suggested);
|
|
|
|
alert.SetDefaultResponse("ok");
|
|
|
|
alert.SetCloseResponse("ok");
|
|
|
|
alert.Present(this);
|
|
|
|
}
|
|
|
|
|
2024-09-14 17:49:20 +02:00
|
|
|
public static Adw.AboutDialog InitAboutDialog() {
|
2024-09-08 22:37:06 +02:00
|
|
|
Adw.AboutDialog aboutDialog = Adw.AboutDialog.New();
|
|
|
|
aboutDialog.SetApplicationName(AppInfo.ApplicationName);
|
|
|
|
aboutDialog.SetDeveloperName(AppInfo.DeveloperName);
|
|
|
|
aboutDialog.SetApplicationIcon(AppInfo.IconName);
|
|
|
|
aboutDialog.SetCopyright(AppInfo.Copyright);
|
|
|
|
aboutDialog.SetIssueUrl(AppInfo.IssueUrl);
|
|
|
|
aboutDialog.SetWebsite(AppInfo.Website);
|
|
|
|
aboutDialog.SetReleaseNotes(AppInfo.ReleaseNotes);
|
|
|
|
aboutDialog.SetVersion(AppInfo.Version);
|
|
|
|
aboutDialog.SetLicenseType(License.MitX11);
|
|
|
|
|
|
|
|
return aboutDialog;
|
|
|
|
}
|
2024-09-14 17:49:20 +02:00
|
|
|
|
|
|
|
public Button InitButtonSelectFolder(EntryRow entryRow, VoidFunc checkButtonState) {
|
|
|
|
Button btnSelect = Button.New();
|
|
|
|
btnSelect.SetValign(Align.Center);
|
|
|
|
btnSelect.AddCssClass("flat");
|
|
|
|
btnSelect.SetIconName("document-open-symbolic");
|
|
|
|
btnSelect.OnClicked += async (_, _) => {
|
|
|
|
FileDialog fileDialog = FileDialog.New();
|
|
|
|
Gio.File? file;
|
|
|
|
try {
|
|
|
|
file = await fileDialog.SelectFolderAsync(this);
|
|
|
|
} catch {
|
|
|
|
file = null;
|
|
|
|
}
|
|
|
|
if (file != null && file.GetPath() != null)
|
|
|
|
entryRow.SetText(file.GetPath()!);
|
|
|
|
checkButtonState();
|
|
|
|
};
|
|
|
|
|
|
|
|
return btnSelect;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Gio.ListStore GetSourceFileFilter() {
|
|
|
|
Gio.ListStore listStore = Gio.ListStore.New(FileFilter.GetGType());
|
|
|
|
FileFilter filterAll = FileFilter.New();
|
|
|
|
filterAll.SetName("Alle unterstützten Bildformate");
|
|
|
|
string[][] formats = [["bmp", "dib"], ["gif"], ["jpeg", "jpg", "jpe", "jfif"], ["pbm"], ["png"], ["tiff", "tif"], ["tga", "bpx", "icb", "pix"], ["webp"]];
|
|
|
|
foreach (string[] format in formats) {
|
|
|
|
FileFilter filter = FileFilter.New();
|
|
|
|
StringBuilder name = new($"{format[0].ToUpper()} (");
|
|
|
|
for (int i = 0; i < format.Length; i++) {
|
|
|
|
name.Append($"*.{format[i]}");
|
|
|
|
if (i != format.Length - 1)
|
|
|
|
name.Append(", ");
|
|
|
|
filter.AddPattern($"*.{format[i]}");
|
|
|
|
filterAll.AddPattern($"*.{format[i]}");
|
|
|
|
filter.AddPattern($"*.{format[i].ToUpper()}");
|
|
|
|
filterAll.AddPattern($"*.{format[i].ToUpper()}");
|
|
|
|
}
|
|
|
|
name.Append(')');
|
|
|
|
filter.SetName(name.ToString());
|
|
|
|
listStore.Append(filter);
|
|
|
|
}
|
|
|
|
listStore.Insert(0, filterAll);
|
|
|
|
|
|
|
|
return listStore;
|
|
|
|
}
|
2024-09-08 22:37:06 +02:00
|
|
|
}
|