[xdg-desktop-portal-gnome/gbsneto/remember-last-location] filechooser: Remember last app folder
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [xdg-desktop-portal-gnome/gbsneto/remember-last-location] filechooser: Remember last app folder
- Date: Tue, 30 Aug 2022 20:39:37 +0000 (UTC)
commit 4254d1c8acc78911c713da5a72bb175c23ef32a8
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Tue Aug 30 17:23:28 2022 -0300
filechooser: Remember last app folder
The GNOME implementation of the FileChooser portal doesn't make any
effort to remember the last folder of any given app. This can be
quite frustrating, and a significant usability problem, especially
when doing repetitive operations on the same app that require picking
files over and over.
Remembering the last folder selected by a given app is a quick win
that doesn't require too much introspection design-wise, so let's
just do it.
src/filechooser.c | 92 ++++++++++++++++++++++++++++++++
src/meson.build | 7 +++
src/xdg-desktop-portal-gnome.gschema.xml | 10 ++++
3 files changed, 109 insertions(+)
---
diff --git a/src/filechooser.c b/src/filechooser.c
index 0f45f84..72d4071 100644
--- a/src/filechooser.c
+++ b/src/filechooser.c
@@ -44,6 +44,8 @@
#include "utils.h"
#include "externalwindow.h"
+#define FILECHOOSER_SETTINGS_SCHEMA "org.gnome.portal.filechooser"
+#define FILECHOOSER_SETTINGS_PATH "/org/gnome/portal/filechooser/"
typedef struct {
XdpImplFileChooser *impl;
@@ -89,6 +91,83 @@ file_dialog_handle_close (FileDialogHandle *handle)
file_dialog_handle_free (handle);
}
+static GSettings*
+get_filechooser_settings_for_app_id (const char *app_id)
+{
+ g_autoptr(GSettings) settings = NULL;
+ g_autoptr(GString) path = NULL;
+
+ g_assert (app_id && g_utf8_validate (app_id, -1, NULL));
+
+ path = g_string_new (FILECHOOSER_SETTINGS_PATH);
+ g_string_append (path, app_id);
+ g_string_append (path, "/");
+
+ settings = g_settings_new_with_path (FILECHOOSER_SETTINGS_SCHEMA, path->str);
+
+ return g_steal_pointer (&settings);
+}
+
+static void
+restore_last_folder (FileDialogHandle *handle,
+ GtkFileChooser *filechooser)
+{
+ g_autoptr(GSettings) settings = NULL;
+ g_autofree char *last_folder_path = NULL;
+
+ if (!handle->app_id || *handle->app_id == '\0')
+ return;
+
+ settings = get_filechooser_settings_for_app_id (handle->app_id);
+ last_folder_path = g_settings_get_string (settings, "last-folder-path");
+
+ if (last_folder_path && *last_folder_path)
+ {
+ g_autoptr(GFile) last_folder = g_file_new_for_path (last_folder_path);
+ gtk_file_chooser_set_current_folder (filechooser, last_folder, NULL);
+ }
+}
+
+static void
+save_last_folder (FileDialogHandle *handle,
+ GtkFileChooser *filechooser)
+{
+ g_autoptr(GListModel) files = NULL;
+ g_autofree char *path = NULL;
+
+ if (!handle->app_id || *handle->app_id == '\0')
+ return;
+
+ files = gtk_file_chooser_get_files (filechooser);
+
+ for (guint i = g_list_model_get_n_items (files); i > 0; i--)
+ {
+ g_autoptr(GFile) file = g_list_model_get_item (files, i - 1);
+
+ if (g_file_is_native (file))
+ {
+ path = g_file_get_path (file);
+
+ if (!g_file_test (path, G_FILE_TEST_IS_DIR))
+ {
+ g_autoptr(GFile) parent = g_file_get_parent (file);
+
+ g_clear_pointer (&path, g_free);
+ path = g_file_get_path (parent);
+ }
+
+ if (path)
+ break;
+ }
+ }
+
+ if (path)
+ {
+ g_autoptr(GSettings) settings = get_filechooser_settings_for_app_id (handle->app_id);
+ g_settings_set_string (settings, "last-folder-path", path);
+ }
+}
+
static void
add_choices (FileDialogHandle *handle,
GVariantBuilder *builder)
@@ -285,6 +364,7 @@ file_chooser_response (GtkWidget *widget,
handle->response = 0;
handle->filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER(widget));
handle->uris = get_uris (GTK_FILE_CHOOSER (widget));
+ save_last_folder (handle, GTK_FILE_CHOOSER (widget));
break;
}
@@ -588,6 +668,10 @@ handle_open (XdpImplFileChooser *object,
g_autoptr(GFile) file = g_file_new_for_path (path);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), file, NULL);
}
+ else
+ {
+ restore_last_folder (handle, GTK_FILE_CHOOSER (dialog));
+ }
}
}
else if (strcmp (method_name, "SaveFiles") == 0)
@@ -601,6 +685,10 @@ handle_open (XdpImplFileChooser *object,
g_autoptr(GFile) file = g_file_new_for_path (path);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), file, NULL);
}
+ else
+ {
+ restore_last_folder (handle, GTK_FILE_CHOOSER (dialog));
+ }
if (g_variant_lookup (arg_options, "files", "aay", &iter))
{
@@ -611,6 +699,10 @@ handle_open (XdpImplFileChooser *object,
g_variant_iter_free (iter);
}
}
+ else
+ {
+ restore_last_folder (handle, GTK_FILE_CHOOSER (dialog));
+ }
g_object_unref (fake_parent);
diff --git a/src/meson.build b/src/meson.build
index c472f98..c53b448 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -141,3 +141,10 @@ executable(
install: true,
install_dir: libexecdir,
)
+
+install_data (
+ 'xdg-desktop-portal-gnome.gschema.xml',
+ install_dir : datadir / 'glib-2.0' / 'schemas',
+)
+
+gnome.post_install(glib_compile_schemas: true)
diff --git a/src/xdg-desktop-portal-gnome.gschema.xml b/src/xdg-desktop-portal-gnome.gschema.xml
new file mode 100644
index 0000000..d4c61cb
--- /dev/null
+++ b/src/xdg-desktop-portal-gnome.gschema.xml
@@ -0,0 +1,10 @@
+<schemalist>
+ <schema id="org.gnome.portal" path="/org/gnome/portal/" gettext-domain="xdg-desktop-portal-gnome">
+ <child name="filechooser" schema="org.gnome.portal.filechooser"/>
+ </schema>
+ <schema id="org.gnome.portal.filechooser" gettext-domain="xdg-desktop-portal-gnome">
+ <key name="last-folder-path" type="s">
+ <default>""</default>
+ </key>
+ </schema>
+</schemalist>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]