diff options
Diffstat (limited to 'src/pdm-dialog.c')
-rwxr-xr-x | src/pdm-dialog.c | 236 |
1 files changed, 212 insertions, 24 deletions
diff --git a/src/pdm-dialog.c b/src/pdm-dialog.c index b46a60c77..1da1448a6 100755 --- a/src/pdm-dialog.c +++ b/src/pdm-dialog.c @@ -28,8 +28,9 @@ #include "ephy-file-helpers.h" #include "ephy-password-manager.h" #include "ephy-gui.h" -#include "ephy-debug.h" #include "ephy-state.h" +#include "ephy-string.h" +#include "ephy-debug.h" #include <gtk/gtklabel.h> #include <gtk/gtkbox.h> @@ -59,13 +60,16 @@ struct PdmActionInfo gpointer data); void (* remove) (PdmActionInfo *info, gpointer data); + void (* scroll_to) (PdmActionInfo *info); /* Data */ PdmDialog *dialog; GtkTreeView *treeview; + GtkTreeSelection *selection; GtkTreeModel *model; int remove_id; int data_col; + char *scroll_to_host; gboolean filled; gboolean delete_row_on_remove; }; @@ -74,6 +78,7 @@ struct PdmActionInfo struct PdmDialogPrivate { + GtkWidget *notebook; GtkTreeModel *model; PdmActionInfo *cookies; PdmActionInfo *passwords; @@ -82,9 +87,16 @@ struct PdmDialogPrivate enum { COL_COOKIES_HOST, + COL_COOKIES_HOST_KEY, COL_COOKIES_NAME, COL_COOKIES_PATH, - COL_COOKIES_DATA + COL_COOKIES_DATA, +}; + +enum +{ + TV_COL_COOKIES_HOST, + TV_COL_COOKIES_NAME }; enum @@ -513,6 +525,25 @@ cookies_treeview_selection_changed_cb (GtkTreeSelection *selection, gtk_widget_set_sensitive (widget, has_selection); } +static gboolean +cookie_search_equal (GtkTreeModel *model, + int column, + const gchar *key, + GtkTreeIter *iter, + gpointer search_data) +{ + GValue value = { 0, }; + gboolean retval; + + /* Note that this is function has to return FALSE for a *match* ! */ + + gtk_tree_model_get_value (model, iter, column, &value); + retval = strstr (g_value_get_string (&value), key) == NULL; + g_value_unset (&value); + + return retval; +} + static void pdm_dialog_cookies_construct (PdmActionInfo *info) { @@ -535,7 +566,8 @@ pdm_dialog_cookies_construct (PdmActionInfo *info) G_CALLBACK (cookies_properties_clicked_cb), dialog); /* set tree model */ - liststore = gtk_list_store_new (4, + liststore = gtk_list_store_new (5, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, @@ -555,30 +587,35 @@ pdm_dialog_cookies_construct (PdmActionInfo *info) renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (treeview, - COL_COOKIES_HOST, + TV_COL_COOKIES_HOST, _("Domain"), renderer, "text", COL_COOKIES_HOST, NULL); - column = gtk_tree_view_get_column (treeview, COL_COOKIES_HOST); + column = gtk_tree_view_get_column (treeview, TV_COL_COOKIES_HOST); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_column_set_sort_column_id (column, COL_COOKIES_HOST); gtk_tree_view_insert_column_with_attributes (treeview, - COL_COOKIES_NAME, + TV_COL_COOKIES_NAME, _("Name"), renderer, "text", COL_COOKIES_NAME, NULL); - column = gtk_tree_view_get_column (treeview, COL_COOKIES_NAME); + column = gtk_tree_view_get_column (treeview, TV_COL_COOKIES_NAME); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_reorderable (column, TRUE); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_column_set_sort_column_id (column, COL_COOKIES_NAME); + + gtk_tree_view_set_enable_search (treeview, TRUE); + gtk_tree_view_set_search_column (treeview, COL_COOKIES_HOST); + gtk_tree_view_set_search_equal_func (treeview, + (GtkTreeViewSearchEqualFunc) cookie_search_equal, + dialog, NULL); info->treeview = treeview; + info->selection = selection; setup_action (info); } @@ -688,6 +725,94 @@ cookies_cleared_cb (EphyCookieManager *manager, gtk_list_store_clear (GTK_LIST_STORE (info->model)); } +static gboolean +cookie_host_to_iter (GtkTreeModel *model, + const char *key1, + GtkTreeIter *iter) +{ + GtkTreeIter iter2; + gboolean valid; + gssize len; + int max = 0; + + len = strlen (key1); + + valid = gtk_tree_model_get_iter_first (model, &iter2); + + while (valid) + { + const char *p, *q; + char *key2; + int n = 0; + + gtk_tree_model_get (model, &iter2, COL_COOKIES_HOST, &key2, -1); + + /* Count the segments (string between successive dots) + * that key1 and key2 share. + */ + + /* Start on the \0 */ + p = key1 + len; + q = key2 + strlen (key2); + + do + { + if (*p == '.') ++n; + --p; + --q; + } + while (p >= key1 && q >= key2 && *p == *q); + + if ((p < key1 && q < key2 && *key1 != '.' && *key2 != '.') || + (p < key1 && q >= key2 && *q == '.') || + (q < key2 && p >= key1 && *p == '.')) + { + ++n; + } + + g_free (key2); + + /* Complete match */ + if (p < key1 && q < key2) + { + *iter = iter2; + return TRUE; + } + + if (n > max) + { + max = n; + *iter = iter2; + } + + valid = gtk_tree_model_iter_next (model, &iter2); + } + + return max > 0; +} + +static int +compare_cookie_host_keys (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + GValue a_value = {0, }; + GValue b_value = {0, }; + int retval; + + gtk_tree_model_get_value (model, a, COL_COOKIES_HOST_KEY, &a_value); + gtk_tree_model_get_value (model, b, COL_COOKIES_HOST_KEY, &b_value); + + retval = strcmp (g_value_get_string (&a_value), + g_value_get_string (&b_value)); + + g_value_unset (&a_value); + g_value_unset (&b_value); + + return retval; +} + static void pdm_dialog_fill_cookies_list (PdmActionInfo *info) { @@ -709,6 +834,15 @@ pdm_dialog_fill_cookies_list (PdmActionInfo *info) /* the element data has been consumed, so we need only to free the list */ g_list_free (list); + /* Now turn on sorting */ + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (info->model), + COL_COOKIES_HOST_KEY, + (GtkTreeIterCompareFunc) compare_cookie_host_keys, + NULL, NULL); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (info->model), + COL_COOKIES_HOST_KEY, + GTK_SORT_ASCENDING); + info->filled = TRUE; /* Now connect the callbacks on the EphyCookieManager */ @@ -721,15 +855,14 @@ pdm_dialog_fill_cookies_list (PdmActionInfo *info) g_signal_connect (manager, "cookies-cleared", G_CALLBACK (cookies_cleared_cb), info->dialog); - /* Now turn on sorting */ - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (info->model), - COL_COOKIES_HOST, - GTK_SORT_ASCENDING); + info->scroll_to (info); } static void pdm_dialog_cookies_destruct (PdmActionInfo *info) { + g_free (info->scroll_to_host); + info->scroll_to_host = NULL; } static void @@ -750,6 +883,11 @@ pdm_dialog_cookie_add (PdmActionInfo *info, COL_COOKIES_PATH, cookie->path, -1); + g_value_init (&value, G_TYPE_STRING); + g_value_take_string (&value, ephy_string_collate_key_for_domain (cookie->domain, -1)); + gtk_list_store_set_value (store, &iter, COL_COOKIES_HOST_KEY, &value); + g_value_unset (&value); + g_value_init (&value, EPHY_TYPE_COOKIE); g_value_take_boxed (&value, cookie); gtk_list_store_set_value (store, &iter, COL_COOKIES_DATA, &value); @@ -769,6 +907,29 @@ pdm_dialog_cookie_remove (PdmActionInfo *info, ephy_cookie_manager_remove_cookie (manager, cookie); } +static void +pdm_dialog_cookie_scroll_to (PdmActionInfo *info) +{ + GtkTreeIter iter; + GtkTreePath *path; + + if (info->scroll_to_host == NULL || !info->filled) return; + + if (cookie_host_to_iter (info->model, info->scroll_to_host, &iter)) + { + gtk_tree_selection_unselect_all (info->selection); + + path = gtk_tree_model_get_path (info->model, &iter); + gtk_tree_view_scroll_to_cell (info->treeview, + path, NULL, TRUE, + 0.0, 0.5); + gtk_tree_path_free (path); + } + + g_free (info->scroll_to_host); + info->scroll_to_host = NULL; +} + /* "Passwords" tab */ static void @@ -984,14 +1145,18 @@ sync_notebook_tab (GtkWidget *notebook, int page_num, PdmDialog *dialog) { + PdmDialogPrivate *priv = dialog->priv; + /* Lazily fill the list store */ - if (page_num == 0 && dialog->priv->cookies->filled == FALSE) + if (page_num == 0 && priv->cookies->filled == FALSE) { - dialog->priv->cookies->fill (dialog->priv->cookies); + priv->cookies->fill (priv->cookies); + + priv->cookies->scroll_to (priv->cookies); } - else if (page_num == 1 && dialog->priv->passwords->filled == FALSE) + else if (page_num == 1 && priv->passwords->filled == FALSE) { - dialog->priv->passwords->fill (dialog->priv->passwords); + priv->passwords->fill (priv->passwords); } } @@ -1008,13 +1173,15 @@ pdm_dialog_response_cb (GtkDialog *widget, g_object_unref (dialog); } + static void pdm_dialog_init (PdmDialog *dialog) { + PdmDialogPrivate *priv; PdmActionInfo *cookies, *passwords; - GtkWidget *notebook, *window; + GtkWidget *window; - dialog->priv = EPHY_PDM_DIALOG_GET_PRIVATE (dialog); + priv = dialog->priv = EPHY_PDM_DIALOG_GET_PRIVATE (dialog); ephy_dialog_construct (EPHY_DIALOG(dialog), properties, @@ -1024,7 +1191,7 @@ pdm_dialog_init (PdmDialog *dialog) ephy_dialog_get_controls (EPHY_DIALOG (dialog), properties[PROP_WINDOW].id, &window, - properties[PROP_NOTEBOOK].id, ¬ebook, + properties[PROP_NOTEBOOK].id, &priv->notebook, NULL); ephy_gui_ensure_window_group (GTK_WINDOW (window)); @@ -1051,9 +1218,11 @@ pdm_dialog_init (PdmDialog *dialog) cookies->fill = pdm_dialog_fill_cookies_list; cookies->add = pdm_dialog_cookie_add; cookies->remove = pdm_dialog_cookie_remove; + cookies->scroll_to = pdm_dialog_cookie_scroll_to; cookies->dialog = dialog; cookies->remove_id = PROP_COOKIES_REMOVE; cookies->data_col = COL_COOKIES_DATA; + cookies->scroll_to_host = NULL; cookies->filled = FALSE; cookies->delete_row_on_remove = FALSE; @@ -1066,17 +1235,18 @@ pdm_dialog_init (PdmDialog *dialog) passwords->dialog = dialog; passwords->remove_id = PROP_PASSWORDS_REMOVE; passwords->data_col = COL_PASSWORDS_DATA; + passwords->scroll_to_host = NULL; passwords->filled = FALSE; passwords->delete_row_on_remove = TRUE; - dialog->priv->cookies = cookies; - dialog->priv->passwords = passwords; + priv->cookies = cookies; + priv->passwords = passwords; cookies->construct (cookies); passwords->construct (passwords); - sync_notebook_tab (notebook, NULL, 0, dialog); - g_signal_connect (G_OBJECT (notebook), "switch_page", + sync_notebook_tab (priv->notebook, NULL, 0, dialog); + g_signal_connect (G_OBJECT (priv->notebook), "switch_page", G_CALLBACK (sync_notebook_tab), dialog); } @@ -1099,3 +1269,21 @@ pdm_dialog_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } + +void +pdm_dialog_open (PdmDialog *dialog, + const char *host) +{ + PdmDialogPrivate *priv = dialog->priv; + + /* Switch to cookies tab */ + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 0); + + g_free (priv->cookies->scroll_to_host); + priv->cookies->scroll_to_host = g_strdup (host); + + priv->cookies->scroll_to (priv->cookies); + gtk_widget_grab_focus (GTK_WIDGET (priv->cookies->treeview)); + + ephy_dialog_show (EPHY_DIALOG (dialog)); +} |