diff options
Diffstat (limited to 'src/bookmarks')
-rw-r--r-- | src/bookmarks/ephy-bookmark-properties.c | 451 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmark-properties.h | 2 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-editor.c | 4 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-ui.c | 602 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-ui.h | 10 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks.c | 111 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks.h | 9 |
7 files changed, 925 insertions, 264 deletions
diff --git a/src/bookmarks/ephy-bookmark-properties.c b/src/bookmarks/ephy-bookmark-properties.c index cbeb74019..c545fe101 100644 --- a/src/bookmarks/ephy-bookmark-properties.c +++ b/src/bookmarks/ephy-bookmark-properties.c @@ -21,11 +21,13 @@ #include "config.h" #include "ephy-bookmark-properties.h" -#include "ephy-topics-selector.h" +#include "ephy-bookmarks-ui.h" +#include "ephy-topics-palette.h" #include "ephy-debug.h" #include "ephy-shell.h" #include "ephy-state.h" #include "ephy-gui.h" +#include "ephy-dnd.h" #include "ephy-favicon-cache.h" #include <gtk/gtkcheckbutton.h> @@ -36,11 +38,24 @@ #include <gtk/gtktable.h> #include <gtk/gtklabel.h> #include <gtk/gtkmisc.h> +#include <gtk/gtkliststore.h> #include <gtk/gtkscrolledwindow.h> #include <glib/gi18n.h> +#include <string.h> + +enum +{ + LIST_SEPARATOR, + LIST_ICON, + LIST_FROMFILE +}; + +static const GtkTargetEntry dest_drag_types[] = { + {EPHY_DND_URL_TYPE, 0, 0}, +}; static void ephy_bookmark_properties_class_init (EphyBookmarkPropertiesClass *klass); -static void ephy_bookmark_properties_init (EphyBookmarkProperties *editor); +static void ephy_bookmark_properties_init (EphyBookmarkProperties *properties); static void ephy_bookmark_properties_set_property (GObject *object, guint prop_id, const GValue *value, @@ -56,17 +71,21 @@ struct _EphyBookmarkPropertiesPrivate { EphyBookmarks *bookmarks; EphyNode *bookmark; - - GtkWidget *title_entry; - GtkWidget *location_entry; - GtkWidget *topics_selector; + EphyTopicsPalette *palette; + gboolean creating; }; enum { PROP_0, PROP_BOOKMARKS, - PROP_BOOKMARK + PROP_BOOKMARK, + PROP_CREATING +}; + +enum +{ + RESPONSE_NEW_TOPIC }; static GObjectClass *parent_class = NULL; @@ -124,18 +143,46 @@ ephy_bookmark_properties_class_init (EphyBookmarkPropertiesClass *klass) "Bookmark", G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + g_object_class_install_property (object_class, + PROP_CREATING, + g_param_spec_boolean ("creating", + "New bookmark", + "New bookmark", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_type_class_add_private (object_class, sizeof(EphyBookmarkPropertiesPrivate)); } static void -ephy_bookmark_properties_set_bookmark (EphyBookmarkProperties *selector, +node_destroy_cb (EphyNode *bookmark, + GtkWidget *dialog) +{ + gtk_widget_destroy (dialog); +} + +static void +ephy_bookmark_properties_set_bookmark (EphyBookmarkProperties *properties, EphyNode *bookmark) { LOG ("Set bookmark"); + + if (properties->priv->bookmark) + { + ephy_node_signal_disconnect_object (properties->priv->bookmark, + EPHY_NODE_DESTROY, + (EphyNodeCallback) node_destroy_cb, + G_OBJECT (properties)); + } - selector->priv->bookmark = bookmark; + properties->priv->bookmark = bookmark; - g_object_notify (G_OBJECT (selector), "bookmark"); + ephy_node_signal_connect_object (properties->priv->bookmark, + EPHY_NODE_DESTROY, + (EphyNodeCallback) node_destroy_cb, + G_OBJECT (properties)); + + g_object_notify (G_OBJECT (properties), "bookmark"); } static void @@ -144,16 +191,19 @@ ephy_bookmark_properties_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - EphyBookmarkProperties *selector = EPHY_BOOKMARK_PROPERTIES (object); + EphyBookmarkProperties *properties = EPHY_BOOKMARK_PROPERTIES (object); switch (prop_id) { case PROP_BOOKMARKS: - selector->priv->bookmarks = g_value_get_object (value); + properties->priv->bookmarks = g_value_get_object (value); break; case PROP_BOOKMARK: ephy_bookmark_properties_set_bookmark - (selector, g_value_get_pointer (value)); + (properties, g_value_get_pointer (value)); + break; + case PROP_CREATING: + properties->priv->creating = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -167,12 +217,12 @@ ephy_bookmark_properties_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - EphyBookmarkProperties *selector = EPHY_BOOKMARK_PROPERTIES (object); + EphyBookmarkProperties *properties = EPHY_BOOKMARK_PROPERTIES (object); switch (prop_id) { case PROP_BOOKMARK: - g_value_set_object (value, selector); + g_value_set_object (value, properties); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -181,21 +231,40 @@ ephy_bookmark_properties_get_property (GObject *object, } static void +bookmark_properties_close_cb (GtkDialog *dialog, + gpointer data) +{ + EphyBookmarkProperties *properties = EPHY_BOOKMARK_PROPERTIES (dialog); + if (properties->priv->creating) + { + ephy_node_unref (properties->priv->bookmark); + } +} + +static void bookmark_properties_response_cb (GtkDialog *dialog, int response_id, gpointer data) { + EphyBookmarkProperties *properties = EPHY_BOOKMARK_PROPERTIES (dialog); switch (response_id) { case GTK_RESPONSE_HELP: ephy_gui_help (GTK_WINDOW (dialog), "epiphany", "to-edit-bookmark-properties"); + return; + case RESPONSE_NEW_TOPIC: + ephy_bookmarks_ui_add_topic (GTK_WIDGET (dialog), + properties->priv->bookmark); + return; + case GTK_RESPONSE_CANCEL: + ephy_node_unref (properties->priv->bookmark); break; - case GTK_RESPONSE_CLOSE: - gtk_widget_destroy (GTK_WIDGET (dialog)); + default: break; } + gtk_widget_destroy (GTK_WIDGET (dialog)); } static void @@ -215,19 +284,26 @@ update_entry (EphyBookmarkProperties *props, GtkWidget *entry, guint prop) } static void -update_window_title(EphyBookmarkProperties *editor) +update_window_title (EphyBookmarkProperties *properties) { char *title; const char *tmp; - tmp = ephy_node_get_property_string (editor->priv->bookmark, + tmp = ephy_node_get_property_string (properties->priv->bookmark, EPHY_NODE_BMK_PROP_TITLE); title = g_strdup_printf (_("“%s” Properties"), tmp); - gtk_window_set_title (GTK_WINDOW (editor), title); + gtk_window_set_title (GTK_WINDOW (properties), title); g_free (title); } +static void +combo_changed_cb (GtkComboBox *combobox, GtkWidget *palette) +{ + int 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) { @@ -244,7 +320,7 @@ location_entry_changed_cb (GtkWidget *entry, EphyBookmarkProperties *props) } static void -set_window_icon (EphyBookmarkProperties *editor) +set_window_icon (EphyBookmarkProperties *properties) { EphyFaviconCache *cache; const char *icon_location; @@ -253,7 +329,7 @@ set_window_icon (EphyBookmarkProperties *editor) cache = EPHY_FAVICON_CACHE (ephy_embed_shell_get_favicon_cache (embed_shell)); icon_location = ephy_node_get_property_string - (editor->priv->bookmark, EPHY_NODE_BMK_PROP_ICON); + (properties->priv->bookmark, EPHY_NODE_BMK_PROP_ICON); LOG ("Get favicon for %s", icon_location ? icon_location : "None"); @@ -264,56 +340,243 @@ set_window_icon (EphyBookmarkProperties *editor) if (icon != NULL) { - gtk_window_set_icon (GTK_WINDOW (editor), icon); + gtk_window_set_icon (GTK_WINDOW (properties), icon); g_object_unref (icon); } else { - gtk_window_set_icon_name (GTK_WINDOW (editor), + gtk_window_set_icon_name (GTK_WINDOW (properties), GTK_STOCK_PROPERTIES); } +} + +static void +refresh_icon (GtkComboBox *combobox, const char *location, gboolean set, gboolean create) +{ + EphyFaviconCache *cache; + GtkListStore *store; + GtkTreeIter iter; + GdkPixbuf *icon; + gboolean valid; + const char *filename; + + store = GTK_LIST_STORE (gtk_combo_box_get_model (combobox)); + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); + while (valid) + { + int type; + char *tmp; + + // Check that this is really an icon + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 3, &type, -1); + if (type == LIST_ICON) + { + // Check if it's the icon we're looking for + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &tmp, -1); + if (location == tmp || (tmp != NULL && location != NULL && strcmp (location, tmp) == 0)) + { + g_free (tmp); + break; + } + g_free (tmp); + } + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); + } + + if (!valid && !create) return; + + cache = EPHY_FAVICON_CACHE (ephy_embed_shell_get_favicon_cache (embed_shell)); + icon = (location && *location) ? ephy_favicon_cache_get (cache, location) : NULL; + + if (!valid) + { + filename = g_strrstr (location, "/"); + filename = filename ? (filename+1) : ""; + filename = *filename ? filename : location; + gtk_list_store_insert_with_values (store, &iter, 0, 0, location, 1, filename, 2, icon, 3, LIST_ICON, -1); + } + else + { + gtk_list_store_set (store, &iter, 2, icon, -1); + } + + if (set) + { + gtk_combo_box_set_active_iter (combobox, &iter); + } +} + +static void +icon_changed_cb (GtkComboBox *combobox, + EphyBookmarkProperties *properties) +{ + GValue value = { 0, }; + GtkTreeIter iter; + int type; + char *location; + + gtk_combo_box_get_active_iter (combobox, &iter); + gtk_tree_model_get (gtk_combo_box_get_model (combobox), &iter, 0, &location, 3, &type, -1); + + if (type == LIST_ICON) + { + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, location); + ephy_node_set_property (properties->priv->bookmark, + EPHY_NODE_BMK_PROP_USERICON, + &value); + g_value_unset (&value); + } + else if (type == LIST_FROMFILE) + { + GtkWidget *widget = gtk_file_chooser_dialog_new + (_("Open Icon"), GTK_WINDOW (properties), GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); + gtk_widget_show (widget); + } + + g_free (location); + + refresh_icon (GTK_COMBO_BOX (combobox), + ephy_node_get_property_string (properties->priv->bookmark, EPHY_NODE_BMK_PROP_USERICON), + TRUE, TRUE); +} + +static void +icon_drag_data_received_cb (GObject *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer user) +{ + gchar **netscape_url; + + netscape_url = g_strsplit ((char *)selection_data->data, "\n", 2); + if (!netscape_url || !netscape_url[0]) + { + g_strfreev (netscape_url); + gtk_drag_finish (context, FALSE, FALSE, time); + return; + } + + refresh_icon (GTK_COMBO_BOX (widget), netscape_url[0], TRUE, TRUE); + g_strfreev (netscape_url); + gtk_drag_finish (context, TRUE, TRUE, time); +} + +static void +icon_cache_changed (EphyFaviconCache *cache, const char *url, GtkComboBox *combobox) +{ + refresh_icon (combobox, url, FALSE, FALSE); +} + +static gboolean +is_separator (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + int type; + gtk_tree_model_get (model, iter, 3, &type, -1); + return (type == LIST_SEPARATOR); +} + +static GtkWidget * +build_icon (EphyBookmarkProperties *properties) +{ + EphyFaviconCache *cache; + GtkWidget *combobox; + GtkListStore *store; + GtkTreeIter iter; + GtkCellLayout *layout; + GtkCellRenderer *renderer; + const char *location; + + store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_INT); + combobox = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)); + gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combobox), is_separator, NULL, NULL); + layout = GTK_CELL_LAYOUT (combobox); + + cache = EPHY_FAVICON_CACHE (ephy_embed_shell_get_favicon_cache (embed_shell)); + g_signal_connect (cache, "changed", G_CALLBACK (icon_cache_changed), combobox); + + gtk_list_store_insert_with_values (store, &iter, 0, 0, NULL, 1, _("From file..."), 2, NULL, 3, LIST_FROMFILE, -1); + gtk_list_store_insert_with_values (store, &iter, 0, 0, NULL, 1, NULL, 2, NULL, 3, LIST_SEPARATOR, -1); + gtk_list_store_insert_with_values (store, &iter, 0, 0, "", 1, _("None"), 2, NULL, 3, LIST_ICON, -1); + gtk_list_store_insert_with_values (store, &iter, 0, 0, NULL, 1, _("Default"), 2, NULL, 3, LIST_ICON, -1); + + location = ephy_node_get_property_string (properties->priv->bookmark, EPHY_NODE_BMK_PROP_ICON); + refresh_icon (GTK_COMBO_BOX (combobox), location, FALSE, TRUE); + + location = ephy_node_get_property_string (properties->priv->bookmark, EPHY_NODE_BMK_PROP_USERICON); + refresh_icon (GTK_COMBO_BOX (combobox), location, TRUE, TRUE); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (layout, renderer, TRUE); + gtk_cell_layout_add_attribute (layout, renderer, "text", 1); + + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (layout, renderer, FALSE); + gtk_cell_layout_add_attribute (layout, renderer, "pixbuf", 2); + + g_signal_connect (G_OBJECT (combobox), "changed", G_CALLBACK (icon_changed_cb), properties); + gtk_widget_show (combobox); + + g_signal_connect (G_OBJECT (combobox), "drag_data_received", + G_CALLBACK (icon_drag_data_received_cb), NULL); + gtk_drag_dest_set (combobox, GTK_DEST_DEFAULT_ALL, dest_drag_types, + G_N_ELEMENTS (dest_drag_types), GDK_ACTION_COPY); + + return combobox; } static void -build_ui (EphyBookmarkProperties *editor) +build_ui (EphyBookmarkProperties *properties) { - GtkWidget *table, *label, *entry, *topics_selector; + GtkWidget *table, *label, *entry, *palette; GtkWidget *scrolled_window; + GtkComboBox *cbox; char *str; const char *tmp; - g_signal_connect (G_OBJECT (editor), + g_signal_connect (G_OBJECT (properties), "response", G_CALLBACK (bookmark_properties_response_cb), - editor); + properties); - ephy_state_add_window (GTK_WIDGET(editor), + g_signal_connect (G_OBJECT (properties), + "close", + G_CALLBACK (bookmark_properties_close_cb), + properties); + + ephy_state_add_window (GTK_WIDGET(properties), "bookmark_properties", 290, 280, FALSE, EPHY_STATE_WINDOW_SAVE_SIZE); - update_window_title (editor); - set_window_icon (editor); + update_window_title (properties); + set_window_icon (properties); - gtk_dialog_set_has_separator (GTK_DIALOG (editor), FALSE); - gtk_container_set_border_width (GTK_CONTAINER (editor), 5); - gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (editor)->vbox), 2); + gtk_dialog_set_has_separator (GTK_DIALOG (properties), FALSE); + gtk_container_set_border_width (GTK_CONTAINER (properties), 5); + gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (properties)->vbox), 2); - table = gtk_table_new (2, 2, FALSE); + table = gtk_table_new (5, 2, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 6); gtk_table_set_col_spacings (GTK_TABLE (table), 12); gtk_container_set_border_width (GTK_CONTAINER (GTK_TABLE (table)), 5); gtk_widget_show (table); entry = gtk_entry_new (); - tmp = ephy_node_get_property_string (editor->priv->bookmark, + tmp = ephy_node_get_property_string (properties->priv->bookmark, EPHY_NODE_BMK_PROP_TITLE); gtk_entry_set_text (GTK_ENTRY (entry), tmp); g_signal_connect (entry, "changed", - G_CALLBACK (title_entry_changed_cb), editor); + G_CALLBACK (title_entry_changed_cb), properties); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); - editor->priv->title_entry = entry; gtk_widget_set_size_request (entry, 200, -1); gtk_widget_show (entry); label = gtk_label_new (NULL); @@ -327,13 +590,12 @@ build_ui (EphyBookmarkProperties *editor) gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); entry = gtk_entry_new (); - tmp = ephy_node_get_property_string (editor->priv->bookmark, + tmp = ephy_node_get_property_string (properties->priv->bookmark, EPHY_NODE_BMK_PROP_LOCATION); gtk_entry_set_text (GTK_ENTRY (entry), tmp); g_signal_connect (entry, "changed", - G_CALLBACK (location_entry_changed_cb), editor); + G_CALLBACK (location_entry_changed_cb), properties); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); - editor->priv->location_entry = entry; gtk_widget_show (entry); label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); @@ -344,11 +606,36 @@ build_ui (EphyBookmarkProperties *editor) 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); + + entry = build_icon (properties); + label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + str = g_strconcat ("<b>", _("_Icon:"), "</b>", NULL); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), str); + g_free (str); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); + gtk_widget_show (label); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); + gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3, GTK_FILL, 0, 0, 0); - topics_selector = ephy_topics_selector_new (editor->priv->bookmarks, - editor->priv->bookmark); - gtk_widget_show (topics_selector); - editor->priv->topics_selector = topics_selector; + cbox = GTK_COMBO_BOX (gtk_combo_box_new_text ()); + gtk_widget_show (GTK_WIDGET (cbox)); + gtk_combo_box_append_text (cbox, _("All")); + gtk_combo_box_append_text (cbox, _("Subtopics")); + label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + str = g_strconcat ("<b>", _("T_opics:"), "</b>", NULL); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), str); + g_free (str); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (cbox)); + 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), GTK_WIDGET (cbox), 1, 2, 3, 4, GTK_FILL, 0, 0, 0); + + palette = ephy_topics_palette_new (properties->priv->bookmarks, + properties->priv->bookmark); + properties->priv->palette = EPHY_TOPICS_PALETTE (palette); + gtk_widget_show (palette); scrolled_window = g_object_new (GTK_TYPE_SCROLLED_WINDOW, "hadjustment", NULL, "vadjustment", NULL, @@ -357,59 +644,73 @@ build_ui (EphyBookmarkProperties *editor) "shadow_type", GTK_SHADOW_IN, NULL); gtk_widget_show (scrolled_window); - gtk_container_add (GTK_CONTAINER (scrolled_window), topics_selector); - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); - str = g_strconcat ("<b>", _("To_pics:"), "</b>", NULL); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), str); - g_free (str); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), topics_selector); - gtk_widget_show (label); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); - gtk_table_attach (GTK_TABLE (table), scrolled_window, 1, 2, 2, 3, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_container_add (GTK_CONTAINER (scrolled_window), palette); + + g_signal_connect_object (G_OBJECT (cbox), "changed", G_CALLBACK (combo_changed_cb), + palette, G_CONNECT_AFTER); + + gtk_table_attach (GTK_TABLE (table), scrolled_window, 1, 2, 4, 5, + GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); + gtk_table_set_row_spacing (GTK_TABLE (table), 3, 3); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editor)->vbox), + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (properties)->vbox), table, TRUE, TRUE, 0); - gtk_dialog_add_button (GTK_DIALOG (editor), + + gtk_dialog_add_button (GTK_DIALOG (properties), GTK_STOCK_HELP, GTK_RESPONSE_HELP); - gtk_dialog_add_button (GTK_DIALOG (editor), - GTK_STOCK_CLOSE, - GTK_RESPONSE_CLOSE); - gtk_dialog_set_default_response (GTK_DIALOG (editor), GTK_RESPONSE_CLOSE); + gtk_dialog_add_button (GTK_DIALOG (properties), + _("_New Topic"), + RESPONSE_NEW_TOPIC); + + if (properties->priv->creating) + { + gtk_dialog_add_button (GTK_DIALOG (properties), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + gtk_dialog_add_button (GTK_DIALOG (properties), + GTK_STOCK_OK, + GTK_RESPONSE_OK); + gtk_dialog_set_default_response (GTK_DIALOG (properties), GTK_RESPONSE_OK); + } + else + { + gtk_dialog_add_button (GTK_DIALOG (properties), + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE); + gtk_dialog_set_default_response (GTK_DIALOG (properties), GTK_RESPONSE_CLOSE); + } + + gtk_combo_box_set_active (cbox, 1); } static void -ephy_bookmark_properties_init (EphyBookmarkProperties *editor) +ephy_bookmark_properties_init (EphyBookmarkProperties *properties) { - editor->priv = EPHY_BOOKMARK_PROPERTIES_GET_PRIVATE (editor); + properties->priv = EPHY_BOOKMARK_PROPERTIES_GET_PRIVATE (properties); } GtkWidget * ephy_bookmark_properties_new (EphyBookmarks *bookmarks, EphyNode *bookmark, - GtkWidget *parent_window) + gboolean creating) { - EphyBookmarkProperties *editor; + EphyBookmarkProperties *properties; g_assert (bookmarks != NULL); - editor = EPHY_BOOKMARK_PROPERTIES (g_object_new + properties = EPHY_BOOKMARK_PROPERTIES (g_object_new (EPHY_TYPE_BOOKMARK_PROPERTIES, "bookmarks", bookmarks, "bookmark", bookmark, + "creating", creating, NULL)); - build_ui (editor); + build_ui (properties); - if (parent_window) - { - gtk_window_set_transient_for (GTK_WINDOW (editor), - GTK_WINDOW (parent_window)); - gtk_window_set_destroy_with_parent (GTK_WINDOW (editor), TRUE); - } - return GTK_WIDGET (editor); + gtk_window_set_destroy_with_parent (GTK_WINDOW (properties), TRUE); + + return GTK_WIDGET (properties); } EphyNode * diff --git a/src/bookmarks/ephy-bookmark-properties.h b/src/bookmarks/ephy-bookmark-properties.h index 387736501..887323049 100644 --- a/src/bookmarks/ephy-bookmark-properties.h +++ b/src/bookmarks/ephy-bookmark-properties.h @@ -53,7 +53,7 @@ GType ephy_bookmark_properties_get_type (void); GtkWidget *ephy_bookmark_properties_new (EphyBookmarks *bookmarks, EphyNode *bookmark, - GtkWidget *parent_window); + gboolean creating); EphyNode *ephy_bookmark_properties_get_node (EphyBookmarkProperties *properties); diff --git a/src/bookmarks/ephy-bookmarks-editor.c b/src/bookmarks/ephy-bookmarks-editor.c index baf3f23cf..35841772f 100644 --- a/src/bookmarks/ephy-bookmarks-editor.c +++ b/src/bookmarks/ephy-bookmarks-editor.c @@ -48,6 +48,7 @@ #include "ephy-bookmarks-editor.h" #include "ephy-bookmarks-import.h" #include "ephy-bookmarks-export.h" +#include "ephy-bookmarks-ui.h" #include "ephy-node-common.h" #include "ephy-node-view.h" #include "ephy-window.h" @@ -461,8 +462,7 @@ static void show_properties_dialog (EphyBookmarksEditor *editor, EphyNode *bookmark) { - ephy_bookmarks_show_bookmark_properties - (editor->priv->bookmarks, bookmark, GTK_WIDGET (editor)); + ephy_bookmarks_ui_show_bookmark (GTK_WIDGET (editor), bookmark); } static GSList * diff --git a/src/bookmarks/ephy-bookmarks-ui.c b/src/bookmarks/ephy-bookmarks-ui.c index 0083fb4e5..ae801ff36 100644 --- a/src/bookmarks/ephy-bookmarks-ui.c +++ b/src/bookmarks/ephy-bookmarks-ui.c @@ -29,6 +29,7 @@ #include "ephy-open-tabs-action.h" #include "ephy-topic-factory-action.h" #include "ephy-bookmark-factory-action.h" +#include "ephy-bookmark-properties.h" #include "ephy-node-common.h" #include "ephy-link.h" #include "ephy-dnd.h" @@ -37,6 +38,8 @@ #include "ephy-string.h" #include "ephy-debug.h" #include "ephy-file-helpers.h" +#include "ephy-gui.h" +#include "egg-editable-toolbar.h" #include <string.h> #include <glib/gi18n.h> @@ -46,13 +49,14 @@ typedef struct { guint bookmarks_menu; - guint favorites_menu; + guint toolbar_menu; } BookmarksWindowData; static GString * bookmarks_menu_string = 0; -static GString * favorites_menu_string = 0; +static GHashTable *properties_dialogs = 0; + static GtkAction * find_action (GtkUIManager *manager, const char *name) @@ -95,30 +99,46 @@ activate_bookmarks_menu (GtkAction *action, EphyWindow *window) } static void -activate_favorites_menu (GtkAction *action, EphyWindow *window) +activate_bookmark_properties (GtkAction *action, EggEditableToolbar *etoolbar) { - BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY); - if (data && !data->favorites_menu) - { - GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window)); - gtk_ui_manager_ensure_update (manager); - - if (!favorites_menu_string->len) - { - EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell); - EphyNode *favorites = ephy_bookmarks_get_favorites (eb); - - g_string_append (favorites_menu_string, - "<ui><menubar><menu name=\"GoMenu\" action=\"Go\">"); - ephy_bookmarks_menu_build (favorites_menu_string, favorites); - g_string_append (favorites_menu_string, "</menu></menubar></ui>"); - } - - data->favorites_menu = gtk_ui_manager_add_ui_from_string - (manager, favorites_menu_string->str, favorites_menu_string->len, 0); - - gtk_ui_manager_ensure_update (manager); - } + GtkWidget *widget = gtk_widget_get_ancestor + (egg_editable_toolbar_get_selected (etoolbar), GTK_TYPE_TOOL_ITEM); + GtkAction *baction = widget ? g_object_get_data (G_OBJECT (widget), "gtk-action") : NULL; + g_return_if_fail (EPHY_IS_BOOKMARK_ACTION (baction)); + ephy_bookmarks_ui_show_bookmark (GTK_WIDGET (etoolbar), + ephy_bookmark_action_get_bookmark + (EPHY_BOOKMARK_ACTION (baction))); +} + +static void +activate_bookmark_open_tab (GtkAction *action, EggEditableToolbar *etoolbar) +{ + GtkWidget *widget = gtk_widget_get_ancestor + (egg_editable_toolbar_get_selected (etoolbar), GTK_TYPE_TOOL_ITEM); + GtkAction *baction = widget ? g_object_get_data (G_OBJECT (widget), "gtk-action") : NULL; + g_return_if_fail (EPHY_IS_BOOKMARK_ACTION (baction)); + ephy_bookmark_action_activate (EPHY_BOOKMARK_ACTION (baction), widget, EPHY_LINK_NEW_TAB); +} + +static void +activate_bookmark_open_window (GtkAction *action, EggEditableToolbar *etoolbar) +{ + GtkWidget *widget = gtk_widget_get_ancestor + (egg_editable_toolbar_get_selected (etoolbar), GTK_TYPE_TOOL_ITEM); + GtkAction *baction = widget ? g_object_get_data (G_OBJECT (widget), "gtk-action") : NULL; + g_return_if_fail (EPHY_IS_BOOKMARK_ACTION (baction)); + ephy_bookmark_action_activate (EPHY_BOOKMARK_ACTION (baction), widget, EPHY_LINK_NEW_WINDOW); +} + +static void +selected_bookmark_action (EggEditableToolbar *etoolbar, + GParamSpec *pspec, + GtkAction *action) +{ + GtkWidget *widget = gtk_widget_get_ancestor (egg_editable_toolbar_get_selected (etoolbar), + GTK_TYPE_TOOL_ITEM); + GtkAction *baction = widget ? g_object_get_data (G_OBJECT (widget), "gtk-action") : NULL; + gtk_action_set_visible (action, EPHY_IS_BOOKMARK_ACTION (baction)); } static void @@ -136,20 +156,6 @@ erase_bookmarks_menu (EphyWindow *window) } static void -erase_favorites_menu (EphyWindow *window) -{ - BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY); - GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window)); - - if (data != NULL && data->favorites_menu != 0) - { - gtk_ui_manager_remove_ui (manager, data->favorites_menu); - data->favorites_menu = 0; - } - g_string_truncate (favorites_menu_string, 0); -} - -static void tree_changed_cb (EphyBookmarks *bookmarks, EphyWindow *window) { erase_bookmarks_menu (window); @@ -159,7 +165,6 @@ static void node_added_cb (EphyNode *parent, EphyNode *child, EphyWindow *window) { erase_bookmarks_menu (window); - erase_favorites_menu (window); } static void @@ -168,7 +173,6 @@ node_changed_cb (EphyNode *parent, EphyNode *child, guint property_id, EphyWindo if (property_id == EPHY_NODE_KEYWORD_PROP_NAME || property_id == EPHY_NODE_BMK_PROP_TITLE) { erase_bookmarks_menu (window); - erase_favorites_menu (window); } } @@ -176,7 +180,6 @@ static void node_removed_cb (EphyNode *parent, EphyNode *child, guint index, EphyWindow *window) { erase_bookmarks_menu (window); - erase_favorites_menu (window); } void @@ -185,10 +188,10 @@ ephy_bookmarks_ui_attach_window (EphyWindow *window) EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell); EphyNode *bookmarks = ephy_bookmarks_get_bookmarks (eb); EphyNode *topics = ephy_bookmarks_get_keywords (eb); - EphyNode *favorites = ephy_bookmarks_get_favorites (eb); BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY); GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window)); + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (ephy_window_get_toolbar (window)); GtkActionGroup *actions; GtkAction *action; @@ -196,10 +199,13 @@ ephy_bookmarks_ui_attach_window (EphyWindow *window) data = g_new0 (BookmarksWindowData, 1); g_object_set_data_full (G_OBJECT (window), BM_WINDOW_DATA_KEY, data, g_free); + + /* Create the self-maintaining action groups for bookmarks and topics */ actions = ephy_bookmark_group_new (bookmarks); gtk_ui_manager_insert_action_group (manager, actions, 0); - g_signal_connect_swapped (G_OBJECT (actions), "open-link", - G_CALLBACK (ephy_link_open), G_OBJECT (window)); + g_signal_connect_object (G_OBJECT (actions), "open-link", + G_CALLBACK (ephy_link_open), G_OBJECT (window), + G_CONNECT_SWAPPED | G_CONNECT_AFTER); g_object_unref (G_OBJECT (actions)); actions = ephy_topic_group_new (topics, manager); @@ -208,12 +214,19 @@ ephy_bookmarks_ui_attach_window (EphyWindow *window) actions = ephy_open_tabs_group_new (topics); gtk_ui_manager_insert_action_group (manager, actions, 0); - g_signal_connect_swapped (G_OBJECT (actions), "open-link", - G_CALLBACK (ephy_link_open), G_OBJECT (window)); + g_signal_connect_object (G_OBJECT (actions), "open-link", + G_CALLBACK (ephy_link_open), G_OBJECT (window), + G_CONNECT_SWAPPED | G_CONNECT_AFTER); g_object_unref (G_OBJECT (actions)); + + /* Create and add an action group specifically foor bookmarks on the toolbar */ actions = gtk_action_group_new ("BookmarkToolbarActions"); + gtk_ui_manager_insert_action_group (manager, actions, 0); + g_object_unref (G_OBJECT (actions)); + + /* Add factory actions */ action = ephy_topic_factory_action_new ("AddTopicToToolbar"); gtk_action_group_add_action (actions, action); g_object_unref (action); @@ -222,23 +235,64 @@ ephy_bookmarks_ui_attach_window (EphyWindow *window) gtk_action_group_add_action (actions, action); g_object_unref (action); + + /* Add the dynamic 'related topic' action */ action = ephy_related_action_new (EPHY_LINK (window), manager, "RelatedTopic"); gtk_action_group_add_action (actions, action); g_object_unref (action); - gtk_ui_manager_insert_action_group (manager, actions, 0); - g_object_unref (G_OBJECT (actions)); + /* Add popup menu actions that are specific to the bookmark widgets */ + action = gtk_action_new ("ToolbarBookmarkProperties", _("Properties"), + _("Show properties for this bookmark"), GTK_STOCK_PROPERTIES); + g_signal_connect_object (G_OBJECT (action), "activate", + G_CALLBACK (activate_bookmark_properties), + G_OBJECT (etoolbar), 0); + g_signal_connect_object (G_OBJECT (etoolbar), "notify::selected", + G_CALLBACK (selected_bookmark_action), + G_OBJECT (action), 0); + gtk_action_group_add_action (actions, action); + g_object_unref (action); + + action = gtk_action_new ("ToolbarBookmarkOpenInTab", _("Open in New _Tab"), + _("Open this bookmark in a new tab"), NULL); + g_signal_connect_object (G_OBJECT (action), "activate", + G_CALLBACK (activate_bookmark_open_tab), + G_OBJECT (etoolbar), 0); + g_signal_connect_object (G_OBJECT (etoolbar), "notify::selected", + G_CALLBACK (selected_bookmark_action), + G_OBJECT (action), 0); + gtk_action_group_add_action (actions, action); + g_object_unref (action); + + action = gtk_action_new ("ToolbarBookmarkOpenInWindow", _("Open in New _Window"), + _("Open this bookmark in a new window"), NULL); + g_signal_connect_object (G_OBJECT (action), "activate", + G_CALLBACK (activate_bookmark_open_window), + G_OBJECT (etoolbar), 0); + g_signal_connect_object (G_OBJECT (etoolbar), "notify::selected", + G_CALLBACK (selected_bookmark_action), + G_OBJECT (action), 0); + gtk_action_group_add_action (actions, action); + g_object_unref (action); + + data->toolbar_menu = gtk_ui_manager_add_ui_from_string (manager, + "<popup name=\"ToolbarPopup\">" + "<separator/>" + "<menuitem action=\"ToolbarBookmarkOpenInTab\"/>" + "<menuitem action=\"ToolbarBookmarkOpenInWindow\"/>" + "<separator/>" + "<menuitem action=\"ToolbarBookmarkProperties\"/>" + "</popup>", -1, NULL); + + /* Add signal handlers for the bookmark database */ ephy_node_signal_connect_object (bookmarks, EPHY_NODE_CHILD_ADDED, (EphyNodeCallback)node_added_cb, G_OBJECT (window)); ephy_node_signal_connect_object (topics, EPHY_NODE_CHILD_ADDED, (EphyNodeCallback)node_added_cb, G_OBJECT (window)); - ephy_node_signal_connect_object (favorites, EPHY_NODE_CHILD_ADDED, - (EphyNodeCallback)node_added_cb, - G_OBJECT (window)); ephy_node_signal_connect_object (bookmarks, EPHY_NODE_CHILD_REMOVED, (EphyNodeCallback)node_removed_cb, @@ -246,9 +300,6 @@ ephy_bookmarks_ui_attach_window (EphyWindow *window) ephy_node_signal_connect_object (topics, EPHY_NODE_CHILD_REMOVED, (EphyNodeCallback)node_removed_cb, G_OBJECT (window)); - ephy_node_signal_connect_object (favorites, EPHY_NODE_CHILD_REMOVED, - (EphyNodeCallback)node_removed_cb, - G_OBJECT (window)); ephy_node_signal_connect_object (bookmarks, EPHY_NODE_CHILD_CHANGED, (EphyNodeCallback)node_changed_cb, @@ -261,17 +312,13 @@ ephy_bookmarks_ui_attach_window (EphyWindow *window) G_CALLBACK (tree_changed_cb), G_OBJECT (window), 0); - /* Build menus on demand. */ - if (!favorites_menu_string) favorites_menu_string = g_string_new (""); + + /* Setup empty menu strings and add signal handlers to build the menus on demand */ if (!bookmarks_menu_string) bookmarks_menu_string = g_string_new (""); action = find_action (manager, "Bookmarks"); g_signal_connect_object (G_OBJECT (action), "activate", G_CALLBACK (activate_bookmarks_menu), G_OBJECT (window), 0); - action = find_action (manager, "Go"); - g_signal_connect_object (G_OBJECT (action), "activate", - G_CALLBACK (activate_favorites_menu), - G_OBJECT (window), 0); } void @@ -280,7 +327,6 @@ ephy_bookmarks_ui_detach_window (EphyWindow *window) EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell); EphyNode *bookmarks = ephy_bookmarks_get_bookmarks (eb); EphyNode *topics = ephy_bookmarks_get_keywords (eb); - EphyNode *favorites = ephy_bookmarks_get_favorites (eb); BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY); GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window)); @@ -288,7 +334,7 @@ ephy_bookmarks_ui_detach_window (EphyWindow *window) g_return_if_fail (data != 0); if (data->bookmarks_menu) gtk_ui_manager_remove_ui (manager, data->bookmarks_menu); - if (data->favorites_menu) gtk_ui_manager_remove_ui (manager, data->favorites_menu); + if (data->toolbar_menu) gtk_ui_manager_remove_ui (manager, data->toolbar_menu); g_object_set_data (G_OBJECT (window), BM_WINDOW_DATA_KEY, 0); ephy_node_signal_disconnect_object (bookmarks, EPHY_NODE_CHILD_ADDED, @@ -297,9 +343,6 @@ ephy_bookmarks_ui_detach_window (EphyWindow *window) ephy_node_signal_disconnect_object (topics, EPHY_NODE_CHILD_ADDED, (EphyNodeCallback)node_added_cb, G_OBJECT (window)); - ephy_node_signal_disconnect_object (favorites, EPHY_NODE_CHILD_ADDED, - (EphyNodeCallback)node_added_cb, - G_OBJECT (window)); ephy_node_signal_disconnect_object (bookmarks, EPHY_NODE_CHILD_REMOVED, (EphyNodeCallback)node_removed_cb, @@ -307,9 +350,6 @@ ephy_bookmarks_ui_detach_window (EphyWindow *window) ephy_node_signal_disconnect_object (topics, EPHY_NODE_CHILD_REMOVED, (EphyNodeCallback)node_removed_cb, G_OBJECT (window)); - ephy_node_signal_disconnect_object (favorites, EPHY_NODE_CHILD_REMOVED, - (EphyNodeCallback)node_removed_cb, - G_OBJECT (window)); ephy_node_signal_disconnect_object (bookmarks, EPHY_NODE_CHILD_CHANGED, (EphyNodeCallback)node_changed_cb, @@ -324,42 +364,356 @@ ephy_bookmarks_ui_detach_window (EphyWindow *window) action = find_action (manager, "Bookmarks"); g_signal_handlers_disconnect_by_func (G_OBJECT (action), G_CALLBACK (activate_bookmarks_menu), G_OBJECT (window)); +} + +static void +properties_dialog_destroy_cb (EphyBookmarkProperties *dialog, + gpointer user_data) +{ + g_hash_table_remove (properties_dialogs, ephy_bookmark_properties_get_node (dialog)); +} + +static void +add_bookmark (GtkWidget *parent, + const char *location, + const char *title) +{ + GtkWidget *dialog; + EphyBookmarks *bookmarks; + EphyNode *bookmark; - action = find_action (manager, "Go"); - g_signal_handlers_disconnect_by_func - (G_OBJECT (action), G_CALLBACK (activate_favorites_menu), G_OBJECT (window)); + bookmarks = ephy_shell_get_bookmarks (ephy_shell); + bookmark = ephy_bookmarks_add (bookmarks, title, location); + + if (properties_dialogs == 0) + { + properties_dialogs = g_hash_table_new (g_direct_hash, g_direct_equal); + } + + dialog = ephy_bookmark_properties_new (bookmarks, bookmark, TRUE); + if (parent != NULL) gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent)); + + g_signal_connect (dialog, "destroy", + G_CALLBACK (properties_dialog_destroy_cb), bookmarks); + g_hash_table_insert (properties_dialogs, + bookmark, dialog); + + gtk_window_present (GTK_WINDOW (dialog)); } static void -toolbar_node_removed_cb (EphyNode *parent, EphyNode *child, guint index, EggToolbarsModel *model) +duplicate_bookmark_response_cb (GtkWidget *dialog, + int response, + EphyNode *node) { - gint i, j; - char *nid = NULL; - const char *id; + GtkWidget *parent; + parent = GTK_WIDGET (gtk_window_get_transient_for (GTK_WINDOW (dialog))); - switch (ephy_node_get_id (parent)) + if (response == GTK_RESPONSE_ACCEPT) { - case BOOKMARKS_NODE_ID: - nid = ephy_bookmark_action_name (child); - break; - case KEYWORDS_NODE_ID: - nid = ephy_topic_action_name (child); - break; - default: + ephy_bookmarks_ui_show_bookmark (parent, node); + } + else if (response == GTK_RESPONSE_REJECT) + { + const char *location = g_object_get_data (G_OBJECT (dialog), "location"); + const char *title = g_object_get_data (G_OBJECT (dialog), "title"); + add_bookmark (parent, location, title); + } + + gtk_widget_destroy (dialog); +} + +static void +dialog_node_destroy_cb (EphyNode *node, + GtkWidget *dialog) +{ + gtk_widget_destroy (dialog); +} + +void +ephy_bookmarks_ui_add_bookmark (GtkWidget *parent, + const char *location, + const char *title) +{ + EphyBookmarks *bookmarks; + EphyNode *bookmark; + + bookmarks = ephy_shell_get_bookmarks (ephy_shell); + bookmark = location ? ephy_bookmarks_find_bookmark (bookmarks, location) : NULL; + + if (bookmark != NULL) + { + GtkWidget *button, *dialog; + char *str; + + dialog = gtk_message_dialog_new_with_markup + (GTK_WINDOW (parent), GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, GTK_BUTTONS_NONE, + "<span weight=\"bold\" size=\"larger\">%s</span>", + _("Bookmark exists")); + + str = g_strdup_printf + (_("You already have a bookmark titled “%s” for this page."), + "<span weight=\"bold\">%s</span>"); + + gtk_message_dialog_format_secondary_markup + (GTK_MESSAGE_DIALOG (dialog), str, + ephy_node_get_property_string (bookmark, EPHY_NODE_BMK_PROP_TITLE)); + + g_free (str); + + button = gtk_dialog_add_button (GTK_DIALOG (dialog), + _("_Create New"), GTK_RESPONSE_REJECT); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_stock + (GTK_STOCK_NEW, GTK_ICON_SIZE_BUTTON)); + + button = gtk_dialog_add_button (GTK_DIALOG (dialog), + _("_View Properties"), GTK_RESPONSE_ACCEPT); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_stock + (GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_BUTTON)); + + gtk_dialog_add_button (GTK_DIALOG (dialog), + GTK_STOCK_OK, GTK_RESPONSE_OK); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); + + gtk_window_set_title (GTK_WINDOW (dialog), _("Bookmark Exists")); + gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser"); + + g_object_set_data_full (G_OBJECT (dialog), "location", g_strdup (location), g_free); + g_object_set_data_full (G_OBJECT (dialog), "title", g_strdup (title), g_free); + + g_signal_connect (G_OBJECT (dialog), + "response", + G_CALLBACK (duplicate_bookmark_response_cb), + bookmark); + + ephy_node_signal_connect_object (bookmark, EPHY_NODE_DESTROY, + (EphyNodeCallback) dialog_node_destroy_cb, + G_OBJECT (dialog)); + + gtk_window_present (GTK_WINDOW (dialog)); + } + else + { + add_bookmark (parent, location, title); + } +} + +static EphyNode * +ephy_bookmarks_ui_find_topic (const char *name) +{ + EphyBookmarks *bookmarks; + GPtrArray *children; + EphyNode *node; + int i; + + bookmarks = ephy_shell_get_bookmarks (ephy_shell); + node = ephy_bookmarks_get_keywords (bookmarks); + children = ephy_node_get_children (node); + node = NULL; + for (i = 0; i < children->len; i++) + { + const char *title; + + node = g_ptr_array_index (children, i); + title = ephy_node_get_property_string (node, EPHY_NODE_KEYWORD_PROP_NAME); + + if (g_utf8_collate (title, name) == 0) + { + return node; + } + } + + return NULL; +} + +static void +add_topic_changed_cb (GtkEditable *editable, + GtkDialog *dialog) +{ + const char *title = gtk_entry_get_text (GTK_ENTRY (editable)); + gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, *title != 0); +} + +static void +duplicate_topic_response_cb (GtkWidget *dialog, + int response, + EphyNode *node) +{ + gtk_widget_destroy (dialog); +} + +static void +add_topic_response_cb (GtkWidget *dialog, + int response, + EphyNode *bookmark) +{ + if (response == GTK_RESPONSE_OK) + { + EphyBookmarks *bookmarks; + GtkEntry *entry; + EphyNode *topic; + const char *name; + + entry = g_object_get_data (G_OBJECT (dialog), "name"); + name = gtk_entry_get_text (entry); + g_return_if_fail (name && *name); + + topic = ephy_bookmarks_ui_find_topic (name); + if (topic != NULL) + { + GtkWidget *message; + char *str = g_strdup_printf + (_("You already have a topic named “%s”.\nPlease use a new topic name."), + "<span weight=\"bold\">%s</span>"); + + message = gtk_message_dialog_new_with_markup + (GTK_WINDOW (dialog), GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, str, + ephy_node_get_property_string (topic, EPHY_NODE_KEYWORD_PROP_NAME)); + + g_free (str); + + g_signal_connect (message, "response", + G_CALLBACK (duplicate_topic_response_cb), + bookmark); + + gtk_window_group_add_window + (ephy_gui_ensure_window_group (GTK_WINDOW (dialog)), GTK_WINDOW (message)); + gtk_window_present (GTK_WINDOW (message)); + return; + } + + + bookmarks = ephy_shell_get_bookmarks (ephy_shell); + topic = ephy_bookmarks_add_keyword (bookmarks, name); + ephy_bookmarks_set_keyword (bookmarks, topic, bookmark); } + + gtk_widget_destroy (dialog); +} - for (i=egg_toolbars_model_n_toolbars(model)-1; i>=0; i--) - for (j=egg_toolbars_model_n_items(model, i)-1; j>=0; j--) - { - id = egg_toolbars_model_item_nth (model, i, j); - if (!strcmp (id, nid)) - { - egg_toolbars_model_remove_item (model, i, j); - } - } +void +ephy_bookmarks_ui_add_topic (GtkWidget *parent, + EphyNode *bookmark) +{ + GtkWidget *dialog, *hbox, *entry, *label; + GtkContainer *container; + GList *children; + + if (bookmark != NULL) + { + char *str = g_strdup_printf + ("<span weight=\"bold\" size=\"larger\">%s</span>", _("New topic for “%s”")); + + dialog = gtk_message_dialog_new_with_markup + (GTK_WINDOW (parent), GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + str, ephy_node_get_property_string (bookmark, EPHY_NODE_BMK_PROP_TITLE)); + + g_free (str); + } + else + { + dialog = gtk_message_dialog_new_with_markup + (GTK_WINDOW (parent), GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + "<span weight=\"bold\" size=\"larger\">%s</span>", _("New topic")); + } - free (nid); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("Enter a unique name for the topic.")); + + hbox = gtk_hbox_new (FALSE, 12); + gtk_widget_show (hbox); + + entry = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); + gtk_widget_show (entry); + + label = gtk_label_new_with_mnemonic ("_Name:"); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); + gtk_widget_show (label); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0); + + /* Get the hbox which is the first child of the main vbox */ + children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox)); + container = GTK_CONTAINER (children->data); + g_list_free (children); + + /* Get the vbox which is the second child of the hbox */ + children = gtk_container_get_children (container); + container = GTK_CONTAINER (children->next->data); + g_list_free (children); + + gtk_container_add (container, hbox); + g_object_set_data (G_OBJECT (dialog), "name", entry); + + gtk_dialog_add_button (GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + gtk_dialog_add_button (GTK_DIALOG (dialog), + _("Create"), GTK_RESPONSE_OK); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); + + gtk_window_set_title (GTK_WINDOW (dialog), _("New Topic")); + gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser"); + + g_signal_connect (G_OBJECT (dialog), + "response", + G_CALLBACK (add_topic_response_cb), + bookmark); + + g_signal_connect (G_OBJECT (entry), + "changed", + G_CALLBACK (add_topic_changed_cb), + dialog); + + add_topic_changed_cb (GTK_EDITABLE (entry), GTK_DIALOG (dialog)); + + ephy_node_signal_connect_object (bookmark, EPHY_NODE_DESTROY, + (EphyNodeCallback) dialog_node_destroy_cb, + G_OBJECT (dialog)); + + gtk_window_group_add_window + (ephy_gui_ensure_window_group (GTK_WINDOW (parent)), GTK_WINDOW (dialog)); + gtk_window_present (GTK_WINDOW (dialog)); +} + +void +ephy_bookmarks_ui_show_bookmark (GtkWidget *parent, + EphyNode *bookmark) +{ + EphyBookmarks *bookmarks = ephy_shell_get_bookmarks (ephy_shell); + GtkWidget *dialog; + + g_return_if_fail (EPHY_IS_BOOKMARKS (bookmarks)); + g_return_if_fail (EPHY_IS_NODE (bookmark)); + + if (properties_dialogs == 0) + { + properties_dialogs = g_hash_table_new (g_direct_hash, g_direct_equal); + } + + dialog = g_hash_table_lookup (properties_dialogs, bookmark); + + if (dialog == NULL) + { + dialog = ephy_bookmark_properties_new (bookmarks, bookmark, FALSE); + + g_signal_connect (dialog, "destroy", + G_CALLBACK (properties_dialog_destroy_cb), bookmarks); + g_hash_table_insert (properties_dialogs, + bookmark, dialog); + } + + parent = gtk_widget_get_ancestor (parent, GTK_TYPE_WINDOW); + if (parent != NULL) gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent)); + gtk_window_present (GTK_WINDOW (dialog)); } /* Below this line we have functions relating to toolbar code */ @@ -375,7 +729,7 @@ topic_has_data (EggToolbarsItemType *type, EphyNode *node, *topics; guint node_id; - if (sscanf (name, "OpenTopic%u", &node_id) != 1 || + if (sscanf (name, "OpenTopic%u", &node_id) != 1 && sscanf (name, "Tpc%u", &node_id) != 1) return FALSE; node = ephy_bookmarks_get_from_id (eb, node_id); if (!node) return FALSE; @@ -390,7 +744,7 @@ topic_get_data (EggToolbarsItemType *type, EphyNode *node; guint node_id; - if (sscanf (name, "OpenTopic%u", &node_id) != 1 || + if (sscanf (name, "OpenTopic%u", &node_id) != 1 && sscanf (name, "Tpc%u", &node_id) != 1) return NULL; node = ephy_bookmarks_get_from_id (eb, node_id); if (!node) return NULL; @@ -414,7 +768,7 @@ bookmark_has_data (EggToolbarsItemType *type, EphyNode *node; guint node_id; - if (sscanf (name, "OpenBmk%u", &node_id) != 1 || + if (sscanf (name, "OpenBmk%u", &node_id) != 1 && sscanf (name, "Bmk%u", &node_id) != 1) return FALSE; node = ephy_bookmarks_get_from_id (eb, node_id); if (!node) return FALSE; @@ -429,7 +783,7 @@ bookmark_get_data (EggToolbarsItemType *type, EphyNode *node; guint node_id; - if (sscanf (name, "OpenBmk%u", &node_id) != 1 || + if (sscanf (name, "OpenBmk%u", &node_id) != 1 && sscanf (name, "Bmk%u", &node_id) != 1) return NULL; node = ephy_bookmarks_get_from_id (eb, node_id); if (!node) return NULL; @@ -462,11 +816,8 @@ static char * bookmark_new_name (EggToolbarsItemType *type, const char *data) { - EphyHistory *gh; EphyNode *node; gchar **netscape_url; - const char *icon; - const char *title; netscape_url = g_strsplit (data, "\n", 2); if (!netscape_url || !netscape_url[0]) @@ -475,28 +826,43 @@ bookmark_new_name (EggToolbarsItemType *type, return NULL; } - title = netscape_url[1]; - if (title == NULL || title[0] == '\0') - { - title = _("Untitled"); - } + node = ephy_bookmarks_add (eb, netscape_url[1], netscape_url[0]); - node = ephy_bookmarks_add (eb, title, netscape_url[0]); + g_strfreev (netscape_url); - if (node != NULL) - { - gh = EPHY_HISTORY (ephy_embed_shell_get_global_history (embed_shell)); - icon = ephy_history_get_icon (gh, netscape_url[0]); + return ephy_bookmark_action_name (node); +} - if (icon) - { - ephy_bookmarks_set_icon (eb, netscape_url[0], icon); - } +static void +toolbar_node_removed_cb (EphyNode *parent, EphyNode *child, guint index, EggToolbarsModel *model) +{ + gint i, j; + char *nid = NULL; + const char *id; + + switch (ephy_node_get_id (parent)) + { + case BOOKMARKS_NODE_ID: + nid = ephy_bookmark_action_name (child); + break; + case KEYWORDS_NODE_ID: + nid = ephy_topic_action_name (child); + break; + default: + return; } - g_strfreev (netscape_url); - - return ephy_bookmark_action_name (node); + for (i=egg_toolbars_model_n_toolbars(model)-1; i>=0; i--) + for (j=egg_toolbars_model_n_items(model, i)-1; j>=0; j--) + { + id = egg_toolbars_model_item_nth (model, i, j); + if (!strcmp (id, nid)) + { + egg_toolbars_model_remove_item (model, i, j); + } + } + + free (nid); } void diff --git a/src/bookmarks/ephy-bookmarks-ui.h b/src/bookmarks/ephy-bookmarks-ui.h index 084b37eea..e4e1d854d 100644 --- a/src/bookmarks/ephy-bookmarks-ui.h +++ b/src/bookmarks/ephy-bookmarks-ui.h @@ -30,4 +30,14 @@ void ephy_bookmarks_ui_detach_window (EphyWindow *window); void ephy_bookmarks_ui_attach_toolbar_model (EggToolbarsModel *model); void ephy_bookmarks_ui_detach_toolbar_model (EggToolbarsModel *model); +void ephy_bookmarks_ui_add_bookmark (GtkWidget *parent, + const char *location, + const char *title); + +void ephy_bookmarks_ui_add_topic (GtkWidget *parent, + EphyNode *bookmark); + +void ephy_bookmarks_ui_show_bookmark (GtkWidget *parent, + EphyNode *bookmark); + #endif diff --git a/src/bookmarks/ephy-bookmarks.c b/src/bookmarks/ephy-bookmarks.c index 69f01df19..f6f6acd89 100644 --- a/src/bookmarks/ephy-bookmarks.c +++ b/src/bookmarks/ephy-bookmarks.c @@ -70,7 +70,6 @@ struct _EphyBookmarksPrivate EphyNode *smartbookmarks; EphyNode *lower_fav; double lower_score; - GHashTable *props_dialogs; guint disable_bookmark_editing_notifier_id; #ifdef ENABLE_ZEROCONF @@ -861,9 +860,6 @@ ephy_bookmarks_init (EphyBookmarks *eb) "bookmarks.rdf", NULL); - eb->priv->props_dialogs = g_hash_table_new (g_direct_hash, - g_direct_equal); - /* Bookmarks */ eb->priv->bookmarks = ephy_node_new_with_id (db, BOOKMARKS_NODE_ID); g_value_init (&value, G_TYPE_STRING); @@ -1016,8 +1012,6 @@ ephy_bookmarks_finalize (GObject *object) eel_gconf_notification_remove (eb->priv->disable_bookmark_editing_notifier_id); - g_hash_table_destroy (eb->priv->props_dialogs); - if (eb->priv->save_timeout_id != 0) { g_source_remove (eb->priv->save_timeout_id); @@ -1098,25 +1092,43 @@ ephy_bookmarks_add (EphyBookmarks *eb, const char *title, const char *url) { + EphyHistory *history; EphyNode *bm; GValue value = { 0, }; bm = ephy_node_new (eb->priv->db); if (bm == NULL) return NULL; - + + if (url == NULL) return NULL; g_value_init (&value, G_TYPE_STRING); - g_value_set_string (&value, title); - ephy_node_set_property (bm, EPHY_NODE_BMK_PROP_TITLE, - &value); + g_value_set_string (&value, url); + ephy_node_set_property (bm, EPHY_NODE_BMK_PROP_LOCATION, &value); g_value_unset (&value); + if (title == NULL || title[0] == '\0') + { + title = _("Untitled"); + } g_value_init (&value, G_TYPE_STRING); - g_value_set_string (&value, url); - ephy_node_set_property (bm, EPHY_NODE_BMK_PROP_LOCATION, - &value); + g_value_set_string (&value, title); + ephy_node_set_property (bm, EPHY_NODE_BMK_PROP_TITLE, &value); g_value_unset (&value); + history = EPHY_HISTORY (ephy_embed_shell_get_global_history (embed_shell)); + if (history != NULL) + { + const char *icon = ephy_history_get_icon (history, url); + if (icon != NULL) + { + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, icon); + ephy_node_set_property (bm, EPHY_NODE_BMK_PROP_ICON, + &value); + g_value_unset (&value); + } + } + update_has_smart_address (eb, bm, url); update_bookmark_keywords (eb, bm); @@ -1194,6 +1206,28 @@ ephy_bookmarks_set_icon (EphyBookmarks *eb, g_value_unset (&value); } + +void +ephy_bookmarks_set_usericon (EphyBookmarks *eb, + const char *url, + const char *icon) +{ + EphyNode *node; + GValue value = { 0, }; + + g_return_if_fail (icon != NULL); + + node = ephy_bookmarks_find_bookmark (eb, url); + if (node == NULL) return; + + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, icon); + ephy_node_set_property (node, EPHY_NODE_BMK_PROP_USERICON, + &value); + g_value_unset (&value); +} + + /* name must end with '=' */ static char * get_option (char *start, @@ -1354,57 +1388,6 @@ ephy_bookmarks_add_keyword (EphyBookmarks *eb, return key; } - -static void -prop_dialog_destroy_cb (EphyBookmarkProperties *dialog, - EphyBookmarks *bookmarks) -{ - EphyNode *bookmark; - - bookmark = ephy_bookmark_properties_get_node (dialog); - - g_hash_table_remove (bookmarks->priv->props_dialogs, bookmark); -} - -static void -bookmark_destroyed_cb (EphyNode *bookmark, - GtkWidget *dialog) -{ - gtk_widget_destroy (dialog); -} - -GtkWidget * -ephy_bookmarks_show_bookmark_properties (EphyBookmarks *bookmarks, - EphyNode *bookmark, - GtkWidget *parent) -{ - GtkWidget *dialog = NULL; - - g_return_val_if_fail (EPHY_IS_BOOKMARKS (bookmarks), NULL); - g_return_val_if_fail (EPHY_IS_NODE (bookmark), NULL); - - dialog = g_hash_table_lookup (bookmarks->priv->props_dialogs, bookmark); - - if (dialog == NULL) - { - dialog = ephy_bookmark_properties_new (bookmarks, bookmark, parent); - - ephy_node_signal_connect_object (bookmark, - EPHY_NODE_DESTROY, - (EphyNodeCallback) bookmark_destroyed_cb, - G_OBJECT (dialog)); - - g_signal_connect (dialog, "destroy", - G_CALLBACK (prop_dialog_destroy_cb), bookmarks); - g_hash_table_insert (bookmarks->priv->props_dialogs, - bookmark, dialog); - } - - gtk_window_present (GTK_WINDOW (dialog)); - - return dialog; -} - void ephy_bookmarks_remove_keyword (EphyBookmarks *eb, EphyNode *keyword) diff --git a/src/bookmarks/ephy-bookmarks.h b/src/bookmarks/ephy-bookmarks.h index 3322cd3b7..6eefbbc6a 100644 --- a/src/bookmarks/ephy-bookmarks.h +++ b/src/bookmarks/ephy-bookmarks.h @@ -48,6 +48,7 @@ typedef enum EPHY_NODE_BMK_PROP_LOCATION = 3, EPHY_NODE_BMK_PROP_KEYWORDS = 4, EPHY_NODE_KEYWORD_PROP_NAME = 5, + EPHY_NODE_BMK_PROP_USERICON = 6, EPHY_NODE_BMK_PROP_ICON = 7, EPHY_NODE_KEYWORD_PROP_PRIORITY = 8, EPHY_NODE_BMK_PROP_IMMUTABLE = 15 @@ -91,6 +92,10 @@ void ephy_bookmarks_set_icon (EphyBookmarks *eb, const char *url, const char *icon); +void ephy_bookmarks_set_usericon (EphyBookmarks *eb, + const char *url, + const char *icon); + void ephy_bookmarks_set_address (EphyBookmarks *eb, EphyNode *bookmark, const char *address); @@ -101,10 +106,6 @@ char *ephy_bookmarks_resolve_address (EphyBookmarks *eb, guint ephy_bookmarks_get_smart_bookmark_width (EphyNode *bookmark); -GtkWidget *ephy_bookmarks_show_bookmark_properties (EphyBookmarks *bookmarks, - EphyNode *bookmark, - GtkWidget *parent_window); - /* Keywords */ |