From 5e32cfa1dfac5dc5418ca012ec0c1d65eac7d005 Mon Sep 17 00:00:00 2001 From: Matteo Nardi Date: Tue, 5 Dec 2023 17:24:53 +0100 Subject: [PATCH] window: remember image property visibility state Added GSettings support to Loupe. Inspiration was taken from Fractal: LpApplication will contain `gio::Settings` and all code needing them will reach them as a singleton by calling `g_application_get_default`. This design makes the settings dependency less explicit than dependency injection, but allows for shorter code when new settings will be added across different parts of the application. A `show-properties` setting is added for remembaring the image property sidebar state. It's read by LpWindow when the current page changes, and saved when toggling the sidebar. When no image is being shown, the sidebar is always hidden, while the setting remains unchanged. The sidebar state will be restored when a picture is opened. Closes #147 --- .gitlab-ci.yml | 4 ++-- data/meson.build | 20 ++++++++++++++++++++ data/org.gnome.Loupe.gschema.xml.in | 9 +++++++++ meson.build | 3 +++ po/POTFILES.in | 1 + src/application.rs | 27 +++++++++++++++++++++++++-- src/window.rs | 25 +++++++++++++++++++++++++ 7 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 data/org.gnome.Loupe.gschema.xml.in diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a1dfc96..b5a7475 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -121,7 +121,7 @@ other-checks: image: alpine script: - apk add --no-cache git - - git ls-files 'src/*.rs' 'src/*.ui' 'data/*.ui' 'data/*.desktop.in*' '*.metainfo.xml.in*' > po/POTFILES.in + - git ls-files 'src/*.rs' 'src/*.ui' 'data/*.ui' 'data/*.desktop.in*' '*.gschema.xml.in' '*.metainfo.xml.in*' > po/POTFILES.in - git diff --exit-code pages: @@ -147,4 +147,4 @@ nightly@aarch64: extends: ".publish_nightly" stage: deploy dependencies: - - flatpak@aarch64 \ No newline at end of file + - flatpak@aarch64 diff --git a/data/meson.build b/data/meson.build index ef6b855..fced285 100644 --- a/data/meson.build +++ b/data/meson.build @@ -90,6 +90,26 @@ appstream_file = i18n.merge_file( subdir('icons') +# GSchema +gschema_conf = configuration_data() +gschema_conf.set('app-id', app_id) +gschema_conf.set('gettext-package', meson.project_name()) +configure_file( + input: '@0@.gschema.xml.in'.format(base_id), + output: '@0@.gschema.xml'.format(app_id), + configuration: gschema_conf, + install: true, + install_dir: iv_datadir / 'glib-2.0' / 'schemas' +) + +# Validate GSchema +test( + 'validate-gschema', glib_compile_schemas, + args: [ + '--strict', '--dry-run', meson.current_source_dir() + ] +) + # Post install gnome.post_install() diff --git a/data/org.gnome.Loupe.gschema.xml.in b/data/org.gnome.Loupe.gschema.xml.in new file mode 100644 index 0000000..13ac2ea --- /dev/null +++ b/data/org.gnome.Loupe.gschema.xml.in @@ -0,0 +1,9 @@ + + + + + false + Show the image properties sidebar + + + diff --git a/meson.build b/meson.build index b3c5b6a..a1f0fd1 100644 --- a/meson.build +++ b/meson.build @@ -15,6 +15,7 @@ dependency('gweather4', version: '>=4.0.0') dependency('lcms2', version: '>=2.12.0') cargo = find_program('cargo', required: true) +glib_compile_schemas = find_program('glib-compile-schemas', required: true) iv_prefix = get_option('prefix') iv_bindir = iv_prefix / get_option('bindir') @@ -35,6 +36,7 @@ if get_option('profile') != 'release' endif endif +base_id = 'org.gnome.Loupe' app_id = 'org.gnome.Loupe@0@'.format(profile) iv_version = meson.project_version() + version_suffix @@ -66,6 +68,7 @@ endif gnome.post_install( gtk_update_icon_cache: true, update_desktop_database: true, + glib_compile_schemas: true, ) meson.add_dist_script( diff --git a/po/POTFILES.in b/po/POTFILES.in index 7d5f361..b94f546 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,5 @@ data/org.gnome.Loupe.desktop.in.in +data/org.gnome.Loupe.gschema.xml.in data/org.gnome.Loupe.metainfo.xml.in.in data/resources/gtk/help-overlay.ui src/about.rs diff --git a/src/application.rs b/src/application.rs index 6f40d63..586f167 100644 --- a/src/application.rs +++ b/src/application.rs @@ -33,8 +33,18 @@ mod imp { // The basic struct that holds our // state and widgets - #[derive(Default, Debug)] - pub struct LpApplication {} + #[derive(Debug)] + pub struct LpApplication { + pub settings: gio::Settings, + } + + impl Default for LpApplication { + fn default() -> Self { + Self { + settings: gio::Settings::new(config::APP_ID), + } + } + } // Sets up the basics for the GObject // The `#[glib::object_subclass] macro implements @@ -209,4 +219,17 @@ impl LpApplication { } }); } + + pub fn settings(&self) -> gio::Settings { + self.imp().settings.clone() + } +} + +impl Default for LpApplication { + fn default() -> Self { + gio::Application::default() + .unwrap() + .downcast::() + .unwrap() + } } diff --git a/src/window.rs b/src/window.rs index 10d1690..94639f0 100644 --- a/src/window.rs +++ b/src/window.rs @@ -35,6 +35,7 @@ use gtk::CompositeTemplate; use std::cell::{Cell, OnceCell, RefCell}; use std::path::{Path, PathBuf}; +use crate::application::LpApplication; use crate::config; use crate::util::{Direction, Position}; use crate::widgets::{LpDragOverlay, LpImage, LpImageView, LpPropertiesView}; @@ -275,6 +276,10 @@ mod imp { .connect_pressed(clone!(@weak obj => move |_,_,_,_| { obj.image_view().navigate(Direction::Back); })); + self.properties_button + .connect_toggled(clone!(@weak obj => move |_| { + obj.on_properties_button_toggled(); + })); if config::PROFILE == ".Devel" { obj.add_css_class("devel"); @@ -764,10 +769,14 @@ impl LpWindow { ); if has_image { + let settings = LpApplication::default().settings(); + imp.properties_button + .set_active(settings.boolean("show-properties")); imp.stack.set_visible_child(&*imp.image_view); imp.image_view.grab_focus(); self.schedule_hide_controls(); } else { + imp.properties_button.set_active(false); imp.stack.set_visible_child(&*imp.status_page); imp.status_page.grab_focus(); // Leave fullscreen since status page has no controls to leave it @@ -775,6 +784,22 @@ impl LpWindow { } } + /// When the image-properties sidebar is displayed or hidden, we should update the + /// "show-properties" setting. + fn on_properties_button_toggled(&self) { + let imp = self.imp(); + // When no image is shown, we skip this update as the sidebar should always be hidden. + // This can happen when deleting a picture. + if imp.image_view.current_page().is_none() { + return; + } + let settings = LpApplication::default().settings(); + let result = settings.set_boolean("show-properties", imp.properties_button.is_active()); + if let Err(err) = result { + log::warn!("Failed to save show-properties state, {}", err); + } + } + pub fn update_title(&self) { let title = self .imp()