aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--lib/ephy-string.c48
-rw-r--r--lib/ephy-string.h3
-rwxr-xr-xsrc/pdm-dialog.c236
-rw-r--r--src/pdm-dialog.h5
-rw-r--r--src/window-commands.c21
6 files changed, 306 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index d46343288..d30bc55a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
2005-11-29 Christian Persch <chpe@cvs.gnome.org>
+ * lib/ephy-string.c: (ephy_string_collate_key_for_domain):
+ * lib/ephy-string.h:
+
+ Add a method to generate collation keys for domain names.
+
+ * src/pdm-dialog.c: (cookie_search_equal),
+ (pdm_dialog_cookies_construct), (cookie_host_to_iter),
+ (compare_cookie_host_keys), (pdm_dialog_fill_cookies_list),
+ (pdm_dialog_cookies_destruct), (pdm_dialog_cookie_add),
+ (pdm_dialog_cookie_scroll_to), (sync_notebook_tab),
+ (pdm_dialog_init), (pdm_dialog_finalize), (pdm_dialog_open):
+ * src/pdm-dialog.h:
+ * src/window-commands.c: (window_cmd_edit_personal_data):
+
+ Open the PDM dialogue on the cookies page scrolled to show the
+ cookies of the currently loaded page, if there are any. Sort
+ cookies by domain. Allow treeview typeaheadfind search to find
+ by substring not prefix.
+
+2005-11-29 Christian Persch <chpe@cvs.gnome.org>
+
* configure.ac:
* data/Makefile.am:
R data/bme.desktop.in:
diff --git a/lib/ephy-string.c b/lib/ephy-string.c
index f16571cd1..3eb991573 100644
--- a/lib/ephy-string.c
+++ b/lib/ephy-string.c
@@ -134,3 +134,51 @@ ephy_string_shorten (char *str,
return new_str;
}
+
+/* This is a collation key that is very very likely to sort before any
+ collation key that libc strxfrm generates. We use this before any
+ special case (dot or number) to make sure that its sorted before
+ anything else.
+ */
+#define COLLATION_SENTINEL "\1\1\1"
+
+/**
+ * ephy_string_collate_key_for_domain:
+ * @host:
+ * @len: the length of @host, or -1 to use the entire null-terminated @host string
+ *
+ * Return value: a collation key for @host.
+ */
+char*
+ephy_string_collate_key_for_domain (const char *str,
+ gssize len)
+{
+ GString *result;
+ const char *dot;
+ gssize newlen;
+
+ if (len < 0) len = strlen (str);
+
+ result = g_string_sized_new (len + 6 * strlen (COLLATION_SENTINEL));
+
+ /* Note that we could do even better by using
+ * g_utf8_collate_key_for_filename on the dot-separated
+ * components, but this seems good enough for now.
+ */
+ while ((dot = g_strrstr_len (str, len, ".")) != NULL)
+ {
+ newlen = dot - str;
+
+ g_string_append_len (result, dot + 1, len - newlen - 1);
+ g_string_append (result, COLLATION_SENTINEL);
+
+ len = newlen;
+ }
+
+ if (len > 0)
+ {
+ g_string_append_len (result, str, len);
+ }
+
+ return g_string_free (result, FALSE);
+}
diff --git a/lib/ephy-string.h b/lib/ephy-string.h
index d5b932ba0..6bb50ff3e 100644
--- a/lib/ephy-string.h
+++ b/lib/ephy-string.h
@@ -33,6 +33,9 @@ char *ephy_string_blank_chr (char *source);
char *ephy_string_shorten (char *str,
gsize target_length);
+char *ephy_string_collate_key_for_domain (const char *host,
+ gssize len);
+
G_END_DECLS
#endif
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, &notebook,
+ 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));
+}
diff --git a/src/pdm-dialog.h b/src/pdm-dialog.h
index 9dd7a3183..b6ffec552 100644
--- a/src/pdm-dialog.h
+++ b/src/pdm-dialog.h
@@ -51,7 +51,10 @@ struct PdmDialogClass
EphyDialogClass parent_class;
};
-GType pdm_dialog_get_type (void);
+GType pdm_dialog_get_type (void);
+
+void pdm_dialog_open (PdmDialog *dialog,
+ const char *host);
G_END_DECLS
diff --git a/src/window-commands.c b/src/window-commands.c
index e466f244b..68d0dc710 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -45,6 +45,7 @@
#include "ephy-toolbar-editor.h"
#include "ephy-find-toolbar.h"
#include "ephy-location-entry.h"
+#include "pdm-dialog.h"
#include <string.h>
#include <glib.h>
@@ -648,11 +649,25 @@ void
window_cmd_edit_personal_data (GtkAction *action,
EphyWindow *window)
{
- EphyDialog *dialog;
+ PdmDialog *dialog;
+ EphyTab *tab;
+ GnomeVFSURI *uri;
+ const char *host;
- dialog = EPHY_DIALOG (ephy_shell_get_pdm_dialog (ephy_shell));
+ tab = ephy_window_get_active_tab (window);
+ if (tab == NULL) return;
- ephy_dialog_show (dialog);
+ uri = gnome_vfs_uri_new (ephy_tab_get_address (tab));
+
+ host = uri != NULL ? gnome_vfs_uri_get_host_name (uri) : NULL;
+
+ dialog = EPHY_PDM_DIALOG (ephy_shell_get_pdm_dialog (ephy_shell));
+ pdm_dialog_open (dialog, host);
+
+ if (uri != NULL)
+ {
+ gnome_vfs_uri_unref (uri);
+ }
}
void