diff options
author | Mahmoud Khalil <mahmoudkhalil11@gmail.com> | 2020-02-16 23:57:46 +0200 |
---|---|---|
committer | Andre Miranda <andreldm@xfce.org> | 2020-05-21 23:39:06 -0300 |
commit | ddea0a250d36b66942ff514d8ca2c2b3557eaa5b (patch) | |
tree | 3b642e838e25140c16342fd6a4920d0437fdc2f4 /src | |
parent | 84370279a53999e0de970eb7ae69464cecc90ee3 (diff) | |
download | xfce4-appfinder-ddea0a250d36b66942ff514d8ca2c2b3557eaa5b.tar.gz |
Sort by frecency (Bug #9265)
Co-authored-by: Andre Miranda <andreldm@xfce.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/appfinder-model.c | 299 | ||||
-rw-r--r-- | src/appfinder-model.h | 9 | ||||
-rw-r--r-- | src/appfinder-preferences.c | 6 | ||||
-rw-r--r-- | src/appfinder-preferences.glade | 17 | ||||
-rw-r--r-- | src/appfinder-window.c | 72 | ||||
-rw-r--r-- | src/main.c | 3 |
6 files changed, 396 insertions, 10 deletions
diff --git a/src/appfinder-model.c b/src/appfinder-model.c index 7a2bb7b..35c34cd 100644 --- a/src/appfinder-model.c +++ b/src/appfinder-model.c @@ -35,6 +35,7 @@ #define HISTORY_PATH "xfce4/xfce4-appfinder/history" #define BOOKMARKS_PATH "xfce4/appfinder/bookmarks" +#define FRECENCY_PATH "xfce4/appfinder/frecency" static void xfce_appfinder_model_tree_model_init (GtkTreeModelIface *iface); @@ -102,6 +103,12 @@ static void xfce_appfinder_model_bookmarks_monitor (XfceAppfi static gboolean xfce_appfinder_model_fuzzy_match (const gchar *source, const gchar *token); +static gint xfce_appfinder_model_item_compare_frecency (gconstpointer a, + gconstpointer b, + gpointer data); +static void xfce_appfinder_model_frecency_collect (XfceAppfinderModel *model, + GMappedFile *mmap); +static void xfce_appfinder_model_frecency_free (gpointer data); struct _XfceAppfinderModelClass @@ -119,6 +126,7 @@ struct _XfceAppfinderModel GHashTable *items_hash; GHashTable *bookmarks_hash; + GHashTable *frecencies_hash; GFileMonitor *bookmarks_monitor; GFile *bookmarks_file; @@ -144,11 +152,20 @@ struct _XfceAppfinderModel GFile *history_file; guint64 history_mtime; + gboolean sort_by_frecency; + XfceAppfinderIconSize icon_size; }; typedef struct { + guint frequency; + guint64 recency; +} +Frecency; + +typedef struct +{ GarconMenuItem *item; gchar *key; gchar *abstract; @@ -158,6 +175,8 @@ typedef struct guint not_visible : 1; guint is_bookmark : 1; + Frecency *frecency; /* owned by frecencies_hash */ + GdkPixbuf *icon; GdkPixbuf *icon_large; } @@ -180,7 +199,8 @@ enum enum { PROP_0, - PROP_ICON_SIZE + PROP_ICON_SIZE, + PROP_SORT_BY_FRECENCY }; @@ -212,6 +232,12 @@ xfce_appfinder_model_class_init (XfceAppfinderModelClass *klass) XFCE_APPFINDER_ICON_SIZE_DEFAULT_ITEM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_SORT_BY_FRECENCY, + g_param_spec_boolean ("sort-by-frecency", NULL, NULL, + FALSE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + model_signals[CATEGORIES_CHANGED] = g_signal_new (g_intern_static_string ("categories-changed"), G_TYPE_FROM_CLASS (gobject_class), @@ -230,6 +256,7 @@ xfce_appfinder_model_init (XfceAppfinderModel *model) 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->frecencies_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, xfce_appfinder_model_frecency_free); model->icon_size = XFCE_APPFINDER_ICON_SIZE_DEFAULT_ITEM; model->command_icon = xfce_appfinder_model_load_pixbuf (XFCE_APPFINDER_STOCK_EXECUTE, model->icon_size); model->command_icon_large = xfce_appfinder_model_load_pixbuf (XFCE_APPFINDER_STOCK_EXECUTE, XFCE_APPFINDER_ICON_SIZE_48); @@ -281,6 +308,10 @@ xfce_appfinder_model_get_property (GObject *object, g_value_set_uint (value, model->icon_size); break; + case PROP_SORT_BY_FRECENCY: + g_value_set_boolean (value, model->sort_by_frecency); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -311,6 +342,10 @@ xfce_appfinder_model_set_property (GObject *object, } break; + case PROP_SORT_BY_FRECENCY: + model->sort_by_frecency = g_value_get_boolean (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -362,6 +397,7 @@ xfce_appfinder_model_finalize (GObject *object) g_hash_table_destroy (model->items_hash); g_hash_table_destroy (model->bookmarks_hash); + g_hash_table_destroy (model->frecencies_hash); g_object_unref (G_OBJECT (model->command_icon_large)); g_object_unref (G_OBJECT (model->command_icon)); @@ -410,6 +446,12 @@ xfce_appfinder_model_get_column_type (GtkTreeModel *tree_model, case XFCE_APPFINDER_MODEL_COLUMN_BOOKMARK: return G_TYPE_BOOLEAN; + case XFCE_APPFINDER_MODEL_COLUMN_FREQUENCY: + return G_TYPE_UINT; + + case XFCE_APPFINDER_MODEL_COLUMN_RECENCY: + return G_TYPE_UINT64; + default: g_assert_not_reached (); return G_TYPE_INVALID; @@ -598,6 +640,16 @@ xfce_appfinder_model_get_value (GtkTreeModel *tree_model, g_value_set_boolean (value, item->is_bookmark); break; + case XFCE_APPFINDER_MODEL_COLUMN_FREQUENCY: + g_value_init (value, G_TYPE_UINT); + g_value_set_uint (value, item->frecency ? item->frecency->frequency : 0); + break; + + case XFCE_APPFINDER_MODEL_COLUMN_RECENCY: + g_value_init (value, G_TYPE_UINT64); + g_value_set_uint64 (value, item->frecency ? item->frecency->recency : 0); + break; + default: g_assert_not_reached (); break; @@ -771,6 +823,7 @@ xfce_appfinder_model_collect_idle (gpointer user_data) desktop_id = garcon_menu_item_get_desktop_id (item->item); item->is_bookmark = g_hash_table_lookup (model->bookmarks_hash, desktop_id) != NULL; + item->frecency = g_hash_table_lookup (model->frecencies_hash, desktop_id); } /* insert in hash table */ @@ -939,7 +992,10 @@ xfce_appfinder_model_item_changed (GarconMenuItem *menu_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; + { + item->is_bookmark = g_hash_table_lookup (model->bookmarks_hash, desktop_id) != NULL; + item->frecency = g_hash_table_lookup (model->frecencies_hash, desktop_id); + } else item->is_bookmark = FALSE; @@ -1892,10 +1948,35 @@ xfce_appfinder_model_collect_thread (gpointer user_data) g_free (filename); } + /* load frecencies */ + filename = xfce_resource_lookup (XFCE_RESOURCE_CACHE, FRECENCY_PATH); + if (G_LIKELY (filename != NULL)) + { + APPFINDER_DEBUG ("load frecencies from %s", filename); + + mmap = g_mapped_file_new (filename, FALSE, &error); + if (G_LIKELY (mmap != NULL)) + { + xfce_appfinder_model_frecency_collect (model, mmap); + g_mapped_file_unref (mmap); + } + else + { + g_warning ("Failed to open frecencies file: %s", error->message); + g_clear_error (&error); + } + + g_free (filename); + } + if (model->collect_items != NULL && !g_cancellable_is_cancelled (model->collect_cancelled)) { - model->collect_items = g_slist_sort (model->collect_items, xfce_appfinder_model_item_compare); + if (model->sort_by_frecency) + model->collect_items = g_slist_sort_with_data (model->collect_items, xfce_appfinder_model_item_compare_frecency, model); + else + model->collect_items = g_slist_sort (model->collect_items, xfce_appfinder_model_item_compare); + model->collect_categories = g_slist_sort (model->collect_categories, xfce_appfinder_model_category_compare); model->collect_idle_id = gdk_threads_add_idle_full (G_PRIORITY_LOW, xfce_appfinder_model_collect_idle, @@ -1915,8 +1996,214 @@ xfce_appfinder_model_collect_thread (gpointer user_data) +static gint +xfce_appfinder_model_item_compare_frecency (gconstpointer a, + gconstpointer b, + gpointer data) +{ + const ModelItem *item_a = a, *item_b = b; + const gchar *desktop_id_a, *desktop_id_b; + XfceAppfinderModel *model; + Frecency *frecency_a, *frecency_b; + guint freq_a, freq_b, res_a, res_b; + guint64 rec_a, rec_b; + + if (item_a->item != NULL && item_b->item != NULL) + { + desktop_id_a = garcon_menu_item_get_desktop_id (item_a->item); + desktop_id_b = garcon_menu_item_get_desktop_id (item_b->item); + + if (desktop_id_a != NULL && desktop_id_b != NULL) + { + model = (XfceAppfinderModel *) data; + + frecency_a = g_hash_table_lookup (model->frecencies_hash, desktop_id_a); + frecency_b = g_hash_table_lookup (model->frecencies_hash, desktop_id_b); + + freq_a = frecency_a ? frecency_a->frequency : 0; + freq_b = frecency_b ? frecency_b->frequency : 0; + + rec_a = frecency_a ? frecency_a->recency : 0; + rec_b = frecency_b ? frecency_b->recency : 0; + + res_a = xfce_appfinder_model_calculate_frecency (freq_a, rec_a); + res_b = xfce_appfinder_model_calculate_frecency (freq_b, rec_b); + + if (res_b - res_a != 0) + return res_b - res_a; + } + } + + /* fallback to alphabetical order if desktop files are invalid + * or items have the same frecency */ + return xfce_appfinder_model_item_compare (a, b); +} + + + +static void +xfce_appfinder_model_frecency_collect (XfceAppfinderModel *model, + GMappedFile *mmap) +{ + gchar *line; + gchar **tokens; + gchar *end; + gchar *contents; + Frecency *frecency; + + 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) + { + line = g_strndup (contents, end - contents); + tokens = g_strsplit (line, ":", 3); + if (g_strv_length (tokens) == 3 && tokens[0] != NULL && tokens[1] != NULL && tokens[2] != NULL) + { + frecency = g_slice_new0 (Frecency); + frecency->frequency = g_ascii_strtoull (tokens[1], NULL, 0); + frecency->recency = g_ascii_strtoull (tokens[2], NULL, 0); + g_hash_table_insert (model->frecencies_hash, g_strdup (tokens[0]), frecency); + } + g_free (line); + g_strfreev (tokens); + } + contents = end + 1; + } +} + + + +static void +xfce_appfinder_model_frecency_free (gpointer data) +{ + g_slice_free (Frecency, data); +} + + + +guint +xfce_appfinder_model_calculate_frecency (guint frequency, + guint64 recency) +{ + GDateTime *date_time_now; + guint64 unix_time_now; + guint64 diff; + + /* get the current timestamp */ + date_time_now = g_date_time_new_now_local (); + unix_time_now = g_date_time_to_unix (date_time_now); + g_date_time_unref (date_time_now); + + diff = unix_time_now - recency; + + /* return frecency according to the frequency and how recent the item is */ + if (diff < 3600) return frequency * 4; + if (diff < 86400) return frequency * 2; + if (diff < 604800) return frequency / 2; + return frequency / 4; +} + + + +void +xfce_appfinder_model_update_frecency (XfceAppfinderModel *model, + const gchar *desktop_id, + GError **error) +{ + ModelItem *item; + GSList *li; + const gchar *item_desktop_id; + GString *frecency_contents; + gchar *filename; + GtkTreePath *path; + gint idx; + GtkTreeIter iter; + GDateTime *now; + + appfinder_return_if_fail (XFCE_IS_APPFINDER_MODEL (model)); + appfinder_return_if_fail (error == NULL || *error == NULL); + appfinder_return_if_fail (desktop_id != NULL); + + frecency_contents = g_string_sized_new (0); + + /* update the model items */ + for (idx = 0, li = model->items; li != NULL; li = li->next, idx++) + { + item = li->data; + if (item->item == NULL) + continue; + + item_desktop_id = garcon_menu_item_get_desktop_id (item->item); + if (item_desktop_id == NULL) + continue; + + if (item->frecency == NULL) + item->frecency = g_hash_table_lookup (model->frecencies_hash, item_desktop_id); + + if (item->frecency == NULL) + { + item->frecency = g_slice_new0 (Frecency); + item->frecency->frequency = 0; + item->frecency->recency = 0; + g_hash_table_insert (model->frecencies_hash, g_strdup (item_desktop_id), item->frecency); + } + + /* find the item we're trying to add/remove */ + if (desktop_id != NULL && g_strcmp0 (item_desktop_id, desktop_id) == 0) + { + /* update frequency */ + item->frecency->frequency++; + + /* update recency */ + now = g_date_time_new_now_local (); + item->frecency->recency = g_date_time_to_unix (now); + g_date_time_unref (now); + + /* 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 items' frecency */ + g_string_append (frecency_contents, g_strdup_printf ( + "%s:%" G_GUINT32_FORMAT ":%" G_GUINT64_FORMAT, + item_desktop_id, + item->frecency->frequency, + item->frecency->recency)); + g_string_append_c (frecency_contents, '\n'); + } + + APPFINDER_DEBUG ("saving frecencies"); + + /* write new frecencies */ + filename = xfce_resource_save_location (XFCE_RESOURCE_CACHE, FRECENCY_PATH, TRUE); + if (G_LIKELY (filename != NULL)) + g_file_set_contents (filename, frecency_contents->str, frecency_contents->len, NULL); + else + g_set_error_literal (error, 0, 0, "Unable to create frecencies file"); + + g_free (filename); + g_string_free (frecency_contents, TRUE); +} + + + XfceAppfinderModel * -xfce_appfinder_model_get (void) +xfce_appfinder_model_get (gboolean sort_by_frecency) { static XfceAppfinderModel *model = NULL; @@ -1926,7 +2213,9 @@ xfce_appfinder_model_get (void) } else { - model = g_object_new (XFCE_TYPE_APPFINDER_MODEL, NULL); + model = g_object_new (XFCE_TYPE_APPFINDER_MODEL, + "sort-by-frecency", sort_by_frecency, + NULL); g_object_add_weak_pointer (G_OBJECT (model), (gpointer) &model); appfinder_refcount_debug_add (G_OBJECT (model), "appfinder-model"); APPFINDER_DEBUG ("allocate new model"); diff --git a/src/appfinder-model.h b/src/appfinder-model.h index 0db7233..1038611 100644 --- a/src/appfinder-model.h +++ b/src/appfinder-model.h @@ -43,6 +43,8 @@ enum XFCE_APPFINDER_MODEL_COLUMN_COMMAND, XFCE_APPFINDER_MODEL_COLUMN_URI, XFCE_APPFINDER_MODEL_COLUMN_BOOKMARK, + XFCE_APPFINDER_MODEL_COLUMN_FREQUENCY, + XFCE_APPFINDER_MODEL_COLUMN_RECENCY, XFCE_APPFINDER_MODEL_COLUMN_TOOLTIP, XFCE_APPFINDER_MODEL_N_COLUMNS, }; @@ -67,7 +69,7 @@ XfceAppfinderIconSize; GType xfce_appfinder_model_get_type (void) G_GNUC_CONST; -XfceAppfinderModel *xfce_appfinder_model_get (void) G_GNUC_MALLOC; +XfceAppfinderModel *xfce_appfinder_model_get (gboolean sort_by_frecency) G_GNUC_MALLOC; GSList *xfce_appfinder_model_get_categories (XfceAppfinderModel *model); @@ -108,6 +110,11 @@ gboolean xfce_appfinder_model_bookmark_toggle (XfceAppfinderM GarconMenuDirectory *xfce_appfinder_model_get_command_category (void); GarconMenuDirectory *xfce_appfinder_model_get_bookmarks_category (void); +void xfce_appfinder_model_update_frecency (XfceAppfinderModel *model, + const gchar *desktop_id, + GError **error); +guint xfce_appfinder_model_calculate_frecency (guint frequency, + guint64 recency); G_END_DECLS diff --git a/src/appfinder-preferences.c b/src/appfinder-preferences.c index f3450fa..cdb69c4 100644 --- a/src/appfinder-preferences.c +++ b/src/appfinder-preferences.c @@ -134,6 +134,10 @@ xfce_appfinder_preferences_init (XfceAppfinderPreferences *preferences) G_CALLBACK (xfce_appfinder_preferences_single_window_sensitive), object); xfce_appfinder_preferences_single_window_sensitive (GTK_WIDGET (previous), GTK_WIDGET (object)); + object = gtk_builder_get_object (GTK_BUILDER (preferences), "sort-by-frecency"); + xfconf_g_property_bind (preferences->channel, "/sort-by-frecency", G_TYPE_BOOLEAN, + G_OBJECT (object), "active"); + previous = gtk_builder_get_object (GTK_BUILDER (preferences), "icon-view"); xfconf_g_property_bind (preferences->channel, "/icon-view", G_TYPE_BOOLEAN, G_OBJECT (previous), "active"); @@ -259,7 +263,7 @@ xfce_appfinder_preferences_clear_history (XfceAppfinderPreferences *preferences) _("This will permanently clear the custom command history."), _("Are you sure you want to clear the command history?"))) { - model = xfce_appfinder_model_get (); + model = xfce_appfinder_model_get (xfconf_channel_get_bool (preferences->channel, "/sort-by-frecency", FALSE)); xfce_appfinder_model_history_clear (model); g_object_unref (G_OBJECT (model)); } diff --git a/src/appfinder-preferences.glade b/src/appfinder-preferences.glade index 10ac1c8..9755a0d 100644 --- a/src/appfinder-preferences.glade +++ b/src/appfinder-preferences.glade @@ -224,6 +224,23 @@ <property name="position">3</property> </packing> </child> + <child> + <object class="GtkCheckButton" id="sort-by-frecency"> + <property name="label" translatable="yes">Sort recently used items first</property> + <property name="use_action_appearance">False</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Order items, such that items that are most recently used are always on the top.</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> </object> </child> </object> diff --git a/src/appfinder-window.c b/src/appfinder-window.c index ac309a5..942cf29 100644 --- a/src/appfinder-window.c +++ b/src/appfinder-window.c @@ -117,6 +117,13 @@ static gint xfce_appfinder_window_sort_items (GtkTreeMo GtkTreeIter *b, gpointer data); static gboolean xfce_appfinder_should_sort_icon_view (void); +static void xfce_appfinder_window_update_frecency (XfceAppfinderWindow *window, + GtkTreeModel *model, + const gchar *uri); +static gint xfce_appfinder_window_sort_items_frecency (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer data); struct _XfceAppfinderWindowClass { @@ -218,7 +225,7 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window) xfconf_g_property_bind (window->channel, "/category-icon-size", G_TYPE_UINT, G_OBJECT (window->category_model), "icon-size"); - window->model = xfce_appfinder_model_get (); + window->model = xfce_appfinder_model_get (xfconf_channel_get_bool (window->channel, "/sort-by-frecency", FALSE)); xfconf_g_property_bind (window->channel, "/item-icon-size", G_TYPE_UINT, G_OBJECT (window->model), "icon-size"); @@ -702,7 +709,10 @@ xfce_appfinder_window_view (XfceAppfinderWindow *window) gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (window->filter_model), xfce_appfinder_window_item_visible, window, NULL); window->sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (window->filter_model)); - gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (window->sort_model), xfce_appfinder_window_sort_items, window->entry, NULL); + if (xfconf_channel_get_bool (window->channel, "/sort-by-frecency", FALSE)) + gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (window->sort_model), xfce_appfinder_window_sort_items_frecency, window->entry, NULL); + else + gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (window->sort_model), xfce_appfinder_window_sort_items, window->entry, NULL); if (icon_view) { @@ -1817,6 +1827,7 @@ xfce_appfinder_window_execute (XfceAppfinderWindow *window, gboolean regular_command = FALSE; gboolean save_cmd; gboolean only_custom_cmd = FALSE; + const gchar *uri; screen = gtk_window_get_screen (GTK_WINDOW (window)); if (gtk_widget_get_visible (window->paned)) @@ -1830,6 +1841,7 @@ xfce_appfinder_window_execute (XfceAppfinderWindow *window, if (xfce_appfinder_window_view_get_selected (window, &model, &iter)) { child_model = model; + gtk_tree_model_get (model, &iter, XFCE_APPFINDER_MODEL_COLUMN_URI, &uri, -1); if (GTK_IS_TREE_MODEL_SORT (model) || xfce_appfinder_should_sort_icon_view ()) { @@ -1841,6 +1853,7 @@ xfce_appfinder_window_execute (XfceAppfinderWindow *window, gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (child_model), &child_iter, &iter); result = xfce_appfinder_model_execute (window->model, &child_iter, screen, ®ular_command, &error); + xfce_appfinder_window_update_frecency (window, model, uri); if (!result && regular_command) { gtk_tree_model_get (model, &child_iter, XFCE_APPFINDER_MODEL_COLUMN_COMMAND, &cmd, -1); @@ -1888,6 +1901,32 @@ xfce_appfinder_window_execute (XfceAppfinderWindow *window, +static void +xfce_appfinder_window_update_frecency (XfceAppfinderWindow *window, + GtkTreeModel *model, + const gchar *uri) +{ + GFile *gfile; + gchar *desktop_id; + GError *error = NULL; + + if (uri != NULL) + { + gfile = g_file_new_for_uri (uri); + desktop_id = g_file_get_basename (gfile); + g_object_unref (G_OBJECT (gfile)); + APPFINDER_DEBUG ("desktop : %s", desktop_id); + + model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (window->filter_model)); + xfce_appfinder_model_update_frecency (XFCE_APPFINDER_MODEL (model), desktop_id, &error); + + g_free (desktop_id); + g_free (error); + } +} + + + void xfce_appfinder_window_set_expanded (XfceAppfinderWindow *window, gboolean expanded) @@ -1985,6 +2024,35 @@ xfce_appfinder_window_sort_items (GtkTreeModel *model, +static gint +xfce_appfinder_window_sort_items_frecency (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer data) +{ + guint a_freq, b_freq; + guint64 a_rec, b_rec; + guint a_res, b_res; + + gtk_tree_model_get (model, a, XFCE_APPFINDER_MODEL_COLUMN_FREQUENCY, &a_freq, -1); + gtk_tree_model_get (model, b, XFCE_APPFINDER_MODEL_COLUMN_FREQUENCY, &b_freq, -1); + + gtk_tree_model_get (model, a, XFCE_APPFINDER_MODEL_COLUMN_RECENCY, &a_rec, -1); + gtk_tree_model_get (model, b, XFCE_APPFINDER_MODEL_COLUMN_RECENCY, &b_rec, -1); + + a_res = xfce_appfinder_model_calculate_frecency (a_freq, a_rec); + b_res = xfce_appfinder_model_calculate_frecency (b_freq, b_rec); + + /* Sort according the frecency */ + if (b_res - a_res != 0) + return b_res - a_res; + + /* If they have the same frecency, fallback to the alphabetical order */ + return xfce_appfinder_window_sort_items (model, a, b, data); +} + + + /* * Checks for gtk => 3.22.27 during runtime. * This is necessary because sort model for icon view did not work as expected. @@ -145,7 +145,8 @@ appfinder_window_destroyed (GtkWidget *window) if (model_cache == NULL) { APPFINDER_DEBUG ("main took reference on the main model"); - model_cache = xfce_appfinder_model_get (); + channel = xfconf_channel_get ("xfce4-appfinder"); + model_cache = xfce_appfinder_model_get (xfconf_channel_get_bool (channel, "/sort-by-frecency", FALSE)); } /* remove from internal list */ |