[Xfce4-commits] <thunar:jannis/new-shortcuts-pane> Add a ThunarShortcut::changed signal for lazy loading shortcuts.
Jannis Pohlmann
noreply at xfce.org
Fri Jul 15 21:10:26 CEST 2011
Updating branch refs/heads/jannis/new-shortcuts-pane
to 4ab0b79b26290bd7eeb04ee3116429604cd459da (commit)
from 235f9f191d08b8742c14edc6b6e587c042adac44 (commit)
commit 4ab0b79b26290bd7eeb04ee3116429604cd459da
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Wed Jun 8 01:09:16 2011 +0200
Add a ThunarShortcut::changed signal for lazy loading shortcuts.
This doesn't do anything yet but we can use it to watch volumes, mounts
and regular files for changes and forward those to the model, then to
the view and then to the individual rows. Another use is to resolve URIs
into GFiles into ThunarFiles asynchronously step-by-step and emit a
"changed" signal after each transition.
Maybe this will help fixing the startup delay issues due to all the slow
GVfs D-Bus services (e.g. network).
thunar/thunar-shortcut.c | 11 +++
thunar/thunar-shortcuts-model.c | 149 +++++++++++++++++++++++++++++++++++----
thunar/thunar-shortcuts-view.c | 77 ++++++++++++++++++++-
3 files changed, 220 insertions(+), 17 deletions(-)
diff --git a/thunar/thunar-shortcut.c b/thunar/thunar-shortcut.c
index 216618c..6b3178c 100644
--- a/thunar/thunar-shortcut.c
+++ b/thunar/thunar-shortcut.c
@@ -54,6 +54,7 @@ enum
/* signal identifiers */
enum
{
+ SIGNAL_CHANGED,
LAST_SIGNAL,
};
@@ -106,6 +107,10 @@ G_DEFINE_TYPE (ThunarShortcut, thunar_shortcut, G_TYPE_OBJECT)
+static guint shortcut_signals[LAST_SIGNAL];
+
+
+
static void
thunar_shortcut_class_init (ThunarShortcutClass *klass)
{
@@ -208,6 +213,12 @@ thunar_shortcut_class_init (ThunarShortcutClass *klass)
"persistent",
FALSE,
EXO_PARAM_READWRITE));
+
+ shortcut_signals[SIGNAL_CHANGED] = g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
}
diff --git a/thunar/thunar-shortcuts-model.c b/thunar/thunar-shortcuts-model.c
index 49cf505..0c5706e 100644
--- a/thunar/thunar-shortcuts-model.c
+++ b/thunar/thunar-shortcuts-model.c
@@ -111,6 +111,10 @@ static gboolean thunar_shortcuts_model_find_category (Thu
ThunarShortcut *shortcut,
ThunarShortcutCategory **category,
gint *category_index);
+static gboolean thunar_shortcuts_model_find_shortcut (ThunarShortcutsModel *model,
+ ThunarShortcut *shortcut,
+ gint *category_index,
+ gint *shortcut_index);
static gboolean thunar_shortcuts_model_find_volume (ThunarShortcutsModel *model,
GVolume *volume,
gint *category_index,
@@ -121,6 +125,8 @@ static gboolean thunar_shortcuts_model_find_mount (Thu
gint *shortcut_index);
static void thunar_shortcuts_model_add_shortcut (ThunarShortcutsModel *model,
ThunarShortcut *shortcut);
+static void thunar_shortcuts_model_shortcut_changed (ThunarShortcutsModel *model,
+ ThunarShortcut *shortcut);
static gboolean thunar_shortcuts_model_load_system_shortcuts (gpointer user_data);
static gboolean thunar_shortcuts_model_load_user_dirs (gpointer user_data);
static gboolean thunar_shortcuts_model_load_bookmarks (gpointer user_data);
@@ -940,6 +946,47 @@ thunar_shortcuts_model_find_category (ThunarShortcutsModel *model,
static gboolean
+thunar_shortcuts_model_find_shortcut (ThunarShortcutsModel *model,
+ ThunarShortcut *shortcut,
+ gint *category_index,
+ gint *shortcut_index)
+{
+ ThunarShortcutCategory *category;
+ ThunarShortcut *current_shortcut;
+ gboolean shortcut_found = FALSE;
+ gint c;
+ gint s;
+
+ _thunar_return_val_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model), FALSE);
+ _thunar_return_val_if_fail (THUNAR_IS_SHORTCUT (shortcut), FALSE);
+
+ for (c = 0; !shortcut_found && (guint) c < model->categories->len; ++c)
+ {
+ category = g_ptr_array_index (model->categories, c);
+
+ for (s = 0; !shortcut_found && (guint) s < category->shortcuts->len; ++s)
+ {
+ current_shortcut = g_ptr_array_index (category->shortcuts, s);
+
+ if (current_shortcut == shortcut)
+ {
+ if (category_index != NULL)
+ *category_index = c;
+
+ if (shortcut_index != NULL)
+ *shortcut_index = s;
+
+ shortcut_found = TRUE;
+ }
+ }
+ }
+
+ return shortcut_found;
+}
+
+
+
+static gboolean
thunar_shortcuts_model_find_volume (ThunarShortcutsModel *model,
GVolume *volume,
gint *category_index,
@@ -1047,25 +1094,59 @@ thunar_shortcuts_model_add_shortcut (ThunarShortcutsModel *model,
}
/* insert the shortcut into the category if we have one for it */
- if (category != NULL)
- {
- /* add the shortcut to the category */
- g_ptr_array_add (category->shortcuts, shortcut);
+ /* add the shortcut to the category */
+ g_ptr_array_add (category->shortcuts, shortcut);
- /* create a tree path for the new row */
- path = gtk_tree_path_new_from_indices (category_index,
- category->shortcuts->len - 1,
- -1);
+ /* create a tree path for the new row */
+ path = gtk_tree_path_new_from_indices (category_index,
+ category->shortcuts->len - 1,
+ -1);
- /* create a tree iter for the new row */
+ /* create a tree iter for the new row */
#ifndef NDEBUG
- iter.stamp = model->stamp;
+ iter.stamp = model->stamp;
#endif
- iter.user_data = GINT_TO_POINTER (category_index);
- iter.user_data2 = GINT_TO_POINTER (category->shortcuts->len - 1);
+ iter.user_data = GINT_TO_POINTER (category_index);
+ iter.user_data2 = GINT_TO_POINTER (category->shortcuts->len - 1);
- /* create a tree path for the new row */
- g_signal_emit_by_name (model, "row-inserted", path, &iter, NULL);
+ /* create a tree path for the new row */
+ g_signal_emit_by_name (model, "row-inserted", path, &iter, NULL);
+
+ /* release the tree path */
+ gtk_tree_path_free (path);
+
+ /* be notified whenever the shortcut changes */
+ g_signal_connect_swapped (shortcut, "changed",
+ G_CALLBACK (thunar_shortcuts_model_shortcut_changed),
+ model);
+}
+
+
+
+static void
+thunar_shortcuts_model_shortcut_changed (ThunarShortcutsModel *model,
+ ThunarShortcut *shortcut)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gint category_index;
+ gint shortcut_index;
+
+ _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model));
+ _thunar_return_if_fail (THUNAR_IS_SHORTCUT (shortcut));
+
+ /* try find the shortcut in the model */
+ if (thunar_shortcuts_model_find_shortcut (model, shortcut,
+ &category_index, &shortcut_index))
+ {
+ /* create a tree path for the row */
+ path = gtk_tree_path_new_from_indices (category_index, shortcut_index, -1);
+
+ /* create a tree iter for the row */
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
+
+ /* notify others that the row has changed */
+ g_signal_emit_by_name (model, "row-changed", path, &iter, NULL);
/* release the tree path */
gtk_tree_path_free (path);
@@ -1174,6 +1255,34 @@ thunar_shortcuts_model_load_system_shortcuts (gpointer user_data)
g_object_unref (icon);
g_object_unref (location);
+ /* create network information */
+ /* TODO we need a new "uri" property for ThunarShortcut that is
+ * resolved into a real GFile and then into a ThunarFile
+ * asynchronously */
+ location = g_file_new_for_uri ("network://");
+ icon = g_themed_icon_new (GTK_STOCK_NETWORK);
+ name = g_strdup (_("Browse Network"));
+
+ /* create the network shortcut */
+ shortcut = g_object_new (THUNAR_TYPE_SHORTCUT,
+ "shortcut-type", THUNAR_SHORTCUT_NETWORK_FILE,
+ "location", location,
+ "icon", icon,
+ "eject-icon", NULL,
+ "name", name,
+ "hidden", FALSE,
+ "mutable", FALSE,
+ "persistent", TRUE,
+ NULL);
+
+ /* add the network shortcut */
+ thunar_shortcuts_model_add_shortcut (model, shortcut);
+
+ /* release network information */
+ g_free (name);
+ g_object_unref (icon);
+ g_object_unref (location);
+
/* load rest of the user dirs next */
model->load_idle_id = g_idle_add (thunar_shortcuts_model_load_user_dirs, model);
@@ -1383,6 +1492,7 @@ thunar_shortcuts_model_volume_added (ThunarShortcutsModel *model,
GVolumeMonitor *monitor)
{
ThunarShortcut *shortcut;
+ gboolean hidden = TRUE;
GIcon *eject_icon;
GIcon *icon;
gchar *name;
@@ -1396,6 +1506,15 @@ thunar_shortcuts_model_volume_added (ThunarShortcutsModel *model,
eject_icon = g_themed_icon_new ("media-eject");
name = g_volume_get_name (volume);
+ /* hide the volume if there is no media */
+ if (!thunar_g_volume_is_present (volume))
+ hidden = TRUE;
+
+ /* hide the volume if it is not removable (this can be
+ * overridden by the user in the shortcuts editor) */
+ if (!thunar_g_volume_is_removable (volume))
+ hidden = TRUE;
+
/* create a shortcut for the volume */
shortcut = g_object_new (THUNAR_TYPE_SHORTCUT,
"shortcut-type", THUNAR_SHORTCUT_REGULAR_VOLUME,
@@ -1403,7 +1522,7 @@ thunar_shortcuts_model_volume_added (ThunarShortcutsModel *model,
"icon", icon,
"eject-icon", eject_icon,
"name", name,
- "hidden", FALSE,
+ "hidden", hidden,
"mutable", FALSE,
"persistent", FALSE,
NULL);
diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c
index 2f635e5..6048998 100644
--- a/thunar/thunar-shortcuts-view.c
+++ b/thunar/thunar-shortcuts-view.c
@@ -91,6 +91,10 @@ static void thunar_shortcuts_view_row_inserted (ThunarShortcut
static void thunar_shortcuts_view_row_deleted (ThunarShortcutsView *view,
GtkTreePath *path,
GtkTreeModel *model);
+static void thunar_shortcuts_view_row_changed (ThunarShortcutsView *view,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ GtkTreeModel *model);
static GtkWidget *thunar_shortcuts_view_get_expander_at (ThunarShortcutsView *view,
gint index);
static void thunar_shortcuts_view_row_activated (ThunarShortcutsView *view,
@@ -302,6 +306,10 @@ thunar_shortcuts_view_constructed (GObject *object)
/* be notified when a shortcut is removed from the model */
g_signal_connect_swapped (view->model, "row-deleted",
G_CALLBACK (thunar_shortcuts_view_row_deleted), view);
+
+ /* be notified when a shortcut changes */
+ g_signal_connect_swapped (view->model, "row-changed",
+ G_CALLBACK (thunar_shortcuts_view_row_changed), view);
}
@@ -432,8 +440,7 @@ thunar_shortcuts_view_row_inserted (ThunarShortcutsView *view,
gtk_box_reorder_child (GTK_BOX (box), shortcut_row, shortcut_index);
/* show the row now (unless it was hidden by the user) */
- if (visible)
- gtk_widget_show (shortcut_row);
+ gtk_widget_set_visible (shortcut_row, visible);
/* be notified when the user wishes to open the shortcut */
g_signal_connect_swapped (shortcut_row, "activated",
@@ -490,6 +497,72 @@ thunar_shortcuts_view_row_deleted (ThunarShortcutsView *view,
+static void
+thunar_shortcuts_view_row_changed (ThunarShortcutsView *view,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ GtkTreeModel *model)
+{
+ ThunarShortcutRow *row;
+ GtkWidget *expander;
+ GtkWidget *box;
+ GIcon *icon;
+ GList *rows;
+ GList *row_element;
+ gchar *name;
+ gint category_index;
+ gint shortcut_index;
+
+ _thunar_return_if_fail (THUNAR_SHORTCUTS_VIEW (view));
+ _thunar_return_if_fail (GTK_IS_TREE_MODEL (model));
+
+ /* get the category and shortcut index */
+ category_index = gtk_tree_path_get_indices (path)[0];
+ shortcut_index = gtk_tree_path_get_indices (path)[1];
+
+ /* find the expander for the row widget */
+ expander = thunar_shortcuts_view_get_expander_at (view, category_index);
+
+ /* if this fails then we are out of sync with the model */
+ g_assert (expander != NULL);
+
+ /* get the box widget that holds the shortcut row */
+ box = gtk_bin_get_child (GTK_BIN (expander));
+
+ /* get a list of all shortcut rows */
+ rows = gtk_container_get_children (GTK_CONTAINER (box));
+
+ /* get the shortcut row we want to update */
+ row_element = g_list_nth (rows, shortcut_index);
+ if (row_element != NULL)
+ {
+ /* cast so that we have a proper row object to work with */
+ row = THUNAR_SHORTCUT_ROW (row_element->data);
+
+ /* read updated information from the tree row */
+ /* TODO also read the ThunarFile if we have one etc. */
+ gtk_tree_model_get (model, iter,
+ THUNAR_SHORTCUTS_MODEL_COLUMN_NAME, &name,
+ THUNAR_SHORTCUTS_MODEL_COLUMN_ICON, &icon,
+ -1);
+
+ /* update the row */
+ g_object_set (row,
+ "name", name,
+ "icon", icon,
+ NULL);
+
+ /* release the values */
+ g_free (name);
+ g_object_unref (icon);
+ }
+
+ /* free the row list */
+ g_list_free (rows);
+}
+
+
+
static GtkWidget *
thunar_shortcuts_view_get_expander_at (ThunarShortcutsView *view,
gint expander_index)
More information about the Xfce4-commits
mailing list