Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Wed, 17 Dec 2014 19:20:39 UTC Commit: a6152b072365126e7b77c606a8b391dee9cbbf21 https://github.com/geany/geany-plugins/commit/a6152b072365126e7b77c606a8b391...
Log Message: ----------- webhelper: Add support for basic bookmarks
Modified Paths: -------------- webhelper/README webhelper/src/gwh-browser.c webhelper/src/gwh-browser.h webhelper/src/gwh-keybindings.h webhelper/src/gwh-plugin.c
Modified: webhelper/README 13 lines changed, 12 insertions(+), 1 deletions(-) =================================================================== @@ -19,7 +19,8 @@ Prominent features * Possible automatic reloading of the web view upon document saving; * A web inspector/debugging tool for the web view's content (including a JavaScript console, a viewer and editor of processed HTML and CSS, a network - usage analysis tool and many more, thanks to WebKit). + usage analysis tool and many more, thanks to WebKit); +* Basic bookmarks for quicker access to frequently used URL.
Requirements @@ -46,6 +47,16 @@ When loaded into Geany, this plugins adds a web view in the message window (the default), the sidebar or in a separate window. You can find most of the features from this view.
+Bookmarks +--------- + +To add a bookmark, you can click on the website's icon next to its URL and +check the "Bookmark this website" item. You can alternatively use the +configurable keybinding to toggle the bookmark for the current URL. + +Bookmarks are displayed in the drop-down menu of the URL bar, sorted +alphabetically by domain. +
License =======
Modified: webhelper/src/gwh-browser.c 234 lines changed, 232 insertions(+), 2 deletions(-) =================================================================== @@ -22,6 +22,8 @@ #include "config.h"
#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <glib.h> #include <glib/gi18n-lib.h> #include <gtk/gtk.h> @@ -49,6 +51,26 @@ (GTK_WIDGET_MAPPED ((w))) # endif /* defined (gtk_widget_get_mapped) */ #endif /* GTK_CHECK_VERSION (2, 20, 0) */ +#if ! GTK_CHECK_VERSION (2, 24, 0) +# define GtkComboBoxText GtkComboBox +# define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX +# define GTK_IS_COMBO_BOX_TEXT GTK_IS_COMBO_BOX +# define gtk_combo_box_text_new_with_entry gtk_combo_box_entry_new_text +# define gtk_combo_box_text_append_text gtk_combo_box_append_text +#endif /* GTK_CHECK_VERSION (2, 24, 0) */ +#if ! GTK_CHECK_VERSION (3, 0, 0) +static void +combo_box_text_remove_all (GtkComboBoxText *combo_box) +{ + GtkListStore *store; + + g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (combo_box)); + + store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box))); + gtk_list_store_clear (store); +} +# define gtk_combo_box_text_remove_all combo_box_text_remove_all +#endif /* GTK_CHECK_VERSION (3, 0, 0) */ #if GTK_CHECK_VERSION (3, 0, 0) /* alias GtkObject, we implement the :destroy signal */ # define GtkObject GtkWidget @@ -76,6 +98,7 @@ struct _GwhBrowserPrivate GtkWidget *inspector_web_view;
GtkWidget *url_entry; + GtkWidget *url_combo; GtkToolItem *item_prev; GtkToolItem *item_next; GtkToolItem *item_cancel; @@ -174,6 +197,28 @@ on_settings_browser_last_uri_notify (GObject *object, }
static void +on_settings_browser_bookmarks_notify (GObject *object, + GParamSpec *pspec, + GwhBrowser *self) +{ + gchar **bookmarks; + + g_return_if_fail (GWH_IS_BROWSER (self)); + + gtk_combo_box_text_remove_all (GTK_COMBO_BOX_TEXT (self->priv->url_combo)); + bookmarks = gwh_browser_get_bookmarks (self); + if (bookmarks) { + gchar **p; + + for (p = bookmarks; *p; p++) { + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->priv->url_combo), + *p); + } + g_strfreev (bookmarks); + } +} + +static void on_settings_browser_orientation_notify (GObject *object, GParamSpec *pspec, GwhBrowser *self) @@ -393,6 +438,53 @@ on_url_entry_activate (GtkEntry *entry, }
static void +on_url_combo_active_notify (GtkComboBox *combo, + GParamSpec *pspec, + GwhBrowser *self) +{ + if (gtk_combo_box_get_active (combo) != -1) { + const gchar *uri = gtk_entry_get_text (GTK_ENTRY (self->priv->url_entry)); + + gwh_browser_set_uri (self, uri); + } +} + +static void +on_item_bookmark_toggled (GtkCheckMenuItem *item, + GwhBrowser *self) +{ + if (gtk_check_menu_item_get_active (item)) { + gwh_browser_add_bookmark (self, gwh_browser_get_uri (self)); + } else { + gwh_browser_remove_bookmark (self, gwh_browser_get_uri (self)); + } +} + +static void +on_url_entry_icon_press (GtkEntry *entry, + GtkEntryIconPosition icon_pos, + GdkEventButton *event, + GwhBrowser *self) +{ + if (icon_pos == GTK_ENTRY_ICON_PRIMARY) { + GtkWidget *menu = gtk_menu_new (); + GtkWidget *item; + const gchar *uri = gwh_browser_get_uri (self); + + item = gtk_check_menu_item_new_with_mnemonic (_("Bookmark this website")); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), + gwh_browser_has_bookmark (self, uri)); + g_signal_connect (item, "toggled", + G_CALLBACK (on_item_bookmark_toggled), self); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button, event->time); + } +} + +static void update_history (GwhBrowser *self) { WebKitWebView *web_view = WEBKIT_WEB_VIEW (self->priv->web_view); @@ -671,6 +763,7 @@ gwh_browser_constructed (GObject *object)
/* a bit ugly, fake notifications */ g_object_notify (G_OBJECT (self->priv->settings), "browser-last-uri"); + g_object_notify (G_OBJECT (self->priv->settings), "browser-bookmarks"); g_object_notify (G_OBJECT (self->priv->settings), "browser-orientation"); g_object_notify (G_OBJECT (self->priv->settings), "inspector-window-geometry"); } @@ -827,14 +920,19 @@ create_toolbar (GwhBrowser *self) gtk_toolbar_insert (GTK_TOOLBAR (toolbar), self->priv->item_reload, -1); gtk_widget_show (GTK_WIDGET (self->priv->item_reload));
- self->priv->url_entry = gtk_entry_new (); + self->priv->url_combo = gtk_combo_box_text_new_with_entry (); item = gtk_tool_item_new (); gtk_tool_item_set_is_important (item, TRUE); - gtk_container_add (GTK_CONTAINER (item), self->priv->url_entry); + gtk_container_add (GTK_CONTAINER (item), self->priv->url_combo); gtk_tool_item_set_expand (item, TRUE); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); gtk_widget_show_all (GTK_WIDGET (item));
+ self->priv->url_entry = gtk_bin_get_child (GTK_BIN (self->priv->url_combo)); + gtk_entry_set_icon_tooltip_text (GTK_ENTRY (self->priv->url_entry), + GTK_ENTRY_ICON_PRIMARY, + _("Website information and settings")); + self->priv->item_inspector = gtk_toggle_tool_button_new_from_stock (GTK_STOCK_INFO); gtk_tool_button_set_label (GTK_TOOL_BUTTON (self->priv->item_inspector), _("Web inspector")); gtk_tool_item_set_tooltip_text (self->priv->item_inspector, _("Toggle web inspector")); @@ -863,6 +961,10 @@ create_toolbar (GwhBrowser *self) G_CALLBACK (on_item_inspector_toggled), self); g_signal_connect (G_OBJECT (self->priv->url_entry), "activate", G_CALLBACK (on_url_entry_activate), self); + g_signal_connect (G_OBJECT (self->priv->url_entry), "icon-press", + G_CALLBACK (on_url_entry_icon_press), self); + g_signal_connect (G_OBJECT (self->priv->url_combo), "notify::active", + G_CALLBACK (on_url_combo_active_notify), self);
return toolbar; } @@ -1059,6 +1161,8 @@ gwh_browser_init (GwhBrowser *self)
g_signal_connect (self->priv->settings, "notify::browser-last-uri", G_CALLBACK (on_settings_browser_last_uri_notify), self); + g_signal_connect (self->priv->settings, "notify::browser-bookmarks", + G_CALLBACK (on_settings_browser_bookmarks_notify), self); g_signal_connect (self->priv->settings, "notify::browser-orientation", G_CALLBACK (on_settings_browser_orientation_notify), self); g_signal_connect (self->priv->settings, "notify::inspector-detached", @@ -1161,3 +1265,129 @@ gwh_browser_toggle_inspector (GwhBrowser *self)
inspector_set_visible (self, ! INSPECTOR_VISIBLE (self)); } + +gchar ** +gwh_browser_get_bookmarks (GwhBrowser *self) +{ + gchar **bookmarks = NULL; + + g_return_val_if_fail (GWH_IS_BROWSER (self), NULL); + + g_object_get (self->priv->settings, "browser-bookmarks", &bookmarks, NULL); + + return bookmarks; +} + +static void +gwh_browser_set_bookmarks (GwhBrowser *self, + gchar **bookmarks) +{ + g_object_set (self->priv->settings, "browser-bookmarks", bookmarks, NULL); +} + +static gint +strv_index (gchar **strv, + const gchar *str) +{ + g_return_val_if_fail (str != NULL, -1); + + if (strv) { + gint idx; + + for (idx = 0; *strv; strv++, idx++) { + if (strcmp (str, *strv) == 0) { + return idx; + } + } + } + + return -1; +} + +gboolean +gwh_browser_has_bookmark (GwhBrowser *self, + const gchar *uri) +{ + gchar **bookmarks = NULL; + gboolean exists = FALSE; + + g_return_val_if_fail (GWH_IS_BROWSER (self), FALSE); + g_return_val_if_fail (uri != NULL, FALSE); + + bookmarks = gwh_browser_get_bookmarks (self); + exists = strv_index (bookmarks, uri) >= 0; + g_strfreev (bookmarks); + + return exists; +} + +static const gchar * +uri_skip_scheme (const gchar *uri) +{ + if (g_ascii_isalpha (*uri)) { + do { + uri++; + } while (*uri == '+' || *uri == '-' || *uri == '.' || + g_ascii_isalnum (*uri)); + /* this is not strictly correct but good enough for what we do */ + while (*uri == ':' || *uri == '/') + uri++; + } + + return uri; +} + +static int +sort_uris (gconstpointer a, + gconstpointer b) +{ + const gchar *uri1 = uri_skip_scheme (*(const gchar *const *) a); + const gchar *uri2 = uri_skip_scheme (*(const gchar *const *) b); + + return g_ascii_strcasecmp (uri1, uri2); +} + +void +gwh_browser_add_bookmark (GwhBrowser *self, + const gchar *uri) +{ + gchar **bookmarks = NULL; + + g_return_if_fail (GWH_IS_BROWSER (self)); + g_return_if_fail (uri != NULL); + + bookmarks = gwh_browser_get_bookmarks (self); + if (strv_index (bookmarks, uri) < 0) { + gsize length = bookmarks ? g_strv_length (bookmarks) : 0; + + bookmarks = g_realloc (bookmarks, (length + 2) * sizeof *bookmarks); + bookmarks[length] = g_strdup (uri); + bookmarks[length + 1] = NULL; + /* it would be faster to insert directly at the right place but who cares */ + qsort (bookmarks, length + 1, sizeof *bookmarks, sort_uris); + gwh_browser_set_bookmarks (self, bookmarks); + } + g_strfreev (bookmarks); +} + +void +gwh_browser_remove_bookmark (GwhBrowser *self, + const gchar *uri) +{ + gchar **bookmarks = NULL; + gint idx; + + g_return_if_fail (GWH_IS_BROWSER (self)); + g_return_if_fail (uri != NULL); + + bookmarks = gwh_browser_get_bookmarks (self); + idx = strv_index (bookmarks, uri); + if (idx >= 0) { + gsize length = g_strv_length (bookmarks); + + memmove (&bookmarks[idx], &bookmarks[idx + 1], + (length - (gsize) idx) * sizeof *bookmarks); + gwh_browser_set_bookmarks (self, bookmarks); + } + g_strfreev (bookmarks); +}
Modified: webhelper/src/gwh-browser.h 11 lines changed, 11 insertions(+), 0 deletions(-) =================================================================== @@ -83,6 +83,17 @@ G_GNUC_INTERNAL GtkWindow *gwh_browser_get_inspector_transient_for (GwhBrowser *self); G_GNUC_INTERNAL void gwh_browser_toggle_inspector (GwhBrowser *self); +G_GNUC_INTERNAL +gchar **gwh_browser_get_bookmarks (GwhBrowser *self); +G_GNUC_INTERNAL +gboolean gwh_browser_has_bookmark (GwhBrowser *self, + const gchar *uri); +G_GNUC_INTERNAL +void gwh_browser_add_bookmark (GwhBrowser *self, + const gchar *uri); +G_GNUC_INTERNAL +void gwh_browser_remove_bookmark (GwhBrowser *self, + const gchar *uri);
G_END_DECLS
Modified: webhelper/src/gwh-keybindings.h 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -32,6 +32,7 @@ G_BEGIN_DECLS enum { GWH_KB_TOGGLE_INSPECTOR, GWH_KB_SHOW_HIDE_SEPARATE_WINDOW, + GWH_KB_TOGGLE_BOOKMARK, GWH_KB_COUNT };
Modified: webhelper/src/gwh-plugin.c 21 lines changed, 21 insertions(+), 0 deletions(-) =================================================================== @@ -284,6 +284,18 @@ on_kb_show_hide_separate_window (guint key_id) } }
+static void +on_kb_toggle_bookmark (guint key_id) +{ + const gchar *uri = gwh_browser_get_uri (GWH_BROWSER (G_browser)); + + if (gwh_browser_has_bookmark (GWH_BROWSER (G_browser), uri)) { + gwh_browser_remove_bookmark (GWH_BROWSER (G_browser), uri); + } else { + gwh_browser_add_bookmark (GWH_BROWSER (G_browser), uri); + } +} +
static gchar * get_config_filename (void) @@ -312,6 +324,12 @@ load_config (void) _("Last URI visited by the browser"), "about:blank", G_PARAM_READWRITE)); + gwh_settings_install_property (G_settings, g_param_spec_boxed ( + "browser-bookmarks", + _("Bookmarks"), + _("List of bookmarks"), + G_TYPE_STRV, + G_PARAM_READWRITE)); gwh_settings_install_property (G_settings, g_param_spec_enum ( "browser-orientation", _("Browser orientation"), @@ -441,6 +459,9 @@ plugin_init (GeanyData *data) on_kb_show_hide_separate_window, 0, 0, "show_hide_separate_window", _("Show/Hide Web View's Window"), NULL); + keybindings_set_item (gwh_keybindings_get_group (), GWH_KB_TOGGLE_BOOKMARK, + on_kb_toggle_bookmark, 0, 0, "toggle_bookmark", + _("Toggle bookmark for the current website"), NULL); }
void
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
plugins-commits@lists.geany.org