summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Schermer <nick@xfce.org>2013-07-28 21:36:45 +0200
committerNick Schermer <nick@xfce.org>2013-07-28 21:54:31 +0200
commit1f0729aa3e21810f40a80cfed1b476200bd2556d (patch)
treea0e98cfcba958b16fd9521b7d9c74dbf5b99ba41 /src
parentbb905554342c0442f3011bca4200fd386557147d (diff)
downloadxfce4-appfinder-1f0729aa3e21810f40a80cfed1b476200bd2556d.tar.gz
Add bookmarks in the model.
Diffstat (limited to 'src')
-rw-r--r--src/appfinder-category-model.c4
-rw-r--r--src/appfinder-model.c540
-rw-r--r--src/appfinder-model.h57
-rw-r--r--src/appfinder-window.c62
4 files changed, 559 insertions, 104 deletions
diff --git a/src/appfinder-category-model.c b/src/appfinder-category-model.c
index 3f3a060..57e0e55 100644
--- a/src/appfinder-category-model.c
+++ b/src/appfinder-category-model.c
@@ -529,6 +529,10 @@ xfce_appfinder_category_model_set_categories (XfceAppfinderCategoryModel *model,
model->categories = g_slist_prepend (model->categories, item);
item = g_slice_new0 (CategoryItem);
+ item->directory = xfce_appfinder_model_get_bookmarks_category ();
+ model->categories = g_slist_prepend (model->categories, item);
+
+ item = g_slice_new0 (CategoryItem);
item->directory = g_object_ref (G_OBJECT (model->all_applications));
model->categories = g_slist_prepend (model->categories, item);
diff --git a/src/appfinder-model.c b/src/appfinder-model.c
index 50de137..355c2eb 100644
--- a/src/appfinder-model.c
+++ b/src/appfinder-model.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Nick Schermer <nick@xfce.org>
+ * Copyright (C) 2011-2013 Nick Schermer <nick@xfce.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,64 +33,73 @@
-#define HISTORY_PATH "xfce4/xfce4-appfinder/history"
-
-
-
-static void xfce_appfinder_model_tree_model_init (GtkTreeModelIface *iface);
-static void xfce_appfinder_model_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void xfce_appfinder_model_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void xfce_appfinder_model_finalize (GObject *object);
-static GtkTreeModelFlags xfce_appfinder_model_get_flags (GtkTreeModel *tree_model);
-static gint xfce_appfinder_model_get_n_columns (GtkTreeModel *tree_model);
-static GType xfce_appfinder_model_get_column_type (GtkTreeModel *tree_model,
- gint column);
-static gboolean xfce_appfinder_model_get_iter (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreePath *path);
-static GtkTreePath *xfce_appfinder_model_get_path (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static void xfce_appfinder_model_get_value (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gint column,
- GValue *value);
-static gboolean xfce_appfinder_model_iter_next (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gboolean xfce_appfinder_model_iter_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent);
-static gboolean xfce_appfinder_model_iter_has_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gint xfce_appfinder_model_iter_n_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gboolean xfce_appfinder_model_iter_nth_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent,
- gint n);
-static gboolean xfce_appfinder_model_iter_parent (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *child);
-static void xfce_appfinder_model_menu_changed (GarconMenu *menu,
- XfceAppfinderModel *model);
-static gpointer xfce_appfinder_model_collect_thread (gpointer user_data);
-static void xfce_appfinder_model_item_changed (GarconMenuItem *menu_item,
- XfceAppfinderModel *model);
-static void xfce_appfinder_model_item_free (gpointer data,
- XfceAppfinderModel *model);
-static void xfce_appfinder_model_history_changed (GFileMonitor *monitor,
- GFile *file,
- GFile *other_file,
- GFileMonitorEvent event_type,
- XfceAppfinderModel *model);
-static void xfce_appfinder_model_history_monitor_stop (XfceAppfinderModel *model);
-static void xfce_appfinder_model_history_monitor (XfceAppfinderModel *model,
- const gchar *path);
+#define HISTORY_PATH "xfce4/xfce4-appfinder/history"
+#define BOOKMARKS_PATH "xfce4/appfinder/bookmarks"
+
+
+
+static void xfce_appfinder_model_tree_model_init (GtkTreeModelIface *iface);
+static void xfce_appfinder_model_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void xfce_appfinder_model_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void xfce_appfinder_model_finalize (GObject *object);
+static GtkTreeModelFlags xfce_appfinder_model_get_flags (GtkTreeModel *tree_model);
+static gint xfce_appfinder_model_get_n_columns (GtkTreeModel *tree_model);
+static GType xfce_appfinder_model_get_column_type (GtkTreeModel *tree_model,
+ gint column);
+static gboolean xfce_appfinder_model_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path);
+static GtkTreePath *xfce_appfinder_model_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static void xfce_appfinder_model_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gint column,
+ GValue *value);
+static gboolean xfce_appfinder_model_iter_next (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static gboolean xfce_appfinder_model_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent);
+static gboolean xfce_appfinder_model_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static gint xfce_appfinder_model_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static gboolean xfce_appfinder_model_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ gint n);
+static gboolean xfce_appfinder_model_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child);
+static void xfce_appfinder_model_menu_changed (GarconMenu *menu,
+ XfceAppfinderModel *model);
+static gpointer xfce_appfinder_model_collect_thread (gpointer user_data);
+static void xfce_appfinder_model_item_changed (GarconMenuItem *menu_item,
+ XfceAppfinderModel *model);
+static void xfce_appfinder_model_item_free (gpointer data,
+ XfceAppfinderModel *model);
+static void xfce_appfinder_model_history_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ XfceAppfinderModel *model);
+static void xfce_appfinder_model_history_monitor_stop (XfceAppfinderModel *model);
+static void xfce_appfinder_model_history_monitor (XfceAppfinderModel *model,
+ const gchar *path);
+static void xfce_appfinder_model_bookmarks_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ XfceAppfinderModel *model);
+static void xfce_appfinder_model_bookmarks_monitor_stop (XfceAppfinderModel *model);
+static void xfce_appfinder_model_bookmarks_monitor (XfceAppfinderModel *model,
+ const gchar *path);
@@ -102,11 +111,18 @@ struct _XfceAppfinderModelClass
struct _XfceAppfinderModel
{
GObject __parent__;
+
gint stamp;
GSList *items;
GHashTable *items_hash;
+ GHashTable *bookmarks_hash;
+
+ GFileMonitor *bookmarks_monitor;
+ GFile *bookmarks_file;
+ guint64 bookmarks_mtime;
+
GarconMenu *menu;
guint menu_changed_idle_id;
@@ -139,6 +155,7 @@ typedef struct
gchar *command;
gchar *tooltip;
guint not_visible : 1;
+ guint is_bookmark : 1;
GdkPixbuf *icon;
GdkPixbuf *icon_large;
@@ -211,6 +228,7 @@ xfce_appfinder_model_init (XfceAppfinderModel *model)
/* generate a unique stamp */
model->stamp = g_random_int ();
model->items_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ model->bookmarks_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
model->icon_size = XFCE_APPFINDER_ICON_SIZE_DEFAULT_ITEM;
model->command_icon = xfce_appfinder_model_load_pixbuf (GTK_STOCK_EXECUTE, model->icon_size);
model->command_icon_large = xfce_appfinder_model_load_pixbuf (GTK_STOCK_EXECUTE, XFCE_APPFINDER_ICON_SIZE_48);
@@ -247,6 +265,7 @@ xfce_appfinder_model_tree_model_init (GtkTreeModelIface *iface)
}
+
static void
xfce_appfinder_model_get_property (GObject *object,
guint prop_id,
@@ -323,6 +342,9 @@ xfce_appfinder_model_finalize (GObject *object)
/* stop history file monitoring */
xfce_appfinder_model_history_monitor_stop (model);
+ /* stop monitoring bookmarks file */
+ xfce_appfinder_model_bookmarks_monitor_stop (model);
+
g_signal_handlers_disconnect_by_func (G_OBJECT (model->menu),
G_CALLBACK (xfce_appfinder_model_menu_changed), model);
g_object_unref (G_OBJECT (model->menu));
@@ -338,6 +360,7 @@ xfce_appfinder_model_finalize (GObject *object)
g_slist_free (model->categories);
g_hash_table_destroy (model->items_hash);
+ g_hash_table_destroy (model->bookmarks_hash);
g_object_unref (G_OBJECT (model->command_icon_large));
g_object_unref (G_OBJECT (model->command_icon));
@@ -383,6 +406,9 @@ xfce_appfinder_model_get_column_type (GtkTreeModel *tree_model,
case XFCE_APPFINDER_MODEL_COLUMN_ICON_LARGE:
return GDK_TYPE_PIXBUF;
+ case XFCE_APPFINDER_MODEL_COLUMN_BOOKMARK:
+ return G_TYPE_BOOLEAN;
+
default:
g_assert_not_reached ();
return G_TYPE_INVALID;
@@ -566,6 +592,11 @@ xfce_appfinder_model_get_value (GtkTreeModel *tree_model,
g_value_take_string (value, garcon_menu_item_get_uri (item->item));
break;
+ case XFCE_APPFINDER_MODEL_COLUMN_BOOKMARK:
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, item->is_bookmark);
+ break;
+
default:
g_assert_not_reached ();
break;
@@ -699,6 +730,7 @@ xfce_appfinder_model_collect_idle (gpointer user_data)
GSList *li, *lnext;
GSList *tmp;
ModelItem *item;
+ const gchar *desktop_id;
appfinder_return_val_if_fail (XFCE_IS_APPFINDER_MODEL (model), FALSE);
appfinder_return_val_if_fail (model->items == NULL, FALSE);
@@ -734,8 +766,13 @@ xfce_appfinder_model_collect_idle (gpointer user_data)
/* watch changes */
item = li->data;
if (item->item != NULL)
- g_signal_connect (G_OBJECT (item->item), "changed",
- G_CALLBACK (xfce_appfinder_model_item_changed), model);
+ {
+ g_signal_connect (G_OBJECT (item->item), "changed",
+ G_CALLBACK (xfce_appfinder_model_item_changed), model);
+
+ desktop_id = garcon_menu_item_get_desktop_id (item->item);
+ item->is_bookmark = g_hash_table_lookup (model->bookmarks_hash, desktop_id) != NULL;
+ }
/* insert in hash table */
if (G_LIKELY (item->command != NULL))
@@ -881,6 +918,7 @@ xfce_appfinder_model_item_changed (GarconMenuItem *menu_item,
GtkTreePath *path;
GPtrArray *categories;
gboolean old_not_visible;
+ const gchar *desktop_id;
/* lookup the item in the list */
for (li = model->items, idx = 0; li != NULL; li = li->next, idx++)
@@ -901,6 +939,13 @@ xfce_appfinder_model_item_changed (GarconMenuItem *menu_item,
item->categories = categories;
li->data = item;
+ /* check if the item should be a bookmark */
+ desktop_id = garcon_menu_item_get_desktop_id (menu_item);
+ if (desktop_id != NULL)
+ item->is_bookmark = g_hash_table_lookup (model->bookmarks_hash, desktop_id) != NULL;
+ else
+ item->is_bookmark = FALSE;
+
if (G_LIKELY (item->command != NULL))
g_hash_table_insert (model->items_hash, item->command, item);
@@ -992,7 +1037,7 @@ xfce_appfinder_model_history_remove_items (XfceAppfinderModel *model)
static guint64
-xfce_appfinder_model_history_get_mtime (GFile *file)
+xfce_appfinder_model_file_get_mtime (GFile *file)
{
GFileInfo *info;
guint64 mtime = 0;
@@ -1008,11 +1053,12 @@ xfce_appfinder_model_history_get_mtime (GFile *file)
}
}
- /* never return 1, because we use that for an empty history */
+ /* never return 1, because we use that for an empty file */
return MAX (mtime, 1);
}
+
static void
xfce_appfinder_model_history_insert (XfceAppfinderModel *model,
const gchar *command)
@@ -1079,7 +1125,7 @@ xfce_appfinder_model_history_changed (GFileMonitor *monitor,
break;
case G_FILE_MONITOR_EVENT_CREATED:
- mtime = xfce_appfinder_model_history_get_mtime (model->history_file);
+ mtime = xfce_appfinder_model_file_get_mtime (model->history_file);
if (mtime > model->history_mtime)
{
/* read the new file and update the commands */
@@ -1182,7 +1228,185 @@ xfce_appfinder_model_history_monitor (XfceAppfinderModel *model,
}
}
- model->history_mtime = xfce_appfinder_model_history_get_mtime (file);
+ model->history_mtime = xfce_appfinder_model_file_get_mtime (file);
+
+ g_object_unref (G_OBJECT (file));
+}
+
+
+static void
+xfce_appfinder_model_bookmarks_collect (XfceAppfinderModel *model,
+ GMappedFile *mmap)
+{
+ gchar *line;
+ gchar *end;
+ gchar *contents;
+
+ /* empty the database */
+ g_hash_table_remove_all (model->bookmarks_hash);
+
+ contents = g_mapped_file_get_contents (mmap);
+ if (contents == NULL)
+ return;
+
+ /* walk the file */
+ for (;!g_cancellable_is_cancelled (model->collect_cancelled);)
+ {
+ end = strchr (contents, '\n');
+ if (G_UNLIKELY (end == NULL))
+ break;
+
+ if (end != contents)
+ {
+ /* look for new commands */
+ line = g_strndup (contents, end - contents);
+ g_hash_table_insert (model->bookmarks_hash, line, GUINT_TO_POINTER (1));
+ }
+ contents = end + 1;
+ }
+}
+
+
+
+static void
+xfce_appfinder_model_bookmarks_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ XfceAppfinderModel *model)
+{
+ guint64 mtime;
+ gchar *filename;
+ GError *error = NULL;
+ GMappedFile *mmap;
+ gboolean is_bookmark;
+ ModelItem *item;
+ GSList *li;
+ const gchar *desktop_id;
+ gint idx;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ appfinder_return_if_fail (XFCE_IS_APPFINDER_MODEL (model));
+ appfinder_return_if_fail (model->bookmarks_monitor == monitor);
+ appfinder_return_if_fail (G_IS_FILE_MONITOR (monitor));
+ appfinder_return_if_fail (G_IS_FILE (model->bookmarks_file));
+
+ switch (event_type)
+ {
+ case G_FILE_MONITOR_EVENT_DELETED:
+ /* TODO */
+ break;
+
+ case G_FILE_MONITOR_EVENT_CREATED:
+ mtime = xfce_appfinder_model_file_get_mtime (model->bookmarks_file);
+ if (mtime > model->bookmarks_mtime)
+ {
+ APPFINDER_DEBUG ("bookmarks file changed");
+
+ /* read the new file and update the commands */
+ filename = g_file_get_path (file);
+ mmap = g_mapped_file_new (filename, FALSE, &error);
+ g_free (filename);
+
+ if (G_LIKELY (mmap != NULL))
+ {
+ xfce_appfinder_model_bookmarks_collect (model, mmap);
+ g_mapped_file_unref (mmap);
+
+ /* update the model items */
+ for (idx = 0, li = model->items; li != NULL; li = li->next, idx++)
+ {
+ item = li->data;
+ if (item->item == NULL)
+ continue;
+
+ /* check if the item should be a bookmark */
+ desktop_id = garcon_menu_item_get_desktop_id (item->item);
+ if (desktop_id != NULL)
+ is_bookmark = g_hash_table_lookup (model->bookmarks_hash, desktop_id) != NULL;
+ else
+ is_bookmark = FALSE;
+
+ if (item->is_bookmark != is_bookmark)
+ {
+ APPFINDER_DEBUG ("bookmark %s changed", desktop_id);
+
+ item->is_bookmark = is_bookmark;
+
+ /* let model know what happened */
+ path = gtk_tree_path_new_from_indices (idx, -1);
+ ITER_INIT (iter, model->stamp, li);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_free (path);
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+static void
+xfce_appfinder_model_bookmarks_monitor_stop (XfceAppfinderModel *model)
+{
+ if (model->bookmarks_monitor != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (model->bookmarks_monitor,
+ G_CALLBACK (xfce_appfinder_model_bookmarks_changed), model);
+
+ g_object_unref (G_OBJECT (model->bookmarks_monitor));
+ model->bookmarks_monitor = NULL;
+ }
+
+ if (model->bookmarks_file != NULL)
+ {
+ g_object_unref (G_OBJECT (model->bookmarks_file));
+ model->bookmarks_file = NULL;
+ }
+}
+
+
+
+static void
+xfce_appfinder_model_bookmarks_monitor (XfceAppfinderModel *model,
+ const gchar *path)
+{
+ GFile *file;
+ GError *error = NULL;
+
+ file = g_file_new_for_path (path);
+
+ if (model->bookmarks_file == NULL
+ || model->bookmarks_monitor == NULL
+ || !g_file_equal (file, model->bookmarks_file))
+ {
+ xfce_appfinder_model_bookmarks_monitor_stop (model);
+
+ /* monitor the file for changes */
+ model->bookmarks_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, model->collect_cancelled, &error);
+ appfinder_refcount_debug_add (G_OBJECT (model->bookmarks_monitor), "bookmarks file monitor");
+ if (model->bookmarks_monitor != NULL)
+ {
+ APPFINDER_DEBUG ("monitor bookmarks file %s", path);
+
+ model->bookmarks_file = g_object_ref (G_OBJECT (file));
+ g_signal_connect (G_OBJECT (model->bookmarks_monitor), "changed",
+ G_CALLBACK (xfce_appfinder_model_bookmarks_changed), model);
+ }
+ else
+ {
+ g_warning ("Failed to setup a monitor for %s: %s", path, error->message);
+ g_error_free (error);
+ }
+ }
+
+ model->bookmarks_mtime = xfce_appfinder_model_file_get_mtime (file);
g_object_unref (G_OBJECT (file));
}
@@ -1269,8 +1493,10 @@ xfce_appfinder_model_collect_item (const gchar *desktop_id,
item->categories = g_ptr_array_new_with_free_func (g_object_unref);
if (context->category != NULL)
- g_ptr_array_add (item->categories,
- g_object_ref (G_OBJECT (context->category)));
+ {
+ g_ptr_array_add (item->categories,
+ g_object_ref (G_OBJECT (context->category)));
+ }
context->items = g_slist_prepend (context->items, item);
g_hash_table_insert (context->desktop_ids, (gchar *) desktop_id, item);
@@ -1592,7 +1818,7 @@ xfce_appfinder_model_collect_thread (gpointer user_data)
XfceAppfinderModel *model = XFCE_APPFINDER_MODEL (user_data);
GError *error = NULL;
gchar *filename;
- GMappedFile *history;
+ GMappedFile *mmap;
appfinder_return_val_if_fail (GARCON_IS_MENU (model->menu), NULL);
appfinder_return_val_if_fail (model->collect_items == NULL, NULL);
@@ -1605,8 +1831,10 @@ xfce_appfinder_model_collect_thread (gpointer user_data)
{
if (garcon_menu_load (model->menu, model->collect_cancelled, &error))
{
- xfce_appfinder_model_collect_menu (model->menu, model->collect_cancelled,
- &model->collect_items, &model->collect_categories);
+ xfce_appfinder_model_collect_menu (model->menu,
+ model->collect_cancelled,
+ &model->collect_items,
+ &model->collect_categories);
}
else
{
@@ -1621,11 +1849,11 @@ xfce_appfinder_model_collect_thread (gpointer user_data)
{
APPFINDER_DEBUG ("load commands from %s", filename);
- history = g_mapped_file_new (filename, FALSE, &error);
- if (G_LIKELY (history != NULL))
+ mmap = g_mapped_file_new (filename, FALSE, &error);
+ if (G_LIKELY (mmap != NULL))
{
- xfce_appfinder_model_collect_history (model, history);
- g_mapped_file_unref (history);
+ xfce_appfinder_model_collect_history (model, mmap);
+ g_mapped_file_unref (mmap);
}
else
{
@@ -1639,6 +1867,30 @@ xfce_appfinder_model_collect_thread (gpointer user_data)
g_free (filename);
}
+ /* load bookmarks */
+ filename = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, BOOKMARKS_PATH);
+ if (G_LIKELY (filename != NULL))
+ {
+ APPFINDER_DEBUG ("load bookmarks from %s", filename);
+
+ mmap = g_mapped_file_new (filename, FALSE, &error);
+ if (G_LIKELY (mmap != NULL))
+ {
+ xfce_appfinder_model_bookmarks_collect (model, mmap);
+ g_mapped_file_unref (mmap);
+ }
+ else
+ {
+ g_warning ("Failed to open bookmarks file: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ /* start monitoring and update mtime */
+ xfce_appfinder_model_bookmarks_monitor (model, filename);
+
+ g_free (filename);
+ }
+
if (model->collect_items != NULL
&& !g_cancellable_is_cancelled (model->collect_cancelled))
{
@@ -1732,6 +1984,8 @@ xfce_appfinder_model_get_visible (XfceAppfinderModel *model,
const gchar *string)
{
ModelItem *item;
+ GarconMenuDirectory *bookmarks;
+ gboolean in_category;
appfinder_return_val_if_fail (XFCE_IS_APPFINDER_MODEL (model), FALSE);
appfinder_return_val_if_fail (iter->stamp == model->stamp, FALSE);
@@ -1747,9 +2001,22 @@ xfce_appfinder_model_get_visible (XfceAppfinderModel *model,
if (item->not_visible)
return FALSE;
- if (category != NULL
- && !xfce_appfinder_model_ptr_array_find (item->categories, category))
- return FALSE;
+ if (category != NULL)
+ {
+ if (!xfce_appfinder_model_ptr_array_find (item->categories, category))
+ {
+ in_category = FALSE;
+ if (item->is_bookmark)
+ {
+ bookmarks = xfce_appfinder_model_get_bookmarks_category ();
+ in_category = (bookmarks == category);
+ g_object_unref (G_OBJECT (bookmarks));
+ }
+
+ if (!in_category)
+ return FALSE;
+ }
+ }
if (string != NULL
&& item->key != NULL)
@@ -1979,6 +2246,7 @@ xfce_appfinder_model_save_command (XfceAppfinderModel *model,
static gsize old_len = 0;
appfinder_return_val_if_fail (XFCE_IS_APPFINDER_MODEL (model), FALSE);
+ appfinder_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!IS_STRING (command)
|| g_hash_table_lookup (model->items_hash, command) != NULL)
@@ -2142,6 +2410,100 @@ xfce_appfinder_model_history_clear (XfceAppfinderModel *model)
+gboolean
+xfce_appfinder_model_bookmark_toggle (XfceAppfinderModel *model,
+ const gchar *desktop_id,
+ GError **error)
+{
+ ModelItem *item;
+ GSList *li;
+ const gchar *desktop_id2;
+ static gsize old_len = 0;
+ GString *contents;
+ gchar *filename;
+ gboolean succeed;
+ GtkTreePath *path;
+ gint idx;
+ GtkTreeIter iter;
+
+ appfinder_return_val_if_fail (XFCE_IS_APPFINDER_MODEL (model), FALSE);
+ appfinder_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ appfinder_return_val_if_fail (desktop_id != NULL, FALSE);
+
+ if (g_hash_table_lookup (model->bookmarks_hash, desktop_id) == NULL)
+ g_hash_table_insert (model->bookmarks_hash, g_strdup (desktop_id), GUINT_TO_POINTER (1));
+ else
+ g_hash_table_remove (model->bookmarks_hash, desktop_id);
+
+ /* string to store custom commands */
+ contents = g_string_sized_new (old_len);
+
+ /* update the model items */
+ for (idx = 0, li = model->items; li != NULL; li = li->next, idx++)
+ {
+ item = li->data;
+ if (item->item == NULL)
+ continue;
+
+ /* find the item we're trying to add/remove */
+ if (desktop_id != NULL)
+ {
+ desktop_id2 = garcon_menu_item_get_desktop_id (item->item);
+ if (desktop_id2 != NULL
+ && strcmp (desktop_id2, desktop_id) == 0)
+ {
+ /* toggle state */
+ item->is_bookmark = !item->is_bookmark;
+
+ /* stop searching, continue collecting */
+ desktop_id = NULL;
+
+ /* update model */
+ path = gtk_tree_path_new_from_indices (idx, -1);
+ ITER_INIT (iter, model->stamp, li);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_free (path);
+ }
+ }
+
+ /* collect bookmarked items */
+ if (item->is_bookmark)
+ {
+ desktop_id2 = garcon_menu_item_get_desktop_id (item->item);
+ if (G_LIKELY (desktop_id2 != NULL))
+ {
+ g_string_append (contents, desktop_id2);
+ g_string_append_c (contents, '\n');
+ }
+ }
+ }
+
+ APPFINDER_DEBUG ("saving bookmarks");
+
+ /* write new bookmarks */
+ filename = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, BOOKMARKS_PATH, TRUE);
+ if (G_LIKELY (filename != NULL))
+ succeed = g_file_set_contents (filename, contents->str, contents->len, error);
+ else
+ g_set_error_literal (error, 0, 0, "Unable to create bookmarks file");
+
+ if (succeed)
+ {
+ /* possible restart monitoring and update mtime */
+ xfce_appfinder_model_bookmarks_monitor (model, filename);
+ }
+
+ /* optimization for next run */
+ old_len = contents->allocated_len;
+
+ g_free (filename);
+ g_string_free (contents, TRUE);
+
+ return succeed;
+}
+
+
+
GarconMenuDirectory *
xfce_appfinder_model_get_command_category (void)
{
@@ -2163,3 +2525,27 @@ xfce_appfinder_model_get_command_category (void)
return category;
}
+
+
+
+GarconMenuDirectory *
+xfce_appfinder_model_get_bookmarks_category (void)
+{
+ static GarconMenuDirectory *category = NULL;
+
+ if (G_LIKELY (category != NULL))
+ {
+ g_object_ref (G_OBJECT (category));
+ }
+ else
+ {
+ category = g_object_new (GARCON_TYPE_MENU_DIRECTORY,
+ "name", _("Bookmarks"),
+ "icon-name", "user-bookmarks",
+ NULL);
+ appfinder_refcount_debug_add (G_OBJECT (category), "bookmarks");
+ g_object_add_weak_pointer (G_OBJECT (category), (gpointer) &category);
+ }
+
+ return category;
+}
diff --git a/src/appfinder-model.h b/src/appfinder-model.h
index 2b31cf8..9a96f2e 100644
--- a/src/appfinder-model.h
+++ b/src/appfinder-model.h
@@ -42,6 +42,7 @@ enum
XFCE_APPFINDER_MODEL_COLUMN_ICON_LARGE,
XFCE_APPFINDER_MODEL_COLUMN_COMMAND,
XFCE_APPFINDER_MODEL_COLUMN_URI,
+ XFCE_APPFINDER_MODEL_COLUMN_BOOKMARK,
XFCE_APPFINDER_MODEL_COLUMN_TOOLTIP,
XFCE_APPFINDER_MODEL_N_COLUMNS,
};
@@ -64,42 +65,48 @@ XfceAppfinderIconSize;
-GType xfce_appfinder_model_get_type (void) G_GNUC_CONST;
+GType xfce_appfinder_model_get_type (void) G_GNUC_CONST;
-XfceAppfinderModel *xfce_appfinder_model_get (void) G_GNUC_MALLOC;
+XfceAppfinderModel *xfce_appfinder_model_get (void) G_GNUC_MALLOC;
-GSList *xfce_appfinder_model_get_categories (XfceAppfinderModel *model);
+GSList *xfce_appfinder_model_get_categories (XfceAppfinderModel *model);
-gboolean xfce_appfinder_model_get_visible (XfceAppfinderModel *model,
- const GtkTreeIter *iter,
- const GarconMenuDirectory *category,
- const gchar *string);
+gboolean xfce_appfinder_model_get_visible (XfceAppfinderModel *model,
+ const GtkTreeIter *iter,
+ const GarconMenuDirectory *category,
+ const gchar *string);
-gboolean xfce_appfinder_model_get_visible_command (XfceAppfinderModel *model,
- const GtkTreeIter *iter,
- const gchar *string);
+gboolean xfce_appfinder_model_get_visible_command (XfceAppfinderModel *model,
+ const GtkTreeIter *iter,
+ const gchar *string);
-gboolean xfce_appfinder_model_execute (XfceAppfinderModel *model,
- const GtkTreeIter *iter,
- GdkScreen *screen,
- gboolean *is_regular_command,
- GError **error);
+gboolean xfce_appfinder_model_execute (XfceAppfinderModel *model,
+ const GtkTreeIter *iter,
+ GdkScreen *screen,
+ gboolean *is_regular_command,
+ GError **error);
-GdkPixbuf *xfce_appfinder_model_load_pixbuf (const gchar *icon_name,
- XfceAppfinderIconSize icon_size) G_GNUC_MALLOC;
+GdkPixbuf *xfce_appfinder_model_load_pixbuf (const gchar *icon_name,
+ XfceAppfinderIconSize icon_size) G_GNUC_MALLOC;
-gboolean xfce_appfinder_model_save_command (XfceAppfinderModel *model,
- const gchar *command,
- GError **error);
+gboolean xfce_appfinder_model_save_command (XfceAppfinderModel *model,
+ const gchar *command,
+ GError **error);
-GdkPixbuf *xfce_appfinder_model_get_icon_for_command (XfceAppfinderModel *model,
- const gchar *command);
+GdkPixbuf *xfce_appfinder_model_get_icon_for_command (XfceAppfinderModel *model,
+ const gchar *command);
-void xfce_appfinder_model_icon_theme_changed (XfceAppfinderModel *model);
+void xfce_appfinder_model_icon_theme_changed (XfceAppfinderModel *model);
-GarconMenuDirectory *xfce_appfinder_model_get_command_category (void);
+void xfce_appfinder_model_history_clear (XfceAppfinderModel *model);
-void xfce_appfinder_model_history_clear (XfceAppfinderModel *model);
+gboolean xfce_appfinder_model_bookmark_toggle (XfceAppfinderModel *model,
+ const gchar *desktop_id,
+ GError **error);
+
+GarconMenuDirectory *xfce_appfinder_model_get_command_category (void);
+
+GarconMenuDirectory *xfce_appfinder_model_get_bookmarks_category (void);
G_END_DECLS
diff --git a/src/appfinder-window.c b/src/appfinder-window.c
index b5ca272..f656a1c 100644
--- a/src/appfinder-window.c
+++ b/src/appfinder-window.c
@@ -813,6 +813,42 @@ xfce_appfinder_window_view_get_selected (XfceAppfinderWindow *window,
static void
+xfce_appfinder_window_popup_menu_toggle_bookmark (GtkWidget *mi,
+ XfceAppfinderWindow *window)
+{
+ const gchar *uri;
+ GFile *gfile;
+ gchar *desktop_id;
+ GtkWidget *menu = gtk_widget_get_parent (mi);
+ GtkTreeModel *filter;
+ GtkTreeModel *model;
+ GError *error = NULL;
+
+ uri = g_object_get_data (G_OBJECT (menu), "uri");
+ if (uri != NULL)
+ {
+ gfile = g_file_new_for_uri (uri);
+ desktop_id = g_file_get_basename (gfile);
+ g_object_unref (G_OBJECT (gfile));
+
+ /* toggle bookmarks */
+ filter = g_object_get_data (G_OBJECT (menu), "model");
+ model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter));
+ xfce_appfinder_model_bookmark_toggle (XFCE_APPFINDER_MODEL (model), desktop_id, &error);
+
+ g_free (desktop_id);
+
+ if (G_UNLIKELY (error != NULL))
+ {
+ g_printerr ("%s: failed to save bookmarks: %s\n", G_LOG_DOMAIN, error->message);
+ g_error_free (error);
+ }
+ }
+}
+
+
+
+static void
xfce_appfinder_window_popup_menu_execute (GtkWidget *mi,
XfceAppfinderWindow *window)
{
@@ -960,14 +996,18 @@ xfce_appfinder_window_popup_menu (GtkWidget *view,
gchar *title;
gchar *uri;
GtkWidget *mi;
+ GtkWidget *image;
gchar *path;
gboolean uri_is_local;
+ gboolean is_bookmark;
if (xfce_appfinder_window_view_get_selected (window, &model, &iter))
{
gtk_tree_model_get (model, &iter,
XFCE_APPFINDER_MODEL_COLUMN_TITLE, &title,
- XFCE_APPFINDER_MODEL_COLUMN_URI, &uri, -1);
+ XFCE_APPFINDER_MODEL_COLUMN_URI, &uri,
+ XFCE_APPFINDER_MODEL_COLUMN_BOOKMARK, &is_bookmark,
+ -1);
/* custom command don't have an uri */
if (uri == NULL)
@@ -981,6 +1021,7 @@ xfce_appfinder_window_popup_menu (GtkWidget *view,
menu = gtk_menu_new ();
g_object_set_data_full (G_OBJECT (menu), "uri", uri, g_free);
g_object_set_data_full (G_OBJECT (menu), "name", title, g_free);
+ g_object_set_data (G_OBJECT (menu), "model", model);
g_signal_connect (G_OBJECT (menu), "selection-done",
G_CALLBACK (gtk_widget_destroy), NULL);
@@ -993,6 +1034,22 @@ xfce_appfinder_window_popup_menu (GtkWidget *view,
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
gtk_widget_show (mi);
+ mi = gtk_image_menu_item_new_with_mnemonic (is_bookmark ? _("Remove From Bookmarks") : _("Add to Bookmarks"));
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+ g_signal_connect (G_OBJECT (mi), "activate",
+ G_CALLBACK (xfce_appfinder_window_popup_menu_toggle_bookmark), window);
+ gtk_widget_show (mi);
+
+ if (is_bookmark)
+ image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
+ else
+ image = gtk_image_new_from_icon_name ("bookmark-new", GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
+
+ mi = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+ gtk_widget_show (mi);
+
mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_EXECUTE, NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
g_signal_connect (G_OBJECT (mi), "activate",
@@ -1479,7 +1536,8 @@ xfce_appfinder_window_item_visible (GtkTreeModel *model,
XfceAppfinderWindow *window = XFCE_APPFINDER_WINDOW (data);
return xfce_appfinder_model_get_visible (XFCE_APPFINDER_MODEL (model), iter,
- window->filter_category, window->filter_text);
+ window->filter_category,
+ window->filter_text);
}