[epiphany] Set the history table sortable by any of the columns. https://bugzilla.gnome.org/show_bug.cgi?id=699
- From: Robert Roth <robertroth src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Set the history table sortable by any of the columns. https://bugzilla.gnome.org/show_bug.cgi?id=699
- Date: Wed, 11 Jun 2014 13:57:50 +0000 (UTC)
commit f3791ae5d11847d037222f1eff4604034b569d25
Author: Robert Roth <robert roth off gmail com>
Date: Wed Jun 11 16:56:21 2014 +0300
Set the history table sortable by any of the columns.
https://bugzilla.gnome.org/show_bug.cgi?id=699519
After the history service got support for ordering history results
by various columns, update the history dialog to allow sorting.
* override the column header clicked event to change the sorting
order and/or direction
* reload the data from the history service on column header clicks
In case the history window contents are resorted, to avoid freezing
the user interface, do the following:
* register a source to process the url list received from the service
multiple urls at a time, (as many as possible before the next frame
drawing) by adding them to the model, and freeing the url
* in case the full list is loaded or another sort is requested, remove
the source, and free the remaining list
* as clearing the liststore while it is set to a treeview emits the
row deleted signal for each row, the liststore is set to null before
clearing, it is cleared, and then set again for the treeview
* as setting the model again resets the sort column and indicator
on the treeview, those attributes must be set again.
src/ephy-history-window.c | 139 +++++++++++++++++++++++++++++++++++----
src/resources/history-dialog.ui | 10 ++-
2 files changed, 135 insertions(+), 14 deletions(-)
---
diff --git a/src/ephy-history-window.c b/src/ephy-history-window.c
index 03af3c7..5cf0a8a 100644
--- a/src/ephy-history-window.c
+++ b/src/ephy-history-window.c
@@ -38,6 +38,8 @@
#include <time.h>
#define NUM_RESULTS_LIMIT -1
+/* 3/5 of gdkframeclockidle.c's FRAME_INTERVAL (16667 microsecs) */
+#define GTK_TREE_VIEW_TIME_MS_PER_IDLE 10
struct _EphyHistoryWindowPrivate
{
@@ -46,7 +48,9 @@ struct _EphyHistoryWindowPrivate
GtkWidget *treeview;
GtkWidget *liststore;
- GtkWidget *date_column;
+ GtkTreeViewColumn *date_column;
+ GtkTreeViewColumn *name_column;
+ GtkTreeViewColumn *location_column;
GtkWidget *date_renderer;
GtkWidget *remove_button;
GtkWidget *open_button;
@@ -57,7 +61,14 @@ struct _EphyHistoryWindowPrivate
GtkWidget *copy_location_menuitem;
GtkWidget *treeview_popup_menu;
+ GList *urls;
+ guint sorter_source;
+
char *search_text;
+
+ gboolean sort_ascending;
+ gint sort_column;
+
GtkWidget *window;
GtkWidget *confirmation_dialog;
@@ -78,22 +89,41 @@ typedef enum
COLUMN_LOCATION
} EphyHistoryWindowColumns;
-static void
-add_urls (GtkListStore *store,
- GList *urls)
+static gboolean
+add_urls_source (EphyHistoryWindow *self)
{
+ GtkListStore *store = GTK_LIST_STORE (self->priv->liststore);
EphyHistoryURL *url;
- GList *iter;
+ GTimer *timer;
+ GList *element;
+
+ timer = g_timer_new ();
+ g_timer_start (timer);
- for (iter = urls; iter != NULL; iter = iter->next) {
- url = (EphyHistoryURL *)iter->data;
+ do {
+ element = self->priv->urls;
+ url = element->data;
gtk_list_store_insert_with_values (store,
NULL, G_MAXINT,
COLUMN_DATE, url->last_visit_time,
COLUMN_NAME, url->title,
COLUMN_LOCATION, url->url,
-1);
+ self->priv->urls = g_list_remove_link (self->priv->urls, element);
+ ephy_history_url_free (url);
+ g_list_free_1 (element);
+
+ } while (self->priv->urls &&
+ g_timer_elapsed (timer, NULL) < GTK_TREE_VIEW_TIME_MS_PER_IDLE / 1000.);
+
+ g_timer_destroy (timer);
+
+ if (self->priv->urls == NULL)
+ {
+ self->priv->sorter_source = 0;
+ return G_SOURCE_REMOVE;
}
+ return G_SOURCE_CONTINUE;
}
static void
@@ -103,15 +133,23 @@ on_find_urls_cb (gpointer service,
gpointer user_data)
{
EphyHistoryWindow *self = EPHY_HISTORY_WINDOW (user_data);
- GList *urls;
+ GtkTreeViewColumn *column;
if (success != TRUE)
return;
- urls = (GList *)result_data;
+ self->priv->urls = (GList *)result_data;
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (self->priv->treeview), NULL);
gtk_list_store_clear (GTK_LIST_STORE (self->priv->liststore));
- add_urls (GTK_LIST_STORE (self->priv->liststore), urls);
- g_list_free_full (urls, (GDestroyNotify)ephy_history_url_free);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (self->priv->treeview), GTK_TREE_MODEL
(self->priv->liststore));
+
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (self->priv->treeview), self->priv->sort_column);
+ gtk_tree_view_column_set_sort_order (column, self->priv->sort_ascending ? GTK_SORT_ASCENDING :
GTK_SORT_DESCENDING);
+ gtk_tree_view_column_set_sort_indicator (column, TRUE);
+
+ self->priv->sorter_source = g_idle_add ((GSourceFunc)add_urls_source, self);
+
}
static GList *
@@ -134,19 +172,54 @@ substrings_filter (EphyHistoryWindow *self)
}
static void
+remove_pending_sorter_source (EphyHistoryWindow *self) {
+
+ if (self->priv->sorter_source != 0)
+ {
+ g_source_remove (self->priv->sorter_source);
+ self->priv->sorter_source = 0;
+ }
+
+ if (self->priv->urls != NULL)
+ {
+ g_list_free_full (self->priv->urls, (GDestroyNotify)ephy_history_url_free);
+ self->priv->urls = NULL;
+ }
+}
+
+static void
filter_now (EphyHistoryWindow *self)
{
gint64 from, to;
GList *substrings;
+ EphyHistorySortType type;
substrings = substrings_filter (self);
from = to = -1; /* all */
+
+ switch (self->priv->sort_column)
+ {
+ case COLUMN_DATE:
+ type = self->priv->sort_ascending ? EPHY_HISTORY_SORT_LEAST_RECENTLY_VISITED :
EPHY_HISTORY_SORT_MOST_RECENTLY_VISITED;
+ break;
+ case COLUMN_NAME:
+ type = self->priv->sort_ascending ? EPHY_HISTORY_SORT_TITLE_ASCENDING :
EPHY_HISTORY_SORT_TITLE_DESCENDING;
+ break;
+ case COLUMN_LOCATION:
+ type = self->priv->sort_ascending ? EPHY_HISTORY_SORT_URL_ASCENDING :
EPHY_HISTORY_SORT_URL_DESCENDING;
+ break;
+ default:
+ type = EPHY_HISTORY_SORT_MOST_RECENTLY_VISITED;
+ }
+
+ remove_pending_sorter_source (self);
+
ephy_history_service_find_urls (self->priv->history_service,
from, to,
NUM_RESULTS_LIMIT, 0,
substrings,
- EPHY_HISTORY_SORT_MOST_RECENTLY_VISITED,
+ type,
self->priv->cancellable,
(EphyHistoryJobCallback)on_find_urls_cb, self);
}
@@ -462,6 +535,31 @@ on_treeview_selection_changed (GtkTreeSelection *selection,
}
static void
+on_treeview_column_clicked_event (GtkTreeViewColumn *column,
+ EphyHistoryWindow *self)
+{
+ GtkTreeViewColumn *previous_sortby;
+ gint new_sort_column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (column), "column"));
+
+ if (new_sort_column == self->priv->sort_column)
+ {
+ self->priv->sort_ascending = !(self->priv->sort_ascending);
+ }
+ else
+ {
+ previous_sortby = gtk_tree_view_get_column (GTK_TREE_VIEW (self->priv->treeview),
self->priv->sort_column);
+ gtk_tree_view_column_set_sort_indicator (previous_sortby, FALSE);
+
+ self->priv->sort_column = new_sort_column;
+ self->priv->sort_ascending = self->priv->sort_column == COLUMN_DATE ? FALSE : TRUE;
+ }
+
+ gtk_tree_view_column_set_sort_order (column, self->priv->sort_ascending ? GTK_SORT_ASCENDING :
GTK_SORT_DESCENDING);
+ gtk_tree_view_column_set_sort_indicator (column, TRUE);
+ filter_now (self);
+}
+
+static void
on_remove_button_clicked (GtkButton *button,
EphyHistoryWindow *self)
{
@@ -569,6 +667,8 @@ ephy_history_window_dispose (GObject *object)
self);
g_clear_object (&self->priv->history_service);
+ remove_pending_sorter_source (self);
+
G_OBJECT_CLASS (ephy_history_window_parent_class)->dispose (object);
}
@@ -616,6 +716,8 @@ ephy_history_window_class_init (EphyHistoryWindowClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, EphyHistoryWindow, remove_button);
gtk_widget_class_bind_template_child_private (widget_class, EphyHistoryWindow, open_button);
gtk_widget_class_bind_template_child_private (widget_class, EphyHistoryWindow, date_column);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyHistoryWindow, name_column);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyHistoryWindow, location_column);
gtk_widget_class_bind_template_child_private (widget_class, EphyHistoryWindow, date_renderer);
gtk_widget_class_bind_template_child_private (widget_class, EphyHistoryWindow, open_menuitem);
gtk_widget_class_bind_template_child_private (widget_class, EphyHistoryWindow,
copy_location_menuitem);
@@ -627,6 +729,7 @@ ephy_history_window_class_init (EphyHistoryWindowClass *klass)
gtk_widget_class_bind_template_callback (widget_class, on_treeview_key_press_event);
gtk_widget_class_bind_template_callback (widget_class, on_treeview_button_press_event);
gtk_widget_class_bind_template_callback (widget_class, on_treeview_selection_changed);
+ gtk_widget_class_bind_template_callback (widget_class, on_treeview_column_clicked_event);
gtk_widget_class_bind_template_callback (widget_class, on_remove_button_clicked);
gtk_widget_class_bind_template_callback (widget_class, on_open_button_clicked);
gtk_widget_class_bind_template_callback (widget_class, on_search_entry_changed);
@@ -718,8 +821,20 @@ ephy_history_window_init (EphyHistoryWindow *self)
self->priv->cancellable = g_cancellable_new ();
+ self->priv->urls = NULL;
+ self->priv->sort_ascending = FALSE;
+ self->priv->sort_column = COLUMN_DATE;
+ self->priv->sorter_source = 0;
+
ephy_gui_ensure_window_group (GTK_WINDOW (self));
+ g_object_set_data (G_OBJECT (self->priv->date_column),
+ "column", GINT_TO_POINTER (COLUMN_DATE));
+ g_object_set_data (G_OBJECT (self->priv->name_column),
+ "column", GINT_TO_POINTER (COLUMN_NAME));
+ g_object_set_data (G_OBJECT (self->priv->location_column),
+ "column", GINT_TO_POINTER (COLUMN_LOCATION));
+
gtk_tree_view_column_set_cell_data_func (GTK_TREE_VIEW_COLUMN (self->priv->date_column),
GTK_CELL_RENDERER (self->priv->date_renderer),
(GtkTreeCellDataFunc) convert_cell_data_func,
diff --git a/src/resources/history-dialog.ui b/src/resources/history-dialog.ui
index bbf3cd9..e793425 100644
--- a/src/resources/history-dialog.ui
+++ b/src/resources/history-dialog.ui
@@ -127,8 +127,10 @@
<property name="sizing">fixed</property>
<property name="fixed-width">150</property>
<property name="title" translatable="yes">Date</property>
+ <property name="clickable">True</property>
<property name="sort_indicator">True</property>
<property name="sort_order">descending</property>
+ <signal name="clicked" handler="on_treeview_column_clicked_event"
object="EphyHistoryWindow" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="date_renderer"/>
<attributes>
@@ -138,10 +140,12 @@
</object>
</child>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <object class="GtkTreeViewColumn" id="name_column">
<property name="sizing">fixed</property>
<property name="fixed-width">500</property>
<property name="title" translatable="yes">Name</property>
+ <property name="clickable">True</property>
+ <signal name="clicked" handler="on_treeview_column_clicked_event"
object="EphyHistoryWindow" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2">
<property name="ellipsize">end</property>
@@ -154,9 +158,11 @@
</child>
<child>
<object class="GtkTreeViewColumn" id="location_column">
- <property name="sizing">fixed</property>
+ <property name="sizing">fixed</property>
<property name="fixed-width">200</property>
<property name="title" translatable="yes">Location</property>
+ <property name="clickable">True</property>
+ <signal name="clicked" handler="on_treeview_column_clicked_event"
object="EphyHistoryWindow" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="location_renderer">
<property name="ellipsize">end</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]