[gtk+/wip/csoriano/gtkpathbar_rework] gtkpathbar: listen to file changes and update pathbar
- From: Carlos Soriano Sánchez <csoriano src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/csoriano/gtkpathbar_rework] gtkpathbar: listen to file changes and update pathbar
- Date: Wed, 4 Mar 2015 18:18:50 +0000 (UTC)
commit 377962ec2f467cf3c5e10cff7684764e87f76e42
Author: Carlos Soriano <csoriano gnome org>
Date: Wed Mar 4 19:13:57 2015 +0100
gtkpathbar: listen to file changes and update pathbar
It's something we have more or less for free in Nautilus
given that we have all the backend in NautilusFile.
Here we have to do it ourselves, but we fix a long old bug,
and one of the most confusing things of gtkpathbar.
gtk/gtkpathbar.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 210 insertions(+), 20 deletions(-)
---
diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c
index 2eddd1b..7110392 100644
--- a/gtk/gtkpathbar.c
+++ b/gtk/gtkpathbar.c
@@ -41,6 +41,8 @@ struct _GtkPathBarPrivate
GdkWindow *event_window;
+ GFile *current_path;
+
GList *button_list;
GList *first_scrolled_button;
GtkWidget *up_slider_button;
@@ -91,6 +93,8 @@ struct _ButtonData
gboolean is_root;
char *dir_name;
GFile *file;
+ GFileMonitor *monitor;
+ guint file_changed_signal_id;
GtkWidget *image;
GtkWidget *label;
GCancellable *cancellable;
@@ -143,9 +147,9 @@ static void gtk_path_bar_style_updated (GtkWidget *widget);
static void gtk_path_bar_screen_changed (GtkWidget *widget,
GdkScreen *previous_screen);
static void gtk_path_bar_check_icon_theme (GtkPathBar *path_bar);
-static void gtk_path_bar_update_button_appearance (GtkPathBar *path_bar,
- ButtonData *button_data,
- gboolean current_dir);
+static void gtk_path_bar_update_button_appearance_and_state (ButtonData *button_data,
+ gboolean current_dir);
+static void gtk_path_bar_update_button_appearance (ButtonData *button_data);
static void
gtk_path_bar_init (GtkPathBar *path_bar)
@@ -1160,13 +1164,11 @@ reload_icons (GtkPathBar *path_bar)
for (list = path_bar->priv->button_list; list; list = list->next)
{
ButtonData *button_data;
- gboolean current_dir;
button_data = BUTTON_DATA (list->data);
if (button_data->type != NORMAL_BUTTON || button_data->is_root)
{
- current_dir = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_data->button));
- gtk_path_bar_update_button_appearance (path_bar, button_data, current_dir);
+ gtk_path_bar_update_button_appearance (button_data);
}
}
@@ -1362,7 +1364,12 @@ static void
button_data_free (ButtonData *button_data)
{
if (button_data->file)
- g_object_unref (button_data->file);
+ {
+ g_signal_handler_disconnect (button_data->file,
+ button_data->file_changed_signal_id);
+ g_object_unref (button_data->monitor);
+ g_object_unref (button_data->file);
+ }
button_data->file = NULL;
g_free (button_data->dir_name);
@@ -1383,9 +1390,7 @@ get_dir_name (ButtonData *button_data)
}
static void
-gtk_path_bar_update_button_appearance (GtkPathBar *path_bar,
- ButtonData *button_data,
- gboolean current_dir)
+gtk_path_bar_update_button_appearance (ButtonData *button_data)
{
const gchar *dir_name = get_dir_name (button_data);
GIcon *icon;
@@ -1404,13 +1409,19 @@ gtk_path_bar_update_button_appearance (GtkPathBar *path_bar,
{
gtk_widget_hide (GTK_WIDGET (button_data->image));
}
+}
- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_data->button)) != current_dir)
- {
- button_data->ignore_changes = TRUE;
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_data->button), current_dir);
- button_data->ignore_changes = FALSE;
- }
+static void
+gtk_path_bar_update_button_appearance_and_state (ButtonData *button_data,
+ gboolean current_dir)
+{
+ gtk_path_bar_update_button_appearance (button_data);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_data->button)) != current_dir) {
+ button_data->ignore_changes = TRUE;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_data->button), current_dir);
+ button_data->ignore_changes = FALSE;
+ }
}
gboolean
@@ -1512,6 +1523,175 @@ button_drag_data_get_cb (GtkWidget *widget,
g_free (uris[0]);
}
+static void
+gtk_path_bar_file_changed_on_get_info (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ const gchar *display_name;
+ ButtonData *button_data;
+ GFileInfo *info;
+ GFile *file;
+
+ button_data = BUTTON_DATA (user_data);
+ file = G_FILE (object);
+
+ info = g_file_query_info_finish (file, result, NULL);
+ if (!info)
+ {
+ g_print ("no info for %s\n", g_file_get_uri (file));
+ return;
+ }
+ display_name = g_file_info_get_display_name (info);
+
+ if (g_strcmp0 (display_name, button_data->dir_name) != 0)
+ {
+ g_free (button_data->dir_name);
+ button_data->dir_name = g_strdup (display_name);
+ }
+
+ gtk_path_bar_update_button_appearance (button_data);
+
+ g_object_unref (info);
+}
+
+static void
+gtk_path_bar_on_file_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer *user_data)
+{
+ GFile *location, *current_location, *parent, *button_parent;
+ ButtonData *innermost_button_data, *button_data;
+ GtkPathBar *path_bar;
+ gboolean renamed, child;
+
+ button_data = BUTTON_DATA (user_data);
+ g_print ("gtk_path_bar_on_file_changed %s, %s\n", g_file_get_uri (file), g_file_get_uri
(button_data->file));
+ path_bar = (GtkPathBar *) gtk_widget_get_ancestor (button_data->button,
+ GTK_TYPE_PATH_BAR);
+ if (path_bar == NULL)
+ {
+ return;
+ }
+
+ innermost_button_data = g_list_nth_data(path_bar->priv->button_list, 0);
+
+ g_assert (path_bar->priv->current_path!= NULL);
+ g_assert (innermost_button_data != NULL);
+
+ /* There's an actual change in the name or location of the file reflected as
+ * different GFile between the one in the button_data and the one that were monitoring
+ * that was the same file at the time of creation of the button_data. */
+ g_print ("event type %i\n", event_type);
+ if (!g_file_equal (button_data->file, file))
+ {
+ parent = g_file_get_parent (file);
+ button_parent = g_file_get_parent (button_data->file);
+
+ renamed = (parent != NULL && button_parent != NULL) &&
+ g_file_equal (parent, button_parent);
+
+ if (parent != NULL)
+ {
+ g_object_unref (parent);
+ }
+ if (button_parent != NULL)
+ {
+ g_object_unref (button_parent);
+ }
+
+ if (renamed)
+ {
+ button_data->file= g_object_ref (file);
+ }
+ else
+ {
+ /* The file has been moved.
+ * If it was below the currently displayed location, remove it.
+ * If it was not below the currently displayed location, update the path bar
+ */
+ child = g_file_has_prefix (button_data->file,
+ path_bar->priv->current_path);
+
+ if (child)
+ {
+ /* moved file inside current path hierarchy */
+#if 0
+ location = g_file_get_parent (button_data->file);
+#endif
+ current_location = g_object_ref (path_bar->priv->current_path);
+ }
+ else
+ {
+ /* moved current path, or file outside current path hierarchy.
+ * Update path bar to new locations.
+ */
+ current_location = button_data->file;
+ }
+
+#if 0
+ nautilus_path_bar_update_path (path_bar, location);
+#endif
+ _gtk_path_bar_set_file (path_bar, current_location, TRUE);
+ g_object_unref (current_location);
+ return;
+ }
+ }
+#if 0
+ else if (nautilus_file_is_gone (file))
+ {
+ gint idx, position;
+
+ /* if the current or a parent location are gone, clear all the buttons,
+ * the view will set the new path.
+ */
+ current_location = nautilus_file_get_location (button_data->file);
+
+ if (g_file_has_prefix (current_location, location) ||
+ g_file_equal (current_location, location)) {
+ nautilus_path_bar_clear_buttons (path_bar);
+ } else if (g_file_has_prefix (location, current_location)) {
+ /* remove this and the following buttons */
+ position = g_list_position (path_bar->priv->button_list,
+ g_list_find (path_bar->priv->button_list, button_data));
+
+ if (position != -1) {
+ for (idx = 0; idx <= position; idx++) {
+ gtk_container_remove (GTK_CONTAINER (path_bar),
+ BUTTON_DATA (path_bar->priv->button_list->data)->button);
+ }
+ }
+ }
+
+ g_object_unref (current_location);
+ g_object_unref (location);
+ return;
+ }
+#endif
+
+ /* MOUNTs use the GMount as the name, so don't update for those */
+ if (button_data->type != MOUNT_BUTTON)
+ {
+ if (event_type == G_FILE_MONITOR_EVENT_CREATED ||
+ event_type == G_FILE_MONITOR_EVENT_MOVED)
+ {
+ g_file_query_info_async (file,
+ "standard::display-name",
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ gtk_path_bar_file_changed_on_get_info,
+ button_data);
+ }
+ }
+ else
+ {
+ gtk_path_bar_update_button_appearance (button_data);
+ }
+}
+
static ButtonData *
make_directory_button (GtkPathBar *path_bar,
const char *dir_name,
@@ -1557,10 +1737,15 @@ make_directory_button (GtkPathBar *path_bar,
button_data->file = g_object_ref (file);
button_data->file_is_hidden = file_is_hidden;
+ button_data->monitor = g_file_monitor (file, G_FILE_MONITOR_SEND_MOVED, NULL, NULL);
+ button_data->file_changed_signal_id = g_signal_connect (button_data->monitor, "changed",
+ G_CALLBACK (gtk_path_bar_on_file_changed),
+ button_data);
+
gtk_container_add (GTK_CONTAINER (button_data->button), child);
gtk_widget_show_all (button_data->button);
- gtk_path_bar_update_button_appearance (path_bar, button_data, current_dir);
+ gtk_path_bar_update_button_appearance_and_state (button_data, current_dir);
g_signal_connect (button_data->button, "clicked",
G_CALLBACK (button_clicked_cb),
@@ -1602,9 +1787,8 @@ gtk_path_bar_check_parent_path (GtkPathBar *path_bar,
{
for (list = path_bar->priv->button_list; list; list = list->next)
{
- gtk_path_bar_update_button_appearance (path_bar,
- BUTTON_DATA (list->data),
- (list == current_path) ? TRUE : FALSE);
+ gtk_path_bar_update_button_appearance_and_state (BUTTON_DATA (list->data),
+ (list == current_path) ? TRUE : FALSE);
}
if (!gtk_widget_get_child_visible (BUTTON_DATA (current_path->data)->button))
@@ -1741,6 +1925,12 @@ _gtk_path_bar_set_file (GtkPathBar *path_bar,
g_return_if_fail (GTK_IS_PATH_BAR (path_bar));
g_return_if_fail (G_IS_FILE (file));
+ if (path_bar->priv->current_path != NULL)
+ {
+ g_object_unref (path_bar->priv->current_path);
+ }
+ path_bar->priv->current_path = g_object_ref (file);
+
/* Check whether the new path is already present in the pathbar as buttons.
* This could be a parent directory or a previous selected subdirectory.
*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]