From: Olivier CrĂȘte Date: Thu, 13 Apr 2023 22:09:48 +0000 (-0600) Subject: pathbar: Handle webdav where is the root is a path X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~372^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=c271cd1a3f76b2256ea173322cebdb246e08a453;p=gtk4.git pathbar: Handle webdav where is the root is a path Our webdav server has a root which is davs://mynextcloud/remote.php/webdav When once creates a GFile out of or out of a subdirectory, and one call g_file_get_parent(), it recurses too far up and try to query davs://mynextcloud/remote.php which fails, resulting in a broken pathbar. To fix that, before querying the metadata of each element of the path, I query the "enclosing mount", then use it's root to compare the GFile against. With the right GMount, we can also fix the icon drawing code in the pathbar for network drives. --- diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c index a19985732e..41e61c20a5 100644 --- a/gtk/gtkpathbar.c +++ b/gtk/gtkpathbar.c @@ -125,6 +125,7 @@ struct _ButtonData GCancellable *cancellable; guint ignore_changes : 1; guint file_is_hidden : 1; + GMount *mount; }; /* This macro is used to check if a button can be used as a fake root. * All buttons in front of a fake root are automatically hidden when in a @@ -417,30 +418,30 @@ set_button_image (GtkPathBar *path_bar, ButtonData *button_data) { struct SetButtonImageData *data; - GMount *mount; switch (button_data->type) { case ROOT_BUTTON: - if (path_bar->root_icon != NULL) + GIcon *root_icon = NULL; + + if (!button_data->mount && path_bar->root_icon != NULL && + g_file_is_native (button_data->file)) { gtk_image_set_from_gicon (GTK_IMAGE (button_data->image), path_bar->root_icon); - break; - } - - mount = g_file_find_enclosing_mount (button_data->file, NULL, NULL); + break; + } - if (!mount && g_file_is_native (button_data->file)) - path_bar->root_icon = g_themed_icon_new ("drive-harddisk-symbolic"); - else if (mount) - path_bar->root_icon = g_mount_get_symbolic_icon (mount); + if (!button_data->mount && g_file_is_native (button_data->file)) + root_icon = path_bar->root_icon = g_object_ref (g_themed_icon_new ("drive-harddisk-symbolic")); + else if (button_data->mount) + root_icon = g_mount_get_symbolic_icon (button_data->mount); else - path_bar->root_icon = NULL; + root_icon = NULL; - g_clear_object (&mount); + gtk_image_set_from_gicon (GTK_IMAGE (button_data->image), root_icon); - gtk_image_set_from_gicon (GTK_IMAGE (button_data->image), path_bar->root_icon); + g_clear_object (&root_icon); break; @@ -515,6 +516,7 @@ static void button_data_free (ButtonData *button_data) { g_clear_object (&button_data->file); + g_clear_object (&button_data->mount); g_free (button_data->dir_name); g_free (button_data); } @@ -571,11 +573,11 @@ file_is_recent_uri (GFile *file) } static ButtonType -find_button_type (GtkPathBar *path_bar, - GFile *file) +find_button_type (GtkPathBar *path_bar, + GFile *file, + GFile *root_file) { - if (path_bar->root_file != NULL && - g_file_equal (file, path_bar->root_file)) + if (root_file != NULL && g_file_equal (file, root_file)) return ROOT_BUTTON; if (path_bar->home_file != NULL && g_file_equal (file, path_bar->home_file)) @@ -593,6 +595,8 @@ static ButtonData * make_directory_button (GtkPathBar *path_bar, const char *dir_name, GFile *file, + GMount *mount, + GFile *root_file, gboolean current_dir, gboolean file_is_hidden) { @@ -604,17 +608,26 @@ make_directory_button (GtkPathBar *path_bar, file_is_hidden = !! file_is_hidden; /* Is it a special button? */ button_data = g_new0 (ButtonData, 1); - button_data->type = find_button_type (path_bar, file); + button_data->type = find_button_type (path_bar, file, root_file); button_data->button = gtk_toggle_button_new (); gtk_widget_set_focus_on_click (button_data->button, FALSE); switch (button_data->type) { case ROOT_BUTTON: - button_data->image = gtk_image_new (); - child = button_data->image; - button_data->label = NULL; - break; + if (mount) + { + button_data->dir_name = g_mount_get_name (mount); + button_data->mount = g_object_ref (mount); + } + else + { + button_data->image = gtk_image_new (); + child = button_data->image; + button_data->label = NULL; + break; + } + G_GNUC_FALLTHROUGH; case HOME_BUTTON: case DESKTOP_BUTTON: case RECENT_BUTTON: @@ -631,7 +644,8 @@ make_directory_button (GtkPathBar *path_bar, button_data->image = NULL; } - button_data->dir_name = g_strdup (dir_name); + if (button_data->dir_name == NULL) + button_data->dir_name = g_strdup (dir_name); button_data->file = g_object_ref (file); button_data->file_is_hidden = file_is_hidden; @@ -715,6 +729,8 @@ gtk_path_bar_check_parent_path (GtkPathBar *path_bar, struct SetFileInfo { GFile *file; + GMount *mount; + GFile *root_file; GFile *parent_file; GtkPathBar *path_bar; GList *new_buttons; @@ -762,10 +778,15 @@ gtk_path_bar_set_file_finish (struct SetFileInfo *info, g_object_unref (info->file); if (info->parent_file) g_object_unref (info->parent_file); + if (info->root_file) + g_object_unref (info->root_file); + if (info->mount) + g_object_unref (info->mount); g_free (info); } + static void gtk_path_bar_get_info_callback (GObject *source, GAsyncResult *result, @@ -802,6 +823,8 @@ gtk_path_bar_get_info_callback (GObject *source, button_data = make_directory_button (file_info->path_bar, display_name, file_info->file, + file_info->mount, + file_info->root_file, file_info->first_directory, is_hidden); g_clear_object (&file_info->file); @@ -824,7 +847,54 @@ gtk_path_bar_get_info_callback (GObject *source, return; } - file_info->parent_file = g_file_get_parent (file_info->file); + if (g_file_equal (file_info->file, file_info->root_file)) + file_info->parent_file = NULL; + else + file_info->parent_file = g_file_get_parent (file_info->file); + + /* Recurse asynchronously */ + file_info->cancellable = g_cancellable_new (); + file_info->path_bar->get_info_cancellable = file_info->cancellable; + g_file_query_info_async (file_info->file, + "standard::display-name," + "standard::is-hidden," + "standard::is-backup", + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + file_info->cancellable, + gtk_path_bar_get_info_callback, + file_info); + add_cancellable (file_info->path_bar, file_info->cancellable); +} + +static void +gtk_path_bar_get_mount_callback (GObject *source, + GAsyncResult *result, + gpointer data) +{ + GFile *file = G_FILE (source); + struct SetFileInfo *file_info = data; + + file_info->mount = g_file_find_enclosing_mount_finish (file, result, NULL); + + if (file_info->mount) + file_info->root_file = g_mount_get_root (file_info->mount); + + g_assert (GTK_IS_PATH_BAR (file_info->path_bar)); + g_assert (G_OBJECT (file_info->path_bar)->ref_count > 0); + + if (file_info->root_file == NULL) + file_info->root_file = g_object_ref (file_info->path_bar->root_file); + + if (g_file_equal (file_info->file, file_info->root_file)) + file_info->parent_file = NULL; + else + file_info->parent_file = g_file_get_parent (file_info->file); + + cancellable_async_done (file_info->path_bar, file_info->cancellable); + if (file_info->path_bar->get_info_cancellable == file_info->cancellable) + file_info->path_bar->get_info_cancellable = NULL; + file_info->cancellable = NULL; /* Recurse asynchronously */ file_info->cancellable = g_cancellable_new (); @@ -861,22 +931,36 @@ _gtk_path_bar_set_file (GtkPathBar *path_bar, info->file = g_object_ref (file); info->path_bar = path_bar; info->first_directory = TRUE; - info->parent_file = g_file_get_parent (info->file); if (path_bar->get_info_cancellable) cancel_cancellable (path_bar, path_bar->get_info_cancellable); info->cancellable = g_cancellable_new (); path_bar->get_info_cancellable = info->cancellable; - g_file_query_info_async (info->file, - "standard::display-name," - "standard::is-hidden," - "standard::is-backup", - G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, - info->cancellable, - gtk_path_bar_get_info_callback, - info); + + if (g_file_is_native (info->file)) + { + info->root_file = g_object_ref (path_bar->root_file); + info->parent_file = g_file_get_parent (info->file); + + g_file_query_info_async (info->file, + "standard::display-name," + "standard::is-hidden," + "standard::is-backup", + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + info->cancellable, + gtk_path_bar_get_info_callback, + info); + } + else + { + g_file_find_enclosing_mount_async (info->file, + G_PRIORITY_DEFAULT, + info->cancellable, + gtk_path_bar_get_mount_callback, + info); + } add_cancellable (path_bar, info->cancellable); }