summaryrefslogtreecommitdiff
path: root/src/ProfileBrowser.vala
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff.email>2023-06-28 21:35:52 +0200
committerJörg Frings-Fürst <debian@jff.email>2023-06-28 21:35:52 +0200
commitb86540b743f1a87a163ffb811c8fe22a01fefa38 (patch)
treeb47cb3bb83c2377234226fb3987ab3320a987dd9 /src/ProfileBrowser.vala
parentac6e0b731b9f0b2efd392e3309a5c07e2a66adad (diff)
parente905d8e16eec152d19797937f13ba3cf4b8f8aca (diff)
Merge branch 'release/debian/0.32.1-1'debian/0.32.1-1
Diffstat (limited to 'src/ProfileBrowser.vala')
-rw-r--r--src/ProfileBrowser.vala294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/ProfileBrowser.vala b/src/ProfileBrowser.vala
new file mode 100644
index 0000000..4532a20
--- /dev/null
+++ b/src/ProfileBrowser.vala
@@ -0,0 +1,294 @@
+// SPDX-FileCopyrightText: Jens Georg <mail@jensge.org>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+namespace Shotwell {
+ class ProfileEditor : Gtk.Dialog {
+ public string profile_name {get; set;}
+ public string id{get; default = Uuid.string_random();}
+ public string library_folder{get; set;}
+ public string data_folder{get; set;}
+
+ public ProfileEditor() {
+ Object(use_header_bar : Resources.use_header_bar());
+ }
+
+ public override void constructed() {
+ base.constructed();
+
+ set_size_request(640, -1);
+
+ add_buttons(_("Create"), Gtk.ResponseType.OK, _("Cancel"), Gtk.ResponseType.CANCEL, null);
+ var create_button = get_widget_for_response(Gtk.ResponseType.OK);
+ create_button.get_style_context().add_class("suggested-action");
+ create_button.sensitive = false;
+ set_title(_("Create new Profile"));
+
+ data_folder = Path.build_filename(Environment.get_user_data_dir(), "shotwell", "profiles", id);
+ library_folder = Environment.get_user_special_dir(UserDirectory.PICTURES);
+
+ var grid = new Gtk.Grid();
+ grid.hexpand = true;
+ grid.vexpand = true;
+ grid.margin = 6;
+ grid.set_row_spacing(12);
+ grid.set_column_spacing(12);
+ var label = new Gtk.Label(_("Name"));
+ label.get_style_context().add_class("dim-label");
+ label.halign = Gtk.Align.END;
+ grid.attach(label, 0, 0, 1, 1);
+
+ var entry = new Gtk.Entry();
+ entry.hexpand = true;
+ entry.bind_property("text", this, "profile-name", GLib.BindingFlags.DEFAULT);
+ entry.bind_property("text", create_button, "sensitive", GLib.BindingFlags.DEFAULT, (binding, from, ref to) => {
+ to = from.get_string() != "";
+ return true;
+ });
+ grid.attach(entry, 1, 0, 2, 1);
+
+ label = new Gtk.Label(_("Library Folder"));
+ label.get_style_context().add_class("dim-label");
+ label.halign = Gtk.Align.END;
+ grid.attach(label, 0, 1, 1, 1);
+
+ entry = new Gtk.Entry();
+ entry.hexpand = true;
+ grid.attach(entry, 1, 1, 1, 1);
+ bind_property("library-folder", entry, "text", GLib.BindingFlags.SYNC_CREATE | GLib.BindingFlags.BIDIRECTIONAL);
+ entry.bind_property("text", create_button, "sensitive", GLib.BindingFlags.DEFAULT, (binding, from, ref to) => {
+ to = from.get_string() != "";
+ return true;
+ });
+
+ var button = new Gtk.Button.from_icon_name("folder-symbolic", Gtk.IconSize.BUTTON);
+ button.hexpand = false;
+ button.vexpand = false;
+ button.halign = Gtk.Align.FILL;
+ button.clicked.connect(() => {
+ var dialog = new Gtk.FileChooserNative(_("Choose Library Folder"), this, Gtk.FileChooserAction.SELECT_FOLDER, _("_OK"), _("_Cancel"));
+ dialog.set_current_folder(library_folder);
+ var result = dialog.run();
+ dialog.hide();
+ if (result == Gtk.ResponseType.ACCEPT) {
+ library_folder = dialog.get_current_folder_file().get_path();
+ }
+ dialog.destroy();
+ });
+ grid.attach(button, 2, 1, 1, 1);
+
+
+ label = new Gtk.Label(_("Data Folder"));
+ label.get_style_context().add_class("dim-label");
+ label.halign = Gtk.Align.END;
+ grid.attach(label, 0, 2, 1, 1);
+
+ entry = new Gtk.Entry();
+ entry.set_text(Environment.get_user_special_dir(UserDirectory.PICTURES));
+ entry.hexpand = true;
+ bind_property("data-folder", entry, "text", GLib.BindingFlags.SYNC_CREATE | GLib.BindingFlags.BIDIRECTIONAL);
+ entry.bind_property("text", create_button, "sensitive", GLib.BindingFlags.DEFAULT, (binding, from, ref to) => {
+ to = from.get_string() != "";
+ return true;
+ });
+ grid.attach(entry, 1, 2, 1, 1);
+
+ button = new Gtk.Button.from_icon_name("folder-symbolic", Gtk.IconSize.BUTTON);
+ button.hexpand = false;
+ button.vexpand = false;
+ button.halign = Gtk.Align.FILL;
+ button.clicked.connect(() => {
+ var dialog = new Gtk.FileChooserNative(_("Choose Data Folder"), this, Gtk.FileChooserAction.SELECT_FOLDER, _("_OK"), _("_Cancel"));
+ dialog.set_current_folder(data_folder);
+ var result = dialog.run();
+ dialog.hide();
+ if (result == Gtk.ResponseType.ACCEPT) {
+ data_folder = dialog.get_current_folder_file().get_path();
+ }
+ dialog.destroy();
+ });
+
+ grid.attach(button, 2, 2, 1, 1);
+
+ get_content_area().add(grid);
+
+ show_all();
+ }
+ }
+
+ private class ProfileRow : Gtk.Box {
+ public Profile profile{get; construct; }
+
+ public ProfileRow(Profile profile) {
+ Object(orientation: Gtk.Orientation.VERTICAL,
+ profile: profile, margin_top: 6, margin_bottom:6, margin_start:6, margin_end:6);
+ }
+
+ public override void constructed() {
+ base.constructed();
+ var content = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 6);
+ pack_start(content, true);
+
+ var revealer = new Gtk.Revealer();
+ revealer.margin_top = 6;
+ pack_end(revealer, true);
+
+ var label = new Gtk.Label(null);
+ label.set_markup("<span weight=\"bold\">%s</span>".printf(profile.name));
+ label.halign = Gtk.Align.START;
+ content.pack_start(label, true, true, 6);
+
+ Gtk.Image image;
+ if (profile.active) {
+ image = new Gtk.Image.from_icon_name ("emblem-default-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
+ image.set_tooltip_text(_("This is the currently active profile"));
+
+ } else {
+ image = new Gtk.Image();
+ }
+ content.pack_start(image, false, false, 6);
+
+ var button = new Gtk.ToggleButton();
+ button.get_style_context().add_class("flat");
+ content.pack_start(button, false, false, 6);
+ button.bind_property("active", revealer, "reveal-child", BindingFlags.DEFAULT);
+ image = new Gtk.Image.from_icon_name("go-down-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
+ button.add(image);
+
+ // FIXME: Would love to use the facade here, but this is currently hardwired to use a fixed profile
+ // and that even is not yet initialized
+ string settings_path;
+ if (profile.id == Profile.SYSTEM) {
+ settings_path = "/org/gnome/shotwell/preferences/files/";
+ } else {
+ settings_path = "/org/gnome/shotwell/profiles/" + profile.id + "/preferences/files/";
+ }
+
+ var settings = new Settings.with_path("org.gnome.shotwell.preferences.files", settings_path);
+ var import_dir = settings.get_string("import-dir");
+ if (import_dir == "") {
+ import_dir = Environment.get_user_special_dir(UserDirectory.PICTURES);
+ }
+
+ var grid = new Gtk.Grid();
+ grid.get_style_context().add_class("content");
+ grid.set_row_spacing(12);
+ grid.set_column_spacing(6);
+ revealer.add(grid);
+ label = new Gtk.Label(_("Library Folder"));
+ label.get_style_context().add_class("dim-label");
+ label.halign = Gtk.Align.END;
+ label.margin_start = 12;
+ grid.attach(label, 0, 0, 1, 1);
+ label = new Gtk.Label(import_dir);
+ label.halign = Gtk.Align.START;
+ label.set_ellipsize(Pango.EllipsizeMode.END);
+ grid.attach(label, 1, 0, 1, 1);
+
+ label = new Gtk.Label(_("Data Folder"));
+ label.get_style_context().add_class("dim-label");
+ label.halign = Gtk.Align.END;
+ label.margin_start = 12;
+ grid.attach(label, 0, 1, 1, 1);
+ label = new Gtk.Label(profile.data_dir);
+ label.halign = Gtk.Align.START;
+ label.hexpand = true;
+ label.set_ellipsize(Pango.EllipsizeMode.END);
+ grid.attach(label, 1, 1, 1, 1);
+
+ if (profile.id != Profile.SYSTEM && !profile.active) {
+ var remove_button = new Gtk.Button.with_label(_("Remove Profile"));
+ remove_button.get_style_context().add_class("destructive-action");
+ remove_button.set_tooltip_text(_("Remove this profile"));
+ remove_button.hexpand = false;
+ remove_button.halign = Gtk.Align.END;
+ grid.attach(remove_button, 1, 2, 1, 1);
+
+ remove_button.clicked.connect(() => {
+ var flags = Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL;
+ if (Resources.use_header_bar() == 1) {
+ flags |= Gtk.DialogFlags.USE_HEADER_BAR;
+ }
+
+ var d = new Gtk.MessageDialog((Gtk.Window) this.get_toplevel(), flags, Gtk.MessageType.QUESTION, Gtk.ButtonsType.NONE, null);
+ var title = _("Remove profile “%s”").printf(profile.name);
+ var subtitle = _("None of the options will remove any of the images associated with this profile");
+ d.set_markup(_("<b><span size=\"larger\">%s</span></b>\n<span weight=\"light\">%s</span>").printf(title, subtitle));
+
+ d.add_buttons(_("Remove profile and files"), Gtk.ResponseType.OK, _("Remove profile only"), Gtk.ResponseType.ACCEPT, _("Cancel"), Gtk.ResponseType.CANCEL);
+ d.get_widget_for_response(Gtk.ResponseType.OK).get_style_context().add_class("destructive-action");
+ var response = d.run();
+ d.destroy();
+ if (response == Gtk.ResponseType.OK || response == Gtk.ResponseType.ACCEPT) {
+ ProfileManager.get_instance().remove(profile.id, response == Gtk.ResponseType.OK);
+ }
+ });
+ }
+ }
+ }
+
+ class ProfileBrowser : Gtk.Box {
+ public ProfileBrowser() {
+ Object(orientation: Gtk.Orientation.VERTICAL, vexpand: true, hexpand: true);
+ }
+
+ public signal void profile_activated(string? profile);
+
+ public override void constructed() {
+ var scrollable = new Gtk.ScrolledWindow(null, null);
+ scrollable.hexpand = true;
+ scrollable.vexpand = true;
+
+ var list_box = new Gtk.ListBox();
+ list_box.activate_on_single_click = false;
+ list_box.row_activated.connect((list_box, row) => {
+ var index = row.get_index();
+ var profile = (Profile) ProfileManager.get_instance().get_item(index);
+ if (profile.id == Profile.SYSTEM) {
+ profile_activated(null);
+ } else {
+ profile_activated(profile.name);
+ }
+ });
+ list_box.get_style_context().add_class("rich-list");
+ list_box.hexpand = true;
+ list_box.vexpand = true;
+ scrollable.add (list_box);
+ list_box.bind_model(ProfileManager.get_instance(), on_widget_create);
+ list_box.set_header_func(on_header);
+
+ var button = new Gtk.Button.with_label(_("Create new Profile"));
+ pack_start(button, false, false, 6);
+ button.clicked.connect(() => {
+ var editor = new ProfileEditor();
+ editor.set_transient_for((Gtk.Window)get_ancestor(typeof(Gtk.Window)));
+ var result = editor.run();
+ editor.hide();
+ if (result == Gtk.ResponseType.OK) {
+ debug("Request to add new profile: %s %s %s %s", editor.id, editor.profile_name, editor.library_folder, editor.data_folder);
+ ProfileManager.get_instance().add_profile(editor.id, editor.profile_name, editor.library_folder, editor.data_folder);
+ }
+ editor.destroy();
+ });
+ add(scrollable);
+ show_all();
+ }
+
+ private Gtk.Widget on_widget_create(Object item) {
+ var row = new Gtk.ListBoxRow();
+ row.add(new ProfileRow((Profile) item));
+ row.show_all();
+
+ return row;
+ }
+
+ private void on_header(Gtk.ListBoxRow row, Gtk.ListBoxRow? before) {
+ if (before == null || row.get_header() != null) {
+ return;
+ }
+
+ var separator = new Gtk.Separator(Gtk.Orientation.HORIZONTAL);
+ separator.show();
+ row.set_header(separator);
+ }
+ }
+}