aboutsummaryrefslogtreecommitdiffstats
path: root/src/bookmarks
diff options
context:
space:
mode:
Diffstat (limited to 'src/bookmarks')
-rw-r--r--src/bookmarks/Makefile.am2
-rw-r--r--src/bookmarks/ephy-bookmark-properties.c104
-rw-r--r--src/bookmarks/ephy-bookmarks-ui.c9
-rw-r--r--src/bookmarks/ephy-topics-entry.c520
-rw-r--r--src/bookmarks/ephy-topics-entry.h61
-rw-r--r--src/bookmarks/ephy-topics-palette.c156
6 files changed, 703 insertions, 149 deletions
diff --git a/src/bookmarks/Makefile.am b/src/bookmarks/Makefile.am
index 1b4b8e679..43f22d152 100644
--- a/src/bookmarks/Makefile.am
+++ b/src/bookmarks/Makefile.am
@@ -23,6 +23,7 @@ NOINST_H_FILES = \
ephy-bookmark-factory-action.h \
ephy-topic-action-group.h \
ephy-bookmark-action-group.h \
+ ephy-topics-entry.h \
ephy-topics-palette.h \
ephy-nodes-cover.h
@@ -42,6 +43,7 @@ libephybookmarks_la_SOURCES = \
ephy-bookmark-factory-action.c \
ephy-topic-action-group.c \
ephy-bookmark-action-group.c \
+ ephy-topics-entry.c \
ephy-topics-palette.c \
ephy-nodes-cover.c \
$(NOINST_H_FILES) \
diff --git a/src/bookmarks/ephy-bookmark-properties.c b/src/bookmarks/ephy-bookmark-properties.c
index c5f274fbb..559b16b01 100644
--- a/src/bookmarks/ephy-bookmark-properties.c
+++ b/src/bookmarks/ephy-bookmark-properties.c
@@ -25,6 +25,7 @@
#include "ephy-bookmark-properties.h"
#include "ephy-bookmarks-ui.h"
+#include "ephy-topics-entry.h"
#include "ephy-topics-palette.h"
#include "ephy-stock-icons.h"
#include "ephy-debug.h"
@@ -56,11 +57,12 @@ struct _EphyBookmarkPropertiesPrivate
{
EphyBookmarks *bookmarks;
EphyNode *bookmark;
- EphyTopicsPalette *palette;
gboolean creating;
EphyNode *duplicate;
GtkWidget *warning;
+ GtkWidget *entry;
+ GtkWidget *palette;
};
enum
@@ -71,11 +73,6 @@ enum
PROP_CREATING
};
-enum
-{
- RESPONSE_NEW_TOPIC = 1
-};
-
static GObjectClass *parent_class;
static void
@@ -202,10 +199,6 @@ bookmark_properties_response_cb (GtkDialog *dialog,
"epiphany",
"to-edit-bookmark-properties");
return;
- case RESPONSE_NEW_TOPIC:
- ephy_bookmarks_ui_add_topic (GTK_WIDGET (dialog),
- priv->bookmark);
- return;
case GTK_RESPONSE_ACCEPT:
/* On destruction of the dialog, if priv->creating==TRUE,
* we will unref any bookmark we have, so we set it
@@ -251,16 +244,6 @@ update_window_title (EphyBookmarkProperties *properties)
g_free (title);
}
-static void
-combo_changed_cb (GtkComboBox *combobox,
- GtkWidget *palette)
-{
- int active;
-
- active = gtk_combo_box_get_active (GTK_COMBO_BOX (combobox));
- g_object_set (palette, "mode", active, NULL);
-}
-
static void
title_entry_changed_cb (GtkWidget *entry,
EphyBookmarkProperties *props)
@@ -281,6 +264,38 @@ location_entry_changed_cb (GtkWidget *entry,
}
static void
+toggled_cb (GtkToggleButton *button,
+ EphyBookmarkProperties *properties)
+{
+ EphyBookmarkPropertiesPrivate *priv = properties->priv;
+ GdkGeometry geometry;
+
+ if(gtk_toggle_button_get_active (button))
+ {
+ g_object_set (priv->entry, "sensitive", FALSE, NULL);
+ g_object_set (priv->palette, "visible", TRUE, NULL);
+
+ geometry.min_width = -1;
+ geometry.min_height = 230;
+ gtk_window_set_geometry_hints (GTK_WINDOW (properties),
+ priv->palette, &geometry,
+ GDK_HINT_MIN_SIZE);
+ }
+ else
+ {
+ g_object_set (priv->entry, "sensitive", TRUE, NULL);
+ g_object_set (priv->palette, "visible", FALSE, NULL);
+
+ geometry.max_height = -1;
+ geometry.max_width = G_MAXINT;
+ gtk_window_set_geometry_hints (GTK_WINDOW (properties),
+ GTK_WIDGET (properties),
+ &geometry, GDK_HINT_MAX_SIZE);
+ }
+}
+
+
+static void
ephy_bookmark_properties_init (EphyBookmarkProperties *properties)
{
properties->priv = EPHY_BOOKMARK_PROPERTIES_GET_PRIVATE (properties);
@@ -294,8 +309,8 @@ ephy_bookmark_properties_constructor (GType type,
GObject *object;
EphyBookmarkProperties *properties;
EphyBookmarkPropertiesPrivate *priv;
- GtkWidget *widget, *table, *label, *entry, *palette;
- GtkWidget *scrolled_window;
+ GtkWidget *widget, *table, *label, *entry, *button;
+ GtkWidget *scrolled_window, *palette;
GtkWindow *window;
GtkDialog *dialog;
const char *tmp;
@@ -322,7 +337,8 @@ ephy_bookmark_properties_constructor (GType type,
ephy_state_add_window (widget,
"bookmark_properties",
290, 280, FALSE,
- EPHY_STATE_WINDOW_SAVE_SIZE);
+ EPHY_STATE_WINDOW_SAVE_SIZE |
+ EPHY_STATE_WINDOW_SAVE_POSITION);
update_window_title (properties);
@@ -330,9 +346,10 @@ ephy_bookmark_properties_constructor (GType type,
gtk_container_set_border_width (GTK_CONTAINER (properties), 5);
gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2);
- table = gtk_table_new (4, 2, FALSE);
+ table = gtk_table_new (4, 3, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+ gtk_table_set_col_spacing (GTK_TABLE (table), 1, 3);
gtk_container_set_border_width (GTK_CONTAINER (table), 5);
gtk_widget_show (table);
@@ -350,7 +367,7 @@ ephy_bookmark_properties_constructor (GType type,
gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
gtk_widget_show (label);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
- gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 3, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
entry = gtk_entry_new ();
tmp = ephy_node_get_property_string (properties->priv->bookmark,
@@ -365,21 +382,30 @@ ephy_bookmark_properties_constructor (GType type,
gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
gtk_widget_show (label);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
- gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 3, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0);
widget = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_BUTTON);
- priv->warning = gtk_button_new_with_mnemonic (_("_Show bookmark with same address"));
+ priv->warning = gtk_button_new_with_mnemonic (_("_Show similar bookmark"));
gtk_button_set_image (GTK_BUTTON (priv->warning), widget);
g_signal_connect (priv->warning, "clicked",
G_CALLBACK(show_duplicate_cb), properties);
gtk_widget_show (priv->warning);
gtk_table_set_row_spacing (GTK_TABLE (table), 1, 0);
- gtk_table_attach (GTK_TABLE (table), priv->warning, 1, 2, 2, 3, GTK_FILL, 0, 0, 3);
+ gtk_table_attach (GTK_TABLE (table), priv->warning, 1, 3, 2, 3, GTK_FILL, 0, 0, 3);
priv->duplicate = ephy_bookmarks_find_duplicate (priv->bookmarks, priv->bookmark);
g_object_set (priv->warning, "visible", priv->duplicate != NULL, NULL);
+ entry = ephy_topics_entry_new (priv->bookmarks, priv->bookmark);
+ priv->entry = entry;
+ gtk_widget_show (entry);
+ label = gtk_label_new_with_mnemonic(_("T_opics:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+
palette = ephy_topics_palette_new (priv->bookmarks, priv->bookmark);
- priv->palette = EPHY_TOPICS_PALETTE (palette);
scrolled_window = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
"hadjustment", NULL,
"vadjustment", NULL,
@@ -387,25 +413,27 @@ ephy_bookmark_properties_constructor (GType type,
"vscrollbar_policy", GTK_POLICY_AUTOMATIC,
"shadow_type", GTK_SHADOW_IN,
NULL);
+ priv->palette = scrolled_window;
gtk_container_add (GTK_CONTAINER (scrolled_window), palette);
gtk_widget_show (palette);
- label = gtk_label_new_with_mnemonic(_("T_opics:"));
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label), palette);
- gtk_widget_show (label);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 6);
- gtk_table_attach (GTK_TABLE (table), scrolled_window, 1, 2, 3, 4,
+ gtk_table_attach (GTK_TABLE (table), scrolled_window, 1, 3, 4, 5,
GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
gtk_widget_show (scrolled_window);
+ widget = gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (widget);
+ button = gtk_toggle_button_new_with_label ("");
+ gtk_button_set_image (GTK_BUTTON (button), widget);
+ g_signal_connect (button, "toggled", G_CALLBACK (toggled_cb), properties);
+ toggled_cb (button, properties);
+ gtk_widget_show (button);
+ gtk_table_attach (GTK_TABLE (table), button, 2, 3, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
+
gtk_box_pack_start (GTK_BOX (dialog->vbox), table, TRUE, TRUE, 0);
gtk_dialog_add_button (dialog,
GTK_STOCK_HELP,
GTK_RESPONSE_HELP);
- gtk_dialog_add_button (dialog,
- _("_New Topic"),
- RESPONSE_NEW_TOPIC);
if (priv->creating)
{
diff --git a/src/bookmarks/ephy-bookmarks-ui.c b/src/bookmarks/ephy-bookmarks-ui.c
index 63f6d9df1..f560e1f56 100644
--- a/src/bookmarks/ephy-bookmarks-ui.c
+++ b/src/bookmarks/ephy-bookmarks-ui.c
@@ -412,10 +412,9 @@ ephy_bookmarks_ui_detach_window (EphyWindow *window)
static void
properties_dialog_destroy_cb (EphyBookmarkProperties *dialog,
- gpointer user_data)
+ EphyNode *bookmark)
{
- g_hash_table_remove (properties_dialogs,
- ephy_bookmark_properties_get_node (dialog));
+ g_hash_table_remove (properties_dialogs, bookmark);
}
void
@@ -437,7 +436,7 @@ ephy_bookmarks_ui_add_bookmark (const char *location,
dialog = ephy_bookmark_properties_new (bookmarks, bookmark, TRUE);
g_signal_connect (dialog, "destroy",
- G_CALLBACK (properties_dialog_destroy_cb), bookmarks);
+ G_CALLBACK (properties_dialog_destroy_cb), bookmark);
g_hash_table_insert (properties_dialogs,
bookmark, dialog);
@@ -661,7 +660,7 @@ ephy_bookmarks_ui_show_bookmark (EphyNode *bookmark)
dialog = ephy_bookmark_properties_new (bookmarks, bookmark, FALSE);
g_signal_connect (dialog, "destroy",
- G_CALLBACK (properties_dialog_destroy_cb), bookmarks);
+ G_CALLBACK (properties_dialog_destroy_cb), bookmark);
g_hash_table_insert (properties_dialogs,
bookmark, dialog);
}
diff --git a/src/bookmarks/ephy-topics-entry.c b/src/bookmarks/ephy-topics-entry.c
new file mode 100644
index 000000000..8c3af0007
--- /dev/null
+++ b/src/bookmarks/ephy-topics-entry.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2002-2004 Marco Pesenti Gritti <mpeseng@tin.it>
+ * Copyright (C) 2005, 2006 Peter Harvey <pah06@uow.edu.au>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "ephy-topics-entry.h"
+#include "ephy-nodes-cover.h"
+#include "ephy-node-common.h"
+#include "ephy-bookmarks.h"
+#include "ephy-debug.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtktreeselection.h>
+#include <gtk/gtkentrycompletion.h>
+#include <string.h>
+
+static void ephy_topics_entry_class_init (EphyTopicsEntryClass *klass);
+static void ephy_topics_entry_init (EphyTopicsEntry *editor);
+
+#define EPHY_TOPICS_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_TOPICS_ENTRY, EphyTopicsEntryPrivate))
+
+struct _EphyTopicsEntryPrivate
+{
+ EphyBookmarks *bookmarks;
+ EphyNode *bookmark;
+ GtkListStore *store;
+ GtkEntryCompletion *completion;
+ gboolean update_keywords;
+ char *action;
+};
+
+enum
+{
+ PROP_0,
+ PROP_BOOKMARKS,
+ PROP_BOOKMARK
+};
+
+static GObjectClass *parent_class = NULL;
+
+GType
+ephy_topics_entry_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EphyTopicsEntryClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) ephy_topics_entry_class_init,
+ NULL,
+ NULL,
+ sizeof (EphyTopicsEntry),
+ 0,
+ (GInstanceInitFunc) ephy_topics_entry_init
+ };
+
+ type = g_type_register_static (GTK_TYPE_ENTRY,
+ "EphyTopicsEntry",
+ &our_info, 0);
+ }
+
+ return type;
+}
+
+static void
+update_widget (EphyTopicsEntry *entry)
+{
+ EphyNode *node;
+ GPtrArray *children, *topics;
+ GtkTreeIter iter;
+ gint i, priority;
+ const char *title;
+ char *tmp1, *tmp2;
+ gboolean update_text;
+
+ entry->priv->update_keywords = FALSE;
+
+ update_text = !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry));
+ gtk_entry_set_completion (GTK_ENTRY (entry), NULL);
+ gtk_list_store_clear (entry->priv->store);
+ if (update_text) gtk_entry_set_text (GTK_ENTRY (entry), "");
+
+ node = ephy_bookmarks_get_keywords (entry->priv->bookmarks);
+ children = ephy_node_get_children (node);
+ topics = g_ptr_array_sized_new (children->len);
+
+ for (i = 0; i < children->len; i++)
+ {
+ node = g_ptr_array_index (children, i);
+
+ priority = ephy_node_get_property_int (node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ if (priority != EPHY_NODE_NORMAL_PRIORITY)
+ continue;
+
+ g_ptr_array_add (topics, node);
+ }
+
+ g_ptr_array_sort (topics, ephy_bookmarks_compare_topic_pointers);
+
+ for (i = 0; i < topics->len; i++)
+ {
+ node = g_ptr_array_index (topics, i);
+ title = ephy_node_get_property_string (node, EPHY_NODE_KEYWORD_PROP_NAME);
+
+ if (ephy_node_has_child (node, entry->priv->bookmark))
+ {
+ if (update_text)
+ {
+ gtk_entry_append_text (GTK_ENTRY (entry), title);
+ gtk_entry_append_text (GTK_ENTRY (entry), "; ");
+ }
+ }
+ else
+ {
+ tmp1 = g_utf8_casefold (title, -1);
+ tmp2 = g_utf8_normalize (tmp1, -1, G_NORMALIZE_DEFAULT);
+ gtk_list_store_append (entry->priv->store, &iter);
+ gtk_list_store_set (entry->priv->store, &iter, 0, title, 1, tmp2, -1);
+ g_free (tmp2);
+ g_free (tmp1);
+ }
+ }
+
+ g_ptr_array_free (topics, TRUE);
+
+ gtk_entry_set_completion (GTK_ENTRY (entry), entry->priv->completion);
+ if (update_text) gtk_editable_set_position (GTK_EDITABLE (entry), -1);
+
+ entry->priv->update_keywords = TRUE;
+}
+
+static void
+update_action (EphyTopicsEntry *entry)
+{
+ GtkEditable *editable = GTK_EDITABLE (entry);
+ const char *text = gtk_entry_get_text (GTK_ENTRY (entry));
+ char *key;
+ gint start, end;
+
+ if(entry->priv->action)
+ {
+ gtk_entry_completion_delete_action (entry->priv->completion, 0);
+ g_free (entry->priv->action);
+ entry->priv->action = 0;
+ }
+
+ /* Find the start and end locations */
+ start = gtk_editable_get_position (editable);
+ while (start > 0 && text[start-1] != ';')
+ {
+ start--;
+ }
+ if(start > 0 && text[start-1] == ';' && text[start] == ' ')
+ {
+ start++;
+ }
+ end = start;
+ while (text[end] && text[end] != ';')
+ {
+ end++;
+ }
+
+ /* If no text to work with, exit */
+ key = g_strndup (text+start, end-start);
+ g_strstrip (key);
+ if (*key != 0 && ephy_bookmarks_find_keyword (entry->priv->bookmarks, key, FALSE) == NULL)
+ {
+ entry->priv->action = key;
+ key = g_strdup_printf (_("Create topic ā€œ%sā€"), key);
+ gtk_entry_completion_insert_action_text (entry->priv->completion, 0, key);
+ }
+
+ g_free (key);
+}
+
+static void
+update_keywords (EphyTopicsEntry *entry)
+{
+ EphyNode *node;
+ GPtrArray *children;
+ const char *text;
+ char **split;
+ char *title, *tmp;
+ gint i, j, priority;
+
+ if(!entry->priv->update_keywords) return;
+
+ /* Get the list of strings input by the user */
+ text = gtk_entry_get_text (GTK_ENTRY (entry));
+ split = g_strsplit (text, ";", 0);
+ for (i=0; split[i]; i++)
+ {
+ g_strstrip (split[i]);
+
+ tmp = g_utf8_casefold (split[i], -1);
+ g_free (split[i]);
+
+ split[i] = g_utf8_normalize (tmp, -1, G_NORMALIZE_DEFAULT);
+ g_free (tmp);
+ }
+
+ /* Test each keyword and set/unset as appropriate */
+ node = ephy_bookmarks_get_keywords (entry->priv->bookmarks);
+ children = ephy_node_get_children (node);
+ for (i = 0; i < children->len; i++)
+ {
+ node = g_ptr_array_index (children, i);
+
+ priority = ephy_node_get_property_int (node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ if (priority != EPHY_NODE_NORMAL_PRIORITY)
+ continue;
+
+ text = ephy_node_get_property_string (node, EPHY_NODE_KEYWORD_PROP_NAME);
+ tmp = g_utf8_casefold (text, -1);
+ title = g_utf8_normalize (tmp, -1, G_NORMALIZE_DEFAULT);
+ g_free (tmp);
+
+ for (j=0; split[j]; j++)
+ if (strcmp (title, split[j]) == 0)
+ break;
+
+ if (split[j])
+ {
+ split[j][0] = 0;
+ ephy_bookmarks_set_keyword (entry->priv->bookmarks, node,
+ entry->priv->bookmark);
+ }
+ else
+ {
+ ephy_bookmarks_unset_keyword (entry->priv->bookmarks, node,
+ entry->priv->bookmark);
+ }
+
+ g_free (title);
+ }
+
+ g_strfreev (split);
+
+ update_action (entry);
+}
+
+static void
+insert_text (EphyTopicsEntry *entry,
+ const char *title)
+{
+ GtkEditable *editable = GTK_EDITABLE (entry);
+ const char *text = gtk_entry_get_text (GTK_ENTRY (entry));
+ char *key;
+ gint start, end;
+
+ /* Find the start and end locations */
+ start = gtk_editable_get_position (editable);
+ while (start > 0 && text[start-1] != ';')
+ {
+ start--;
+ }
+ if(start > 0 && text[start-1] == ';' && text[start] == ' ')
+ {
+ start++;
+ }
+ end = start;
+ while (text[end] && text[end] != ';')
+ {
+ end++;
+ }
+ end = end;
+ if (text[end] == ';')
+ {
+ end++;
+ if (text[end] == ' ')
+ {
+ end++;
+ }
+ }
+
+ /* If we were provided with nothing, then we're meant to find a topic
+ * or create one from whatever has been entered */
+ if (title == NULL)
+ {
+ /* If no text to work with, exit */
+ key = g_strndup (text+start, end-start);
+ g_strstrip (key);
+ if (*key == 0)
+ {
+ g_free (key);
+ return;
+ }
+
+ }
+
+ /* Replace the text in the current position with the title */
+ gtk_editable_delete_text (editable, start, end);
+ gtk_editable_insert_text (editable, title, strlen(title), &start);
+ gtk_editable_insert_text (editable, "; ", 2, &start);
+ gtk_editable_set_position (editable, start);
+ update_widget(entry);
+}
+
+static void
+action_cb (GtkEntryCompletion *completion,
+ gint index,
+ gpointer user_data)
+{
+ EphyTopicsEntry *entry = EPHY_TOPICS_ENTRY (gtk_entry_completion_get_entry (completion));
+ char *action = g_strdup(entry->priv->action);
+
+ if (ephy_bookmarks_find_keyword (entry->priv->bookmarks, action, FALSE) == NULL)
+ {
+ ephy_bookmarks_add_keyword (entry->priv->bookmarks, action);
+ }
+
+ insert_text (entry, action);
+ g_free (action);
+}
+
+static gboolean
+match_selected_cb (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ EphyTopicsEntry *entry = EPHY_TOPICS_ENTRY (gtk_entry_completion_get_entry (completion));
+ char *title;
+
+ gtk_tree_model_get (model, iter, 0, &title, -1);
+ insert_text (entry, title);
+ g_free (title);
+
+ return TRUE;
+}
+
+static void
+tree_changed_cb (EphyBookmarks *bookmarks,
+ EphyTopicsEntry *entry)
+{
+ update_widget(entry);
+}
+
+static gboolean
+focus_out_cb (GtkEditable *editable,
+ GdkEventFocus *event,
+ gpointer user_data)
+{
+ update_widget (EPHY_TOPICS_ENTRY (editable));
+ return FALSE;
+}
+
+static gboolean
+match_func (GtkEntryCompletion *completion,
+ const gchar *key,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ gboolean result;
+ const char *real_key;
+ char *text;
+
+ real_key = g_strrstr (key, ";");
+ if (real_key) real_key++;
+ else real_key = key;
+ while (*real_key == ' ') real_key++;
+
+ gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter, 1, &text, -1);
+ if (text == NULL) return FALSE;
+ result = g_str_has_prefix (text, real_key);
+ g_free (text);
+
+ return result;
+}
+
+static void
+ephy_topics_entry_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyTopicsEntry *entry = EPHY_TOPICS_ENTRY (object);
+
+ switch (prop_id)
+ {
+ case PROP_BOOKMARKS:
+ entry->priv->bookmarks = g_value_get_object (value);
+ g_signal_connect_object (entry->priv->bookmarks, "tree-changed",
+ G_CALLBACK (tree_changed_cb), entry,
+ G_CONNECT_AFTER);
+ break;
+ case PROP_BOOKMARK:
+ entry->priv->bookmark = g_value_get_pointer (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+ephy_topics_entry_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ EphyTopicsEntry *entry;
+ EphyTopicsEntryPrivate *priv;
+
+ object = parent_class->constructor (type, n_construct_properties,
+ construct_params);
+ entry = EPHY_TOPICS_ENTRY (object);
+ priv = EPHY_TOPICS_ENTRY_GET_PRIVATE (object);
+
+ priv->store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ priv->completion = gtk_entry_completion_new ();
+ priv->update_keywords = TRUE;
+
+ gtk_entry_completion_set_model (priv->completion, GTK_TREE_MODEL (priv->store));
+ gtk_entry_completion_set_text_column (priv->completion, 0);
+ gtk_entry_completion_set_popup_completion (priv->completion, TRUE);
+ gtk_entry_completion_set_popup_single_match (priv->completion, TRUE);
+
+ gtk_entry_completion_set_match_func (priv->completion, match_func, NULL, NULL);
+
+ g_signal_connect (priv->completion, "match-selected",
+ G_CALLBACK (match_selected_cb), NULL);
+ g_signal_connect (object, "focus-out-event",
+ G_CALLBACK (focus_out_cb), NULL);
+ g_signal_connect (object, "changed",
+ G_CALLBACK (update_keywords), NULL);
+ g_signal_connect (G_OBJECT (priv->completion), "action-activated",
+ G_CALLBACK (action_cb), NULL);
+
+ update_widget (entry);
+
+ return object;
+}
+
+static void
+ephy_topics_entry_init (EphyTopicsEntry *entry)
+{
+ entry->priv = EPHY_TOPICS_ENTRY_GET_PRIVATE (entry);
+
+}
+
+static void
+ephy_topics_entry_finalize (GObject *object)
+{
+ EphyTopicsEntry *entry = EPHY_TOPICS_ENTRY (object);
+
+ g_free (entry->priv->action);
+
+ parent_class->finalize (object);
+}
+
+GtkWidget *
+ephy_topics_entry_new (EphyBookmarks *bookmarks,
+ EphyNode *bookmark)
+{
+ EphyTopicsEntry *entry;
+
+ g_assert (bookmarks != NULL);
+
+ entry = EPHY_TOPICS_ENTRY (g_object_new
+ (EPHY_TYPE_TOPICS_ENTRY,
+ "bookmarks", bookmarks,
+ "bookmark", bookmark,
+ NULL));
+
+ return GTK_WIDGET (entry);
+}
+
+static void
+ephy_topics_entry_class_init (EphyTopicsEntryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->set_property = ephy_topics_entry_set_property;
+ object_class->constructor = ephy_topics_entry_constructor;
+ object_class->finalize = ephy_topics_entry_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_BOOKMARKS,
+ g_param_spec_object ("bookmarks",
+ "Bookmarks set",
+ "Bookmarks set",
+ EPHY_TYPE_BOOKMARKS,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property (object_class,
+ PROP_BOOKMARK,
+ g_param_spec_pointer ("bookmark",
+ "Bookmark",
+ "Bookmark",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_type_class_add_private (object_class, sizeof(EphyTopicsEntryPrivate));
+}
diff --git a/src/bookmarks/ephy-topics-entry.h b/src/bookmarks/ephy-topics-entry.h
new file mode 100644
index 000000000..295e0ab65
--- /dev/null
+++ b/src/bookmarks/ephy-topics-entry.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2002 Marco Pesenti Gritti <mpeseng@tin.it>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_TOPICS_ENTRY_H
+#define EPHY_TOPICS_ENTRY_H
+
+#include "ephy-bookmarks.h"
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_TOPICS_ENTRY (ephy_topics_entry_get_type ())
+#define EPHY_TOPICS_ENTRY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_TOPICS_ENTRY, EphyTopicsEntry))
+#define EPHY_TOPICS_ENTRY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_TOPICS_ENTRY, EphyTopicsEntryClass))
+#define EPHY_IS_TOPICS_ENTRY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_TOPICS_ENTRY))
+#define EPHY_IS_TOPICS_ENTRY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_TOPICS_ENTRY))
+#define EPHY_TOPICS_ENTRY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_TOPICS_ENTRY, EphyTopicsEntryClass))
+
+typedef struct _EphyTopicsEntryPrivate EphyTopicsEntryPrivate;
+
+typedef struct
+{
+ GtkEntry parent;
+
+ /*< private >*/
+ EphyTopicsEntryPrivate *priv;
+} EphyTopicsEntry;
+
+typedef struct
+{
+ GtkEntryClass parent;
+} EphyTopicsEntryClass;
+
+GType ephy_topics_entry_get_type (void);
+
+GtkWidget *ephy_topics_entry_new (EphyBookmarks *bookmarks,
+ EphyNode *bookmark);
+
+void ephy_topics_entry_insert_topic (EphyTopicsEntry *entry,
+ const char *title);
+
+G_END_DECLS
+
+#endif /* EPHY_TOPICS_ENTRY_H */
diff --git a/src/bookmarks/ephy-topics-palette.c b/src/bookmarks/ephy-topics-palette.c
index ee650b0a1..29ff7b0c5 100644
--- a/src/bookmarks/ephy-topics-palette.c
+++ b/src/bookmarks/ephy-topics-palette.c
@@ -57,10 +57,7 @@ enum
{
COLUMN_TITLE,
COLUMN_NODE,
- COLUMN_WEIGHT,
COLUMN_SELECTED,
- COLUMN_SEPARATOR,
- COLUMN_SELECTABLE,
COLUMNS
};
@@ -106,70 +103,37 @@ append_topics (EphyTopicsPalette *palette,
GtkTreeIter *iter,
gboolean *valid,
gboolean *first,
- const char *label,
- const char *empty,
GPtrArray *topics)
{
EphyNode *node;
const char *title;
- char *noted;
gint i;
+ if (topics->len == 0)
+ {
+ return;
+ }
+
if (!*first)
{
if (!*valid) gtk_list_store_append (palette->priv->store, iter);
gtk_list_store_set (palette->priv->store, iter, COLUMN_TITLE, NULL,
- COLUMN_NODE, NULL, COLUMN_SEPARATOR, TRUE, -1);
+ COLUMN_NODE, NULL, -1);
*valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (palette->priv->store), iter);
}
- if (label != NULL)
+ for (i = 0; i < topics->len ; i++)
{
+ node = g_ptr_array_index (topics, i);
+ title = ephy_node_get_property_string (node, EPHY_NODE_KEYWORD_PROP_NAME);
+
if (!*valid) gtk_list_store_append (palette->priv->store, iter);
- gtk_list_store_set (palette->priv->store, iter, COLUMN_TITLE, label,
- COLUMN_NODE, NULL, COLUMN_SELECTED, FALSE,
- COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
- COLUMN_SEPARATOR, FALSE, COLUMN_SELECTABLE, FALSE, -1);
+ gtk_list_store_set (palette->priv->store, iter, COLUMN_TITLE, title,
+ COLUMN_NODE, node, COLUMN_SELECTED,
+ ephy_node_has_child (node, palette->priv->bookmark), -1);
*valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (palette->priv->store), iter);
*first = FALSE;
}
-
- if (!topics || topics->len == 0)
- {
- if (empty != NULL)
- {
- if (!*valid) gtk_list_store_append (palette->priv->store, iter);
- gtk_list_store_set (palette->priv->store, iter, COLUMN_TITLE, empty,
- COLUMN_NODE, NULL, COLUMN_SELECTED, FALSE,
- COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL,
- COLUMN_SEPARATOR, FALSE, COLUMN_SELECTABLE, FALSE, -1);
- *valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (palette->priv->store), iter);
- *first = FALSE;
- }
- }
- else
- {
- for (i = 0; i < topics->len ; i++)
- {
- node = g_ptr_array_index (topics, i);
- title = ephy_node_get_property_string (node, EPHY_NODE_KEYWORD_PROP_NAME);
- noted = NULL;
- if (ephy_node_get_children(node)->len == 0)
- {
- noted = g_strdup_printf ("%s (unused)", title);
- }
-
- if (!*valid) gtk_list_store_append (palette->priv->store, iter);
- gtk_list_store_set (palette->priv->store, iter, COLUMN_TITLE, noted ? noted : title,
- COLUMN_NODE, node, COLUMN_SELECTED,
- ephy_node_has_child (node, palette->priv->bookmark),
- COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL,
- COLUMN_SEPARATOR, FALSE, COLUMN_SELECTABLE, TRUE, -1);
- *valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (palette->priv->store), iter);
- *first = FALSE;
- g_free (noted);
- }
- }
}
static void
@@ -187,8 +151,6 @@ update_list (EphyTopicsPalette *palette)
if (palette->priv->mode == MODE_LIST)
{
- gtk_tree_view_column_set_title (palette->priv->column, _("By title"));
-
/* Allocate and fill the suggestions array. */
node = ephy_bookmarks_get_keywords (palette->priv->bookmarks);
children = ephy_node_get_children (node);
@@ -205,15 +167,13 @@ update_list (EphyTopicsPalette *palette)
}
g_ptr_array_sort (topics, ephy_bookmarks_compare_topic_pointers);
- append_topics (palette, &iter, &valid, &first, NULL, _("No topics"), topics);
+ append_topics (palette, &iter, &valid, &first, topics);
g_ptr_array_free (topics, TRUE);
}
else if (palette->priv->mode == MODE_GROUPED)
{
GPtrArray *suggested, *selected;
- gtk_tree_view_column_set_title (palette->priv->column, _("By relation"));
-
/* Allocate and fill the bookmarks array. */
node = ephy_bookmarks_get_bookmarks (palette->priv->bookmarks);
children = ephy_node_get_children (node);
@@ -277,9 +237,9 @@ update_list (EphyTopicsPalette *palette)
g_ptr_array_sort (selected, ephy_bookmarks_compare_topic_pointers);
g_ptr_array_sort (suggested, ephy_bookmarks_compare_topic_pointers);
g_ptr_array_sort (topics, ephy_bookmarks_compare_topic_pointers);
- append_topics (palette, &iter, &valid, &first, _("Selection"), _("No selected topics"), selected);
- append_topics (palette, &iter, &valid, &first, _("Subtopics"), _("No more subtopics"), suggested);
- append_topics (palette, &iter, &valid, &first, _("Other"), _("No other topics"), topics);
+ append_topics (palette, &iter, &valid, &first, selected);
+ append_topics (palette, &iter, &valid, &first, suggested);
+ append_topics (palette, &iter, &valid, &first, topics);
g_ptr_array_free (selected, TRUE);
g_ptr_array_free (suggested, TRUE);
g_ptr_array_free (bookmarks, TRUE);
@@ -291,6 +251,8 @@ update_list (EphyTopicsPalette *palette)
valid = gtk_list_store_remove (palette->priv->store, &iter);
}
+ gtk_tree_selection_unselect_all
+ (gtk_tree_view_get_selection (GTK_TREE_VIEW (palette)));
}
static gboolean
@@ -351,14 +313,6 @@ ephy_topics_palette_set_property (GObject *object,
}
static void
-column_clicked (GtkTreeViewColumn *column,
- EphyTopicsPalette *palette)
-{
- palette->priv->mode = (palette->priv->mode+1)%MODES;
- update_list_idle (palette);
-}
-
-static void
cell_edited (GtkCellRendererText *renderer,
const char *path_str,
const char *new_text,
@@ -368,7 +322,7 @@ cell_edited (GtkCellRendererText *renderer,
{
EphyNode *node;
node = ephy_bookmarks_add_keyword (palette->priv->bookmarks, new_text);
- ephy_bookmarks_set_keyword (palette->priv->bookmarks, node,
+ ephy_bookmarks_set_keyword (palette->priv->bookmarks, node,
palette->priv->bookmark);
}
else
@@ -388,30 +342,21 @@ toggled (GtkCellRendererToggle *cell_renderer,
model = gtk_tree_view_get_model (GTK_TREE_VIEW (palette));
- if (gtk_tree_model_get_iter_from_string (model, &iter, path))
+ g_return_if_fail(gtk_tree_model_get_iter_from_string (model, &iter, path));
+
+ gtk_tree_model_get (model, &iter, COLUMN_NODE, &topic, -1);
+
+ if (ephy_node_has_child (topic, palette->priv->bookmark))
{
- gtk_tree_model_get (model, &iter, COLUMN_NODE, &topic, -1);
- if (topic == NULL)
- {
- char *title;
- gtk_tree_model_get (model, &iter, COLUMN_TITLE, &title, -1);
- g_return_if_fail (title != NULL && *title != 0);
- topic = ephy_bookmarks_add_keyword (palette->priv->bookmarks, title);
- g_free (title);
- }
-
- if (ephy_node_has_child (topic, palette->priv->bookmark))
- {
- ephy_bookmarks_unset_keyword (palette->priv->bookmarks,
- topic,
- palette->priv->bookmark);
- }
- else
- {
- ephy_bookmarks_set_keyword (palette->priv->bookmarks,
- topic,
- palette->priv->bookmark);
- }
+ ephy_bookmarks_unset_keyword (palette->priv->bookmarks,
+ topic,
+ palette->priv->bookmark);
+ }
+ else
+ {
+ ephy_bookmarks_set_keyword (palette->priv->bookmarks,
+ topic,
+ palette->priv->bookmark);
}
}
@@ -420,9 +365,9 @@ is_separator (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data)
{
- gboolean separator;
- gtk_tree_model_get (model, iter, COLUMN_SEPARATOR, &separator, -1);
- return separator;
+ EphyNode *node;
+ gtk_tree_model_get (model, iter, COLUMN_NODE, &node, -1);
+ return (node == NULL);
}
static GObject *
@@ -441,35 +386,29 @@ ephy_topics_palette_constructor (GType type,
palette = EPHY_TOPICS_PALETTE (object);
priv = EPHY_TOPICS_PALETTE_GET_PRIVATE (object);
- priv->store = gtk_list_store_new (COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
+ priv->store = gtk_list_store_new (COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
gtk_tree_view_set_model (GTK_TREE_VIEW (object), GTK_TREE_MODEL (priv->store));
g_object_unref (priv->store);
priv->column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_clickable (priv->column, TRUE);
- g_signal_connect (priv->column, "clicked", G_CALLBACK (column_clicked), palette);
renderer = gtk_cell_renderer_toggle_new ();
gtk_tree_view_column_pack_start (priv->column, renderer, FALSE);
gtk_tree_view_column_add_attribute (priv->column, renderer, "active", COLUMN_SELECTED);
- gtk_tree_view_column_add_attribute (priv->column, renderer, "visible", COLUMN_SELECTABLE);
g_signal_connect (renderer, "toggled", G_CALLBACK (toggled), palette);
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (priv->column, renderer, TRUE);
gtk_tree_view_column_add_attribute (priv->column, renderer, "text", COLUMN_TITLE);
- gtk_tree_view_column_add_attribute (priv->column, renderer, "weight", COLUMN_WEIGHT);
g_signal_connect (renderer, "edited", G_CALLBACK (cell_edited), palette);
gtk_tree_view_append_column (GTK_TREE_VIEW (object), priv->column);
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (object), TRUE);
- gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (object), TRUE);
gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (object), is_separator, NULL, NULL);
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (object), TRUE);
gtk_tree_view_set_search_column (GTK_TREE_VIEW (object), COLUMN_TITLE);
- gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (object)), GTK_SELECTION_NONE);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (object), FALSE);
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (object)), GTK_SELECTION_BROWSE);
update_list (palette);
@@ -515,23 +454,28 @@ ephy_topics_palette_class_init (EphyTopicsPaletteClass *klass)
"Bookmarks set",
"Bookmarks set",
EPHY_TYPE_BOOKMARKS,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
g_object_class_install_property (object_class,
PROP_BOOKMARK,
g_param_spec_pointer ("bookmark",
"Bookmark",
"Bookmark",
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
g_object_class_install_property (object_class,
PROP_MODE,
g_param_spec_int ("mode",
"Mode",
"Mode",
- 0, MODES-1, 0, G_PARAM_WRITABLE));
+ 0, MODES-1, 0,
+ G_PARAM_WRITABLE |
+ G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
g_type_class_add_private (object_class, sizeof(EphyTopicsPalettePrivate));
}