diff options
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | libyelp/Makefile.am | 3 | ||||
-rw-r--r-- | libyelp/yelp-help-list.c | 2 | ||||
-rw-r--r-- | libyelp/yelp-search-entry.c | 672 | ||||
-rw-r--r-- | libyelp/yelp-search-entry.h | 77 | ||||
-rw-r--r-- | libyelp/yelp-view.c | 219 | ||||
-rw-r--r-- | libyelp/yelp-view.h | 4 | ||||
-rw-r--r-- | src/yelp-application.c | 205 | ||||
-rw-r--r-- | src/yelp-application.h | 10 | ||||
-rw-r--r-- | src/yelp-window.c | 1021 | ||||
-rw-r--r-- | src/yelp-window.h | 4 |
11 files changed, 1315 insertions, 906 deletions
diff --git a/configure.ac b/configure.ac index 1948fedd..67f5e12d 100644 --- a/configure.ac +++ b/configure.ac @@ -27,10 +27,10 @@ GLIB_GSETTINGS # Library dependecies PKG_CHECK_MODULES(YELP, [ - gio-2.0 >= 2.25.11 + gio-2.0 >= 2.38.0 gio-unix-2.0 gtk+-unix-print-3.0 - gtk+-3.0 >= 3.8.0 + gtk+-3.0 >= 3.11.8 libxml-2.0 >= 2.6.5 libxslt >= 1.1.4 libexslt >= 0.8.1 diff --git a/libyelp/Makefile.am b/libyelp/Makefile.am index a4dd68bd..1314060e 100644 --- a/libyelp/Makefile.am +++ b/libyelp/Makefile.am @@ -9,12 +9,12 @@ libyelp_la_SOURCES = \ yelp-help-list.c \ yelp-info-document.c \ yelp-info-parser.c \ - yelp-location-entry.c \ yelp-magic-decompressor.c \ yelp-mallard-document.c \ yelp-man-document.c \ yelp-man-parser.c \ yelp-marshal.c \ + yelp-search-entry.c \ yelp-settings.c \ yelp-simple-document.c \ yelp-sqlite-storage.c \ @@ -48,6 +48,7 @@ endif libyelp_la_CFLAGS = \ $(YELP_CFLAGS) \ + -Wno-deprecated-declarations \ -DDATADIR=\""$(datadir)"\" \ -DYELP_ICON_PATH=\"$(YELP_ICON_PATH)\" diff --git a/libyelp/yelp-help-list.c b/libyelp/yelp-help-list.c index 9cb72088..4a5c8705 100644 --- a/libyelp/yelp-help-list.c +++ b/libyelp/yelp-help-list.c @@ -347,7 +347,6 @@ help_list_think (YelpHelpList *list) entry->id = docid; entry->filename = filename; entry->type = YELP_URI_DOCUMENT_TYPE_MALLARD; - g_object_unref (child); goto found; } g_free (filename); @@ -361,7 +360,6 @@ help_list_think (YelpHelpList *list) entry->id = docid; entry->filename = filename; entry->type = YELP_URI_DOCUMENT_TYPE_DOCBOOK; - g_object_unref (child); goto found; } g_free (filename); diff --git a/libyelp/yelp-search-entry.c b/libyelp/yelp-search-entry.c new file mode 100644 index 00000000..784ed824 --- /dev/null +++ b/libyelp/yelp-search-entry.c @@ -0,0 +1,672 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2009-2014 Shaun McCance <shaunm@gnome.org> + * + * 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, see <http://www.gnu.org/licenses/>. + * + * Author: Shaun McCance <shaunm@gnome.org> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> +#include <glib/gi18n.h> + +#include "yelp-search-entry.h" +#include "yelp-marshal.h" +#include "yelp-settings.h" + +static void search_entry_constructed (GObject *object); +static void search_entry_dispose (GObject *object); +static void search_entry_finalize (GObject *object); +static void search_entry_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void search_entry_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +/* Signals */ +static void search_entry_location_selected (YelpSearchEntry *entry); +static void search_entry_search_activated (YelpSearchEntry *entry); +static void search_entry_bookmark_clicked (YelpSearchEntry *entry); + + +/* Utilities */ +static void search_entry_set_completion (YelpSearchEntry *entry, + GtkTreeModel *model); + + +/* GtkEntry callbacks */ +static void entry_activate_cb (GtkEntry *text_entry, + gpointer user_data); + +/* GtkEntryCompletion callbacks */ +static void cell_set_completion_bookmark_icon (GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + YelpSearchEntry *entry); +static void cell_set_completion_text_cell (GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + YelpSearchEntry *entry); +static gboolean entry_match_func (GtkEntryCompletion *completion, + const gchar *key, + GtkTreeIter *iter, + YelpSearchEntry *entry); +static gint entry_completion_sort (GtkTreeModel *model, + GtkTreeIter *iter1, + GtkTreeIter *iter2, + gpointer user_data); +static gboolean entry_match_selected (GtkEntryCompletion *completion, + GtkTreeModel *model, + GtkTreeIter *iter, + YelpSearchEntry *entry); +/* YelpView callbacks */ +static void view_loaded (YelpView *view, + YelpSearchEntry *entry); + + +typedef struct _YelpSearchEntryPrivate YelpSearchEntryPrivate; +struct _YelpSearchEntryPrivate +{ + YelpView *view; + YelpBookmarks *bookmarks; + gchar *completion_uri; + + /* do not free below */ + GtkEntryCompletion *completion; +}; + +enum { + COMPLETION_COL_TITLE, + COMPLETION_COL_DESC, + COMPLETION_COL_ICON, + COMPLETION_COL_PAGE, + COMPLETION_COL_FLAGS +}; + +enum { + COMPLETION_FLAG_ACTIVATE_SEARCH = 1<<0 +}; + +enum { + SEARCH_ACTIVATED, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_VIEW, + PROP_BOOKMARKS +}; + +static GHashTable *completions; + +static guint search_entry_signals[LAST_SIGNAL] = {0,}; + +G_DEFINE_TYPE (YelpSearchEntry, yelp_search_entry, GTK_TYPE_SEARCH_ENTRY) +#define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE((object), YELP_TYPE_SEARCH_ENTRY, YelpSearchEntryPrivate)) + +static void +yelp_search_entry_class_init (YelpSearchEntryClass *klass) +{ + GObjectClass *object_class; + + klass->search_activated = search_entry_search_activated; + klass->bookmark_clicked = search_entry_bookmark_clicked; + + object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = search_entry_constructed; + object_class->dispose = search_entry_dispose; + object_class->finalize = search_entry_finalize; + object_class->get_property = search_entry_get_property; + object_class->set_property = search_entry_set_property; + + /** + * YelpSearchEntry::search-activated + * @widget: The #YelpLocationEntry for which the signal was emitted. + * @text: The search text. + * @user_data: User data set when the handler was connected. + * + * This signal will be emitted whenever the user activates a search, generally + * by pressing <keycap>Enter</keycap> in the embedded text entry while @widget + * is in search mode. + **/ + search_entry_signals[SEARCH_ACTIVATED] = + g_signal_new ("search-activated", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (YelpSearchEntryClass, search_activated), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + /** + * YelpLocationEntry:view + * + * The YelpView instance that this location entry controls. + **/ + g_object_class_install_property (object_class, + PROP_VIEW, + g_param_spec_object ("view", + _("View"), + _("A YelpView instance to control"), + YELP_TYPE_VIEW, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * YelpLocationEntry:bookmarks + * + * An instance of an implementation of YelpBookmarks to provide + * bookmark information for this location entry. + **/ + g_object_class_install_property (object_class, + PROP_BOOKMARKS, + g_param_spec_object ("bookmarks", + _("Bookmarks"), + _("A YelpBookmarks implementation instance"), + YELP_TYPE_BOOKMARKS, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_type_class_add_private ((GObjectClass *) klass, + sizeof (YelpSearchEntryPrivate)); + + completions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); +} + +static void +yelp_search_entry_init (YelpSearchEntry *entry) +{ + YelpSearchEntryPrivate *priv = GET_PRIV (entry); +} + +static void +search_entry_constructed (GObject *object) +{ + GtkCellRenderer *bookmark_cell; + GList *cells; + GtkTreeIter iter; + YelpSearchEntryPrivate *priv = GET_PRIV (object); + + g_signal_connect (object, "activate", + G_CALLBACK (entry_activate_cb), object); + + g_signal_connect (priv->view, "loaded", G_CALLBACK (view_loaded), object); +} + +static void +search_entry_dispose (GObject *object) +{ + YelpSearchEntryPrivate *priv = GET_PRIV (object); + + if (priv->view) { + g_object_unref (priv->view); + priv->view = NULL; + } + + if (priv->bookmarks) { + g_object_unref (priv->bookmarks); + priv->bookmarks = NULL; + } + + G_OBJECT_CLASS (yelp_search_entry_parent_class)->dispose (object); +} + +static void +search_entry_finalize (GObject *object) +{ + YelpSearchEntryPrivate *priv = GET_PRIV (object); + + g_free (priv->completion_uri); + + G_OBJECT_CLASS (yelp_search_entry_parent_class)->finalize (object); +} + +static void +search_entry_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + YelpSearchEntryPrivate *priv = GET_PRIV (object); + + switch (prop_id) { + case PROP_VIEW: + g_value_set_object (value, priv->view); + break; + case PROP_BOOKMARKS: + g_value_set_object (value, priv->bookmarks); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +search_entry_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + YelpSearchEntryPrivate *priv = GET_PRIV (object); + + switch (prop_id) { + case PROP_VIEW: + priv->view = g_value_dup_object (value); + break; + case PROP_BOOKMARKS: + priv->bookmarks = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +search_entry_search_activated (YelpSearchEntry *entry) +{ + YelpUri *base, *uri; + YelpSearchEntryPrivate *priv = GET_PRIV (entry); + + g_object_get (priv->view, "yelp-uri", &base, NULL); + if (base == NULL) + return; + uri = yelp_uri_new_search (base, + gtk_entry_get_text (GTK_ENTRY (entry))); + g_object_unref (base); + yelp_view_load_uri (priv->view, uri); + gtk_widget_grab_focus (GTK_WIDGET (priv->view)); +} + +static void +search_entry_bookmark_clicked (YelpSearchEntry *entry) +{ + YelpUri *uri; + gchar *doc_uri, *page_id; + YelpSearchEntryPrivate *priv = GET_PRIV (entry); + + g_object_get (priv->view, + "yelp-uri", &uri, + "page-id", &page_id, + NULL); + doc_uri = yelp_uri_get_document_uri (uri); + if (priv->bookmarks && doc_uri && page_id) { + if (!yelp_bookmarks_is_bookmarked (priv->bookmarks, doc_uri, page_id)) { + gchar *icon, *title; + g_object_get (priv->view, + "page-icon", &icon, + "page-title", &title, + NULL); + yelp_bookmarks_add_bookmark (priv->bookmarks, doc_uri, page_id, icon, title); + g_free (icon); + g_free (title); + } + else { + yelp_bookmarks_remove_bookmark (priv->bookmarks, doc_uri, page_id); + } + } + g_free (doc_uri); + g_free (page_id); + g_object_unref (uri); +} + +static void +search_entry_set_completion (YelpSearchEntry *entry, + GtkTreeModel *model) +{ + YelpSearchEntryPrivate *priv = GET_PRIV (entry); + GList *cells; + GtkCellRenderer *icon_cell, *bookmark_cell; + + priv->completion = gtk_entry_completion_new (); + gtk_entry_completion_set_minimum_key_length (priv->completion, 3); + gtk_entry_completion_set_model (priv->completion, model); + gtk_entry_completion_set_text_column (priv->completion, COMPLETION_COL_TITLE); + gtk_entry_completion_set_match_func (priv->completion, + (GtkEntryCompletionMatchFunc) entry_match_func, + entry, NULL); + g_signal_connect (priv->completion, "match-selected", + G_CALLBACK (entry_match_selected), entry); + + cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->completion)); + g_object_set (cells->data, "xpad", 4, NULL); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->completion), + GTK_CELL_RENDERER (cells->data), + (GtkCellLayoutDataFunc) cell_set_completion_text_cell, + entry, NULL); + g_object_set (cells->data, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + g_list_free (cells); + + icon_cell = gtk_cell_renderer_pixbuf_new (); + g_object_set (icon_cell, "yalign", 0.2, NULL); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->completion), icon_cell, FALSE); + gtk_cell_layout_reorder (GTK_CELL_LAYOUT (priv->completion), icon_cell, 0); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->completion), + icon_cell, + "icon-name", + COMPLETION_COL_ICON, + NULL); + if (priv->bookmarks) { + bookmark_cell = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (priv->completion), bookmark_cell, FALSE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->completion), + bookmark_cell, + (GtkCellLayoutDataFunc) cell_set_completion_bookmark_icon, + entry, NULL); + } + gtk_entry_set_completion (GTK_ENTRY (entry), priv->completion); +} + +static void +entry_activate_cb (GtkEntry *text_entry, + gpointer user_data) +{ + YelpSearchEntryPrivate *priv = GET_PRIV (user_data); + gchar *text = g_strdup (gtk_entry_get_text (text_entry)); + + if (text == NULL || strlen(text) == 0) + return; + + g_signal_emit (user_data, search_entry_signals[SEARCH_ACTIVATED], 0, text); + + g_free (text); +} + +static void +cell_set_completion_bookmark_icon (GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + YelpSearchEntry *entry) +{ + YelpSearchEntryPrivate *priv = GET_PRIV (entry); + + if (priv->completion_uri) { + gchar *page_id = NULL; + gtk_tree_model_get (model, iter, + COMPLETION_COL_PAGE, &page_id, + -1); + + if (page_id && yelp_bookmarks_is_bookmarked (priv->bookmarks, + priv->completion_uri, page_id)) + g_object_set (cell, "icon-name", "yelp-bookmark-remove-symbolic", NULL); + else + g_object_set (cell, "icon-name", NULL, NULL); + + g_free (page_id); + } +} + +static void +cell_set_completion_text_cell (GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + YelpSearchEntry *entry) +{ + gchar *title; + gint flags; + YelpSearchEntryPrivate *priv = GET_PRIV (entry); + + gtk_tree_model_get (model, iter, COMPLETION_COL_FLAGS, &flags, -1); + if (flags & COMPLETION_FLAG_ACTIVATE_SEARCH) { + title = g_strdup_printf (_("Search for ā%sā"), + gtk_entry_get_text (GTK_ENTRY (entry))); + g_object_set (cell, "text", title, NULL); + g_free (title); + return; + } + + gtk_tree_model_get (model, iter, + COMPLETION_COL_TITLE, &title, + -1); + g_object_set (cell, "text", title, NULL); + g_free (title); +} + +static gboolean +entry_match_func (GtkEntryCompletion *completion, + const gchar *key, + GtkTreeIter *iter, + YelpSearchEntry *entry) +{ + gint stri; + gchar *title, *desc, *titlecase = NULL, *desccase = NULL; + gboolean ret = FALSE; + gchar **strs; + gint flags; + GtkTreeModel *model = gtk_entry_completion_get_model (completion); + YelpSearchEntryPrivate *priv = GET_PRIV (entry); + static GRegex *nonword = NULL; + + if (nonword == NULL) + nonword = g_regex_new ("\\W", 0, 0, NULL); + if (nonword == NULL) + return FALSE; + + gtk_tree_model_get (model, iter, COMPLETION_COL_FLAGS, &flags, -1); + if (flags & COMPLETION_FLAG_ACTIVATE_SEARCH) + return TRUE; + + gtk_tree_model_get (model, iter, + COMPLETION_COL_TITLE, &title, + COMPLETION_COL_DESC, &desc, + -1); + if (title) { + titlecase = g_utf8_casefold (title, -1); + g_free (title); + } + if (desc) { + desccase = g_utf8_casefold (desc, -1); + g_free (desc); + } + + strs = g_regex_split (nonword, key, 0); + ret = TRUE; + for (stri = 0; strs[stri]; stri++) { + if (!titlecase || !strstr (titlecase, strs[stri])) { + if (!desccase || !strstr (desccase, strs[stri])) { + ret = FALSE; + break; + } + } + } + + g_free (titlecase); + g_free (desccase); + g_strfreev (strs); + + return ret; +} + +static gint +entry_completion_sort (GtkTreeModel *model, + GtkTreeIter *iter1, + GtkTreeIter *iter2, + gpointer user_data) +{ + gint ret = 0; + gint flags1, flags2; + gchar *key1, *key2; + + gtk_tree_model_get (model, iter1, COMPLETION_COL_FLAGS, &flags1, -1); + gtk_tree_model_get (model, iter2, COMPLETION_COL_FLAGS, &flags2, -1); + if (flags1 & COMPLETION_FLAG_ACTIVATE_SEARCH) + return 1; + else if (flags2 & COMPLETION_FLAG_ACTIVATE_SEARCH) + return -1; + + gtk_tree_model_get (model, iter1, COMPLETION_COL_ICON, &key1, -1); + gtk_tree_model_get (model, iter2, COMPLETION_COL_ICON, &key2, -1); + ret = yelp_settings_cmp_icons (key1, key2); + g_free (key1); + g_free (key2); + + if (ret) + return ret; + + gtk_tree_model_get (model, iter1, COMPLETION_COL_TITLE, &key1, -1); + gtk_tree_model_get (model, iter2, COMPLETION_COL_TITLE, &key2, -1); + if (key1 && key2) + ret = g_utf8_collate (key1, key2); + else if (key2 == NULL) + return -1; + else if (key1 == NULL) + return 1; + g_free (key1); + g_free (key2); + + return ret; +} + +static gboolean +entry_match_selected (GtkEntryCompletion *completion, + GtkTreeModel *model, + GtkTreeIter *iter, + YelpSearchEntry *entry) +{ + YelpUri *base, *uri; + gchar *page, *xref; + gint flags; + YelpSearchEntryPrivate *priv = GET_PRIV (entry); + + gtk_tree_model_get (model, iter, COMPLETION_COL_FLAGS, &flags, -1); + if (flags & COMPLETION_FLAG_ACTIVATE_SEARCH) { + entry_activate_cb (GTK_ENTRY (entry), entry); + return TRUE; + } + + g_object_get (priv->view, "yelp-uri", &base, NULL); + gtk_tree_model_get (model, iter, COMPLETION_COL_PAGE, &page, -1); + + xref = g_strconcat ("xref:", page, NULL); + uri = yelp_uri_new_relative (base, xref); + + yelp_view_load_uri (priv->view, uri); + + g_free (page); + g_free (xref); + g_object_unref (uri); + g_object_unref (base); + + gtk_widget_grab_focus (GTK_WIDGET (priv->view)); + return TRUE; +} + +static void +view_loaded (YelpView *view, + YelpSearchEntry *entry) +{ + gchar **ids; + gint i; + GtkTreeIter iter; + gint flags; + YelpUri *uri; + gchar *doc_uri; + GtkTreeModel *completion; + YelpSearchEntryPrivate *priv = GET_PRIV (entry); + YelpDocument *document = yelp_view_get_document (view); + + g_object_get (view, "yelp-uri", &uri, NULL); + doc_uri = yelp_uri_get_document_uri (uri); + + if ((priv->completion_uri == NULL) || + !g_str_equal (doc_uri, priv->completion_uri)) { + completion = (GtkTreeModel *) g_hash_table_lookup (completions, doc_uri); + if (completion == NULL) { + GtkListStore *base = gtk_list_store_new (5, + G_TYPE_STRING, /* title */ + G_TYPE_STRING, /* desc */ + G_TYPE_STRING, /* icon */ + G_TYPE_STRING, /* uri */ + G_TYPE_INT /* flags */ + ); + completion = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (base)); + gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (completion), + entry_completion_sort, + NULL, NULL); + g_hash_table_insert (completions, g_strdup (doc_uri), completion); + if (document != NULL) { + ids = yelp_document_list_page_ids (document); + for (i = 0; ids[i]; i++) { + gchar *title, *desc, *icon; + gtk_list_store_insert (GTK_LIST_STORE (base), &iter, 0); + title = yelp_document_get_page_title (document, ids[i]); + desc = yelp_document_get_page_desc (document, ids[i]); + icon = yelp_document_get_page_icon (document, ids[i]); + gtk_list_store_set (base, &iter, + COMPLETION_COL_TITLE, title, + COMPLETION_COL_DESC, desc, + COMPLETION_COL_ICON, icon, + COMPLETION_COL_PAGE, ids[i], + -1); + g_free (icon); + g_free (desc); + g_free (title); + } + g_strfreev (ids); + gtk_list_store_insert (GTK_LIST_STORE (base), &iter, 0); + gtk_list_store_set (base, &iter, + COMPLETION_COL_ICON, "edit-find-symbolic", + COMPLETION_COL_FLAGS, COMPLETION_FLAG_ACTIVATE_SEARCH, + -1); + } + g_object_unref (base); + } + g_free (priv->completion_uri); + priv->completion_uri = doc_uri; + search_entry_set_completion (entry, completion); + } + + g_object_unref (uri); +} + +/** + * yelp_search_entry_new: + * @view: A #YelpView. + * + * Creates a new #YelpSearchEntry widget to control @view. + * + * Returns: A new #YelpSearchEntry. + **/ +GtkWidget* +yelp_search_entry_new (YelpView *view, + YelpBookmarks *bookmarks) +{ + GtkWidget *ret; + g_return_val_if_fail (YELP_IS_VIEW (view), NULL); + + ret = GTK_WIDGET (g_object_new (YELP_TYPE_SEARCH_ENTRY, + "view", view, + "bookmarks", bookmarks, + NULL)); + + return ret; +} diff --git a/libyelp/yelp-search-entry.h b/libyelp/yelp-search-entry.h new file mode 100644 index 00000000..df7e3feb --- /dev/null +++ b/libyelp/yelp-search-entry.h @@ -0,0 +1,77 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2009-2014 Shaun McCance <shaunm@gnome.org> + * + * 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, see <http://www.gnu.org/licenses/>. + * + * Author: Shaun McCance <shaunm@gnome.org> + */ + +#ifndef __YELP_SEARCH_ENTRY_H__ +#define __YELP_SEARCH_ENTRY_H__ + +#include <gtk/gtk.h> + +#include "yelp-bookmarks.h" +#include "yelp-view.h" + +G_BEGIN_DECLS + +#define YELP_TYPE_SEARCH_ENTRY (yelp_search_entry_get_type ()) +#define YELP_SEARCH_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), YELP_TYPE_SEARCH_ENTRY, \ + YelpSearchEntry)) +#define YELP_SEARCH_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), YELP_TYPE_SEARCH_ENTRY, \ + YelpSearchEntryClass)) +#define YELP_IS_SEARCH_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), YELP_TYPE_SEARCH_ENTRY)) +#define YELP_IS_SEARCH_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), YELP_TYPE_SEARCH_ENTRY)) +#define YELP_SEARCH_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), YELP_TYPE_SEARCH_ENTRY, \ + YelpSearchEntryClass)) + +/** + * YelpSearchEntry: + **/ +typedef struct _YelpSearchEntry YelpSearchEntry; +typedef struct _YelpSearchEntryClass YelpSearchEntryClass; + +struct _YelpSearchEntry +{ + GtkSearchEntry parent; +}; + +struct _YelpSearchEntryClass +{ + GtkSearchEntryClass parent; + + void (* search_activated) (YelpSearchEntry *entry); + void (* bookmark_clicked) (YelpSearchEntry *entry); + + /* Padding for future expansion */ + void (*_gtk_reserved0) (void); + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); +}; + +GType yelp_search_entry_get_type (void); +GtkWidget * yelp_search_entry_new (YelpView *window, + YelpBookmarks *bookmarks); + +G_END_DECLS + +#endif /* __YELP_SEARCH_ENTRY_H__ */ diff --git a/libyelp/yelp-view.c b/libyelp/yelp-view.c index 1ec960a9..e3e11d39 100644 --- a/libyelp/yelp-view.c +++ b/libyelp/yelp-view.c @@ -104,11 +104,14 @@ static void view_document_loaded (WebKitWebView *vi WebKitWebFrame *frame, gpointer user_data); -static void view_print (GtkAction *action, +static void view_print_action (GAction *action, + GVariant *parameter, YelpView *view); -static void view_history_action (GtkAction *action, +static void view_history_action (GAction *action, + GVariant *parameter, YelpView *view); -static void view_navigation_action (GtkAction *action, +static void view_navigation_action (GAction *action, + GVariant *parameter, YelpView *view); static void view_clear_load (YelpView *view); @@ -126,34 +129,6 @@ static void document_callback (YelpDocument *document, YelpView *view, GError *error); -static const GtkActionEntry entries[] = { - {"YelpViewPrint", GTK_STOCK_PRINT, - N_("_Print..."), - "<Control>P", - NULL, - G_CALLBACK (view_print) }, - {"YelpViewGoBack", GTK_STOCK_GO_BACK, - N_("_Back"), - "<Alt>Left", - NULL, - G_CALLBACK (view_history_action) }, - {"YelpViewGoForward", GTK_STOCK_GO_FORWARD, - N_("_Forward"), - "<Alt>Right", - NULL, - G_CALLBACK (view_history_action) }, - {"YelpViewGoPrevious", NULL, - N_("_Previous Page"), - "<Control>Page_Up", - NULL, - G_CALLBACK (view_navigation_action) }, - {"YelpViewGoNext", NULL, - N_("_Next Page"), - "<Control>Page_Down", - NULL, - G_CALLBACK (view_navigation_action) } -}; - static gchar *nautilus_sendto = NULL; enum { @@ -249,7 +224,11 @@ struct _YelpViewPrivate { GList *back_cur; gboolean back_load; - GtkActionGroup *action_group; + GSimpleAction *print_action; + GSimpleAction *back_action; + GSimpleAction *forward_action; + GSimpleAction *prev_action; + GSimpleAction *next_action; GSList *link_actions; @@ -289,15 +268,39 @@ yelp_view_init (YelpView *view) g_signal_connect (view, "script-alert", G_CALLBACK (view_script_alert), NULL); - priv->action_group = gtk_action_group_new ("YelpView"); - gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (priv->action_group, - entries, G_N_ELEMENTS (entries), - view); - action = gtk_action_group_get_action (priv->action_group, "YelpViewGoBack"); - gtk_action_set_sensitive (action, FALSE); - action = gtk_action_group_get_action (priv->action_group, "YelpViewGoForward"); - gtk_action_set_sensitive (action, FALSE); + priv->print_action = g_simple_action_new ("yelp-view-print", NULL); + g_signal_connect (priv->print_action, + "activate", + G_CALLBACK (view_print_action), + view); + + priv->back_action = g_simple_action_new ("yelp-view-go-back", NULL); + g_simple_action_set_enabled (priv->back_action, FALSE); + g_signal_connect (priv->back_action, + "activate", + G_CALLBACK (view_history_action), + view); + + priv->forward_action = g_simple_action_new ("yelp-view-go-forward", NULL); + g_simple_action_set_enabled (priv->forward_action, FALSE); + g_signal_connect (priv->forward_action, + "activate", + G_CALLBACK (view_history_action), + view); + + priv->prev_action = g_simple_action_new ("yelp-view-go-previous", NULL); + g_simple_action_set_enabled (priv->prev_action, FALSE); + g_signal_connect (priv->prev_action, + "activate", + G_CALLBACK (view_navigation_action), + view); + + priv->next_action = g_simple_action_new ("yelp-view-go-next", NULL); + g_simple_action_set_enabled (priv->next_action, FALSE); + g_signal_connect (priv->next_action, + "activate", + G_CALLBACK (view_navigation_action), + view); } static void @@ -317,9 +320,29 @@ yelp_view_dispose (GObject *object) priv->hadjuster = 0; } - if (priv->action_group) { - g_object_unref (priv->action_group); - priv->action_group = NULL; + if (priv->print_action) { + g_object_unref (priv->print_action); + priv->print_action = NULL; + } + + if (priv->back_action) { + g_object_unref (priv->back_action); + priv->back_action = NULL; + } + + if (priv->forward_action) { + g_object_unref (priv->forward_action); + priv->forward_action = NULL; + } + + if (priv->prev_action) { + g_object_unref (priv->prev_action); + priv->prev_action = NULL; + } + + if (priv->next_action) { + g_object_unref (priv->next_action); + priv->next_action = NULL; } if (priv->document) { @@ -573,12 +596,8 @@ yelp_view_load_uri (YelpView *view, g_object_set (view, "state", YELP_VIEW_STATE_LOADING, NULL); - gtk_action_set_sensitive (gtk_action_group_get_action (priv->action_group, - "YelpViewGoPrevious"), - FALSE); - gtk_action_set_sensitive (gtk_action_group_get_action (priv->action_group, - "YelpViewGoNext"), - FALSE); + g_simple_action_set_enabled (priv->prev_action, FALSE); + g_simple_action_set_enabled (priv->next_action, FALSE); if (!yelp_uri_is_resolved (uri)) { if (priv->resolve_uri != NULL) { @@ -632,11 +651,16 @@ yelp_view_get_document (YelpView *view) return priv->document; } -GtkActionGroup * -yelp_view_get_action_group (YelpView *view) +void +yelp_view_register_actions (YelpView *view, + GActionMap *map) { YelpViewPrivate *priv = GET_PRIV (view); - return priv->action_group; + g_action_map_add_action (map, G_ACTION (priv->print_action)); + g_action_map_add_action (map, G_ACTION (priv->back_action)); + g_action_map_add_action (map, G_ACTION (priv->forward_action)); + g_action_map_add_action (map, G_ACTION (priv->prev_action)); + g_action_map_add_action (map, G_ACTION (priv->next_action)); } /******************************************************************************/ @@ -1330,12 +1354,14 @@ view_populate_popup (YelpView *view, } } else { +#if 0 item = gtk_action_create_menu_item (gtk_action_group_get_action (priv->action_group, "YelpViewGoBack")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); item = gtk_action_create_menu_item (gtk_action_group_get_action (priv->action_group, "YelpViewGoForward")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); +#endif } if ((context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE) || @@ -1520,13 +1546,14 @@ view_document_loaded (WebKitWebView *view, } static void -view_print (GtkAction *action, YelpView *view) +view_print_action (GAction *action, GVariant *parameter, YelpView *view) { webkit_web_frame_print (webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view))); } static void -view_history_action (GtkAction *action, +view_history_action (GAction *action, + GVariant *parameter, YelpView *view) { GList *newcur; @@ -1535,7 +1562,7 @@ view_history_action (GtkAction *action, if (priv->back_cur == NULL) return; - if (g_str_equal (gtk_action_get_name (action), "YelpViewGoBack")) + if (g_str_equal (g_action_get_name (action), "yelp-view-go-back")) newcur = priv->back_cur->next; else newcur = priv->back_cur->prev; @@ -1555,8 +1582,9 @@ view_history_action (GtkAction *action, } static void -view_navigation_action (GtkAction *action, - YelpView *view) +view_navigation_action (GAction *action, + GVariant *parameter, + YelpView *view) { YelpViewPrivate *priv = GET_PRIV (view); gchar *page_id, *new_id, *xref; @@ -1564,14 +1592,14 @@ view_navigation_action (GtkAction *action, page_id = yelp_uri_get_page_id (priv->uri); - if (g_str_equal (gtk_action_get_name (action), "YelpViewGoPrevious")) + if (g_str_equal (g_action_get_name (action), "yelp-view-go-previous")) new_id = yelp_document_get_prev_id (priv->document, page_id); else new_id = yelp_document_get_next_id (priv->document, page_id); /* Just in case we screwed up somewhere */ if (new_id == NULL) { - gtk_action_set_sensitive (action, FALSE); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); return; } @@ -1615,8 +1643,6 @@ view_load_page (YelpView *view) YelpViewPrivate *priv = GET_PRIV (view); gchar *page_id; - debug_print (DB_FUNCTION, "entering\n"); - g_return_if_fail (priv->cancellable == NULL); if (priv->document == NULL) { @@ -1860,8 +1886,6 @@ uri_resolved (YelpUri *uri, YelpViewPrivate *priv = GET_PRIV (view); YelpDocument *document; YelpBackEntry *back; - GtkAction *action; - GSList *proxies, *cur; GError *error = NULL; gchar *struri; GParamSpec *spec; @@ -1936,61 +1960,8 @@ uri_resolved (YelpUri *uri, } priv->back_load = FALSE; - action = gtk_action_group_get_action (priv->action_group, "YelpViewGoBack"); - gtk_action_set_sensitive (action, FALSE); - proxies = gtk_action_get_proxies (action); - if (priv->back_cur->next && priv->back_cur->next->data) { - gchar *tooltip = ""; - back = priv->back_cur->next->data; - - gtk_action_set_sensitive (action, TRUE); - if (back->title && back->desc) { - gchar *color; - color = yelp_settings_get_color (yelp_settings_get_default (), - YELP_SETTINGS_COLOR_TEXT_LIGHT); - tooltip = g_markup_printf_escaped ("<span size='larger'>%s</span>\n<span color='%s'>%s</span>", - back->title, color, back->desc); - g_free (color); - } - else if (back->title) - tooltip = g_markup_printf_escaped ("<span size='larger'>%s</span>", - back->title); - /* Can't seem to use markup on GtkAction tooltip */ - for (cur = proxies; cur != NULL; cur = cur->next) - gtk_widget_set_tooltip_markup (GTK_WIDGET (cur->data), tooltip); - } - else { - for (cur = proxies; cur != NULL; cur = cur->next) - gtk_widget_set_tooltip_text (GTK_WIDGET (cur->data), ""); - } - - action = gtk_action_group_get_action (priv->action_group, "YelpViewGoForward"); - gtk_action_set_sensitive (action, FALSE); - proxies = gtk_action_get_proxies (action); - if (priv->back_cur->prev && priv->back_cur->prev->data) { - gchar *tooltip = ""; - back = priv->back_cur->prev->data; - - gtk_action_set_sensitive (action, TRUE); - if (back->title && back->desc) { - gchar *color; - color = yelp_settings_get_color (yelp_settings_get_default (), - YELP_SETTINGS_COLOR_TEXT_LIGHT); - tooltip = g_markup_printf_escaped ("<span size='larger'>%s</span>\n<span color='%s'>%s</span>", - back->title, color, back->desc); - g_free (color); - } - else if (back->title) - tooltip = g_markup_printf_escaped ("<span size='larger'>%s</span>", - back->title); - /* Can't seem to use markup on GtkAction tooltip */ - for (cur = proxies; cur != NULL; cur = cur->next) - gtk_widget_set_tooltip_markup (GTK_WIDGET (cur->data), tooltip); - } - else { - for (cur = proxies; cur != NULL; cur = cur->next) - gtk_widget_set_tooltip_text (GTK_WIDGET (cur->data), ""); - } + g_simple_action_set_enabled (priv->back_action, (priv->back_cur->next && priv->back_cur->next->data)); + g_simple_action_set_enabled (priv->forward_action, (priv->back_cur->prev && priv->back_cur->prev->data)); spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view), "yelp-uri"); @@ -2045,11 +2016,8 @@ document_callback (YelpDocument *document, { YelpViewPrivate *priv = GET_PRIV (view); - debug_print (DB_FUNCTION, "entering\n"); - if (signal == YELP_DOCUMENT_SIGNAL_INFO) { gchar *prev_id, *next_id, *real_id; - GtkAction *action; YelpBackEntry *back = NULL; GParamSpec *spec; @@ -2086,13 +2054,11 @@ document_callback (YelpDocument *document, } prev_id = yelp_document_get_prev_id (document, priv->page_id); - action = gtk_action_group_get_action (priv->action_group, "YelpViewGoPrevious"); - gtk_action_set_sensitive (action, prev_id != NULL); + g_simple_action_set_enabled (priv->prev_action, prev_id != NULL); g_free (prev_id); next_id = yelp_document_get_next_id (document, priv->page_id); - action = gtk_action_group_get_action (priv->action_group, "YelpViewGoNext"); - gtk_action_set_sensitive (action, next_id != NULL); + g_simple_action_set_enabled (priv->next_action, next_id != NULL); g_free (next_id); spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view), @@ -2116,7 +2082,6 @@ document_callback (YelpDocument *document, const gchar *contents; gchar *mime_type, *page_id, *frag_id, *full_uri; page_id = yelp_uri_get_page_id (priv->uri); - debug_print (DB_ARG, " document.uri.page_id=\"%s\"\n", page_id); mime_type = yelp_document_get_mime_type (document, page_id); contents = yelp_document_read_contents (document, page_id); frag_id = yelp_uri_get_frag_id (priv->uri); diff --git a/libyelp/yelp-view.h b/libyelp/yelp-view.h index 53fe511d..a96feef2 100644 --- a/libyelp/yelp-view.h +++ b/libyelp/yelp-view.h @@ -72,7 +72,9 @@ void yelp_view_load_document (YelpView *view YelpUri *uri, YelpDocument *document); YelpDocument * yelp_view_get_document (YelpView *view); -GtkActionGroup * yelp_view_get_action_group (YelpView *view); + +void yelp_view_register_actions (YelpView *view, + GActionMap *map); void yelp_view_add_link_action (YelpView *view, GtkAction *action, diff --git a/src/yelp-application.c b/src/yelp-application.c index 6f125ba5..20c8266a 100644 --- a/src/yelp-application.c +++ b/src/yelp-application.c @@ -45,7 +45,6 @@ static gboolean editor_mode = FALSE; enum { - READ_LATER_CHANGED, LAST_SIGNAL }; static gint signals[LAST_SIGNAL] = { 0 }; @@ -93,16 +92,14 @@ static gboolean application_window_deleted (YelpWindow *w YelpApplication *app); GSettings * application_get_doc_settings (YelpApplication *app, const gchar *doc_uri); -static void application_adjust_font (GtkAction *action, +static void application_adjust_font (GAction *action, + GVariant *parameter, YelpApplication *app); static void application_set_font_sensitivity (YelpApplication *app); static void bookmarks_changed (GSettings *settings, const gchar *key, YelpApplication *app); -static void readlater_changed (GSettings *settings, - const gchar *key, - YelpApplication *app); static gboolean window_resized (YelpWindow *window, YelpApplication *app); @@ -116,26 +113,15 @@ struct _YelpApplicationPrivate { GSList *windows; GHashTable *windows_by_document; - GtkActionGroup *action_group; + GPropertyAction *show_cursor_action; + GSimpleAction *larger_text_action; + GSimpleAction *smaller_text_action; GSettingsBackend *backend; GSettings *gsettings; GHashTable *docsettings; }; -static const GtkActionEntry action_entries[] = { - { "LargerText", GTK_STOCK_ZOOM_IN, - N_("_Larger Text"), - "<Control>plus", - N_("Increase the size of the text"), - G_CALLBACK (application_adjust_font) }, - { "SmallerText", GTK_STOCK_ZOOM_OUT, - N_("_Smaller Text"), - "<Control>minus", - N_("Decrease the size of the text"), - G_CALLBACK (application_adjust_font) } -}; - static void yelp_application_init (YelpApplication *app) { @@ -143,6 +129,21 @@ yelp_application_init (YelpApplication *app) priv->docsettings = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_object_unref); + + gtk_application_add_accelerator (GTK_APPLICATION (app), "F7", "app.yelp-application-show-cursor", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>plus", "app.yelp-application-larger-text", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>minus", "app.yelp-application-smaller-text", NULL); + + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>f", "win.yelp-window-find", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>s", "win.yelp-window-search", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>n", "win.yelp-window-new", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>w", "win.yelp-window-close", NULL); + + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>p", "win.yelp-view-print", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Alt>Left", "win.yelp-view-go-back", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Alt>Right", "win.yelp-view-go-forward", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>Page_Up", "win.yelp-view-go-previous", NULL); + gtk_application_add_accelerator (GTK_APPLICATION (app), "<Control>Page_Down", "win.yelp-view-go-next", NULL); } static void @@ -158,14 +159,6 @@ yelp_application_class_init (YelpApplicationClass *klass) object_class->dispose = yelp_application_dispose; object_class->finalize = yelp_application_finalize; - signals[READ_LATER_CHANGED] = - g_signal_new ("read-later-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - g_type_class_add_private (klass, sizeof (YelpApplicationPrivate)); } @@ -182,9 +175,19 @@ yelp_application_dispose (GObject *object) { YelpApplicationPrivate *priv = GET_PRIV (object); - if (priv->action_group) { - g_object_unref (priv->action_group); - priv->action_group = NULL; + if (priv->show_cursor_action) { + g_object_unref (priv->show_cursor_action); + priv->show_cursor_action = NULL; + } + + if (priv->larger_text_action) { + g_object_unref (priv->larger_text_action); + priv->larger_text_action = NULL; + } + + if (priv->smaller_text_action) { + g_object_unref (priv->smaller_text_action); + priv->smaller_text_action = NULL; } if (priv->gsettings) { @@ -248,13 +251,11 @@ yelp_application_startup (GApplication *application) YelpApplicationPrivate *priv = GET_PRIV (app); gchar *keyfile; YelpSettings *settings; - GtkAction *action; g_set_application_name (N_("Help")); /* chain up */ - G_APPLICATION_CLASS (yelp_application_parent_class) - ->startup (application); + G_APPLICATION_CLASS (yelp_application_parent_class)->startup (application); settings = yelp_settings_get_default (); if (editor_mode) @@ -265,53 +266,51 @@ yelp_application_startup (GApplication *application) NULL); /* Use a config file for per-document settings, because Ryan asked me to. */ - keyfile = g_build_filename (g_get_user_config_dir (), - "yelp", "yelp.cfg", NULL); + keyfile = g_build_filename (g_get_user_config_dir (), "yelp", "yelp.cfg", NULL); priv->backend = g_keyfile_settings_backend_new (keyfile, "/org/gnome/yelp/", "yelp"); g_free (keyfile); + /* But the main settings are in dconf */ priv->gsettings = g_settings_new ("org.gnome.yelp"); g_settings_bind (priv->gsettings, "show-cursor", settings, "show-text-cursor", G_SETTINGS_BIND_DEFAULT); + priv->show_cursor_action = g_property_action_new ("yelp-application-show-cursor", + settings, "show-text-cursor"); + g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->show_cursor_action)); + g_settings_bind (priv->gsettings, "font-adjustment", settings, "font-adjustment", G_SETTINGS_BIND_DEFAULT); - priv->action_group = gtk_action_group_new ("ApplicationActions"); - gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (priv->action_group, - action_entries, G_N_ELEMENTS (action_entries), - app); - action = (GtkAction *) gtk_toggle_action_new ("ShowTextCursor", - _("Show Text _Cursor"), - NULL, NULL); - gtk_action_group_add_action_with_accel (priv->action_group, - action, "F7"); - g_settings_bind (priv->gsettings, "show-cursor", - action, "active", - G_SETTINGS_BIND_DEFAULT); - g_object_unref (action); + priv->larger_text_action = g_simple_action_new ("yelp-application-larger-text", NULL); + g_signal_connect (priv->larger_text_action, + "activate", + G_CALLBACK (application_adjust_font), + app); + g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->larger_text_action)); + + priv->smaller_text_action = g_simple_action_new ("yelp-application-smaller-text", NULL); + g_signal_connect (priv->smaller_text_action, + "activate", + G_CALLBACK (application_adjust_font), + app); + g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->smaller_text_action)); + application_set_font_sensitivity (app); } /******************************************************************************/ -GtkActionGroup * -yelp_application_get_action_group (YelpApplication *app) -{ - YelpApplicationPrivate *priv = GET_PRIV (app); - return priv->action_group; -} - static void -application_adjust_font (GtkAction *action, +application_adjust_font (GAction *action, + GVariant *parameter, YelpApplication *app) { YelpApplicationPrivate *priv = GET_PRIV (app); gint adjustment = g_settings_get_int (priv->gsettings, "font-adjustment"); - gint adjust = g_str_equal (gtk_action_get_name (action), "LargerText") ? 1 : -1; + gint adjust = g_str_equal (g_action_get_name (action), "yelp-application-larger-text") ? 1 : -1; adjustment += adjust; g_settings_set_int (priv->gsettings, "font-adjustment", adjustment); @@ -331,10 +330,10 @@ application_set_font_sensitivity (YelpApplication *app) g_warning ("Expcected integer param spec for font-adjustment"); return; } - gtk_action_set_sensitive (gtk_action_group_get_action (priv->action_group, "LargerText"), - adjustment < ((GParamSpecInt *) spec)->maximum); - gtk_action_set_sensitive (gtk_action_group_get_action (priv->action_group, "SmallerText"), - adjustment > ((GParamSpecInt *) spec)->minimum); + g_simple_action_set_enabled (priv->larger_text_action, + adjustment < ((GParamSpecInt *) spec)->maximum); + g_simple_action_set_enabled (priv->smaller_text_action, + adjustment > ((GParamSpecInt *) spec)->minimum); } /******************************************************************************/ @@ -531,8 +530,6 @@ application_get_doc_settings (YelpApplication *app, const gchar *doc_uri) g_object_set_data ((GObject *) settings, "doc_uri", key); g_signal_connect (settings, "changed::bookmarks", G_CALLBACK (bookmarks_changed), app); - g_signal_connect (settings, "changed::readlater", - G_CALLBACK (readlater_changed), app); g_free (settings_path); } return settings; @@ -698,76 +695,6 @@ yelp_application_get_bookmarks (YelpApplication *app, return g_settings_get_value (settings, "bookmarks"); } -void -yelp_application_add_read_later (YelpApplication *app, - const gchar *doc_uri, - const gchar *full_uri, - const gchar *title) -{ - GSettings *settings; - - settings = application_get_doc_settings (app, doc_uri); - - if (settings) { - GVariantBuilder builder; - GVariantIter *iter; - gchar *this_uri, *this_title; - gboolean broken = FALSE; - g_settings_get (settings, "readlater", "a(ss)", &iter); - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)")); - while (g_variant_iter_loop (iter, "(&s&s)", &this_uri, &this_title)) { - if (g_str_equal (full_uri, this_uri)) { - /* Already have this link */ - broken = TRUE; - break; - } - g_variant_builder_add (&builder, "(ss)", this_uri, this_title); - } - g_variant_iter_free (iter); - - if (!broken) { - GVariant *value; - g_variant_builder_add (&builder, "(ss)", full_uri, title); - value = g_variant_builder_end (&builder); - g_settings_set_value (settings, "readlater", value); - } - } -} - -void -yelp_application_remove_read_later (YelpApplication *app, - const gchar *doc_uri, - const gchar *full_uri) -{ - GSettings *settings; - - settings = application_get_doc_settings (app, doc_uri); - - if (settings) { - GVariantBuilder builder; - GVariantIter *iter; - gchar *this_uri, *this_title; - g_settings_get (settings, "readlater", "a(ss)", &iter); - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)")); - while (g_variant_iter_loop (iter, "(&s&s)", &this_uri, &this_title)) { - if (!g_str_equal (this_uri, full_uri)) - g_variant_builder_add (&builder, "(ss)", this_uri, this_title); - } - g_variant_iter_free (iter); - - g_settings_set_value (settings, "readlater", g_variant_builder_end (&builder)); - } -} - -GVariant * -yelp_application_get_read_later (YelpApplication *app, - const gchar *doc_uri) -{ - GSettings *settings = application_get_doc_settings (app, doc_uri); - - return g_settings_get_value (settings, "readlater"); -} - static void bookmarks_changed (GSettings *settings, const gchar *key, @@ -778,16 +705,6 @@ bookmarks_changed (GSettings *settings, g_signal_emit_by_name (app, "bookmarks-changed", doc_uri); } -static void -readlater_changed (GSettings *settings, - const gchar *key, - YelpApplication *app) -{ - const gchar *doc_uri = g_object_get_data ((GObject *) settings, "doc_uri"); - if (doc_uri) - g_signal_emit (app, signals[READ_LATER_CHANGED], 0, doc_uri); -} - static gboolean window_resized (YelpWindow *window, YelpApplication *app) diff --git a/src/yelp-application.h b/src/yelp-application.h index 16b74d07..25bcb178 100644 --- a/src/yelp-application.h +++ b/src/yelp-application.h @@ -51,7 +51,6 @@ void yelp_application_new_window (YelpApplication *app, const gchar *uri); void yelp_application_new_window_uri (YelpApplication *app, YelpUri *uri); -GtkActionGroup * yelp_application_get_action_group (YelpApplication *app); void yelp_application_add_bookmark (YelpBookmarks *bookmarks, const gchar *doc_uri, const gchar *page_id, @@ -70,14 +69,5 @@ void yelp_application_update_bookmarks (YelpApplication *app, const gchar *title); GVariant * yelp_application_get_bookmarks (YelpApplication *app, const gchar *doc_uri); -void yelp_application_add_read_later (YelpApplication *app, - const gchar *doc_uri, - const gchar *full_uri, - const gchar *title); -void yelp_application_remove_read_later (YelpApplication *app, - const gchar *doc_uri, - const gchar *full_uri); -GVariant * yelp_application_get_read_later (YelpApplication *app, - const gchar *doc_uri); #endif /* __YELP_APPLICATION_H__ */ diff --git a/src/yelp-window.c b/src/yelp-window.c index e84e226f..6cac2908 100644 --- a/src/yelp-window.c +++ b/src/yelp-window.c @@ -26,9 +26,10 @@ #include <gdk/gdkkeysyms.h> #include <glib/gi18n.h> +#include <gio/gio.h> #include <gtk/gtk.h> -#include "yelp-location-entry.h" +#include "yelp-search-entry.h" #include "yelp-settings.h" #include "yelp-uri.h" #include "yelp-view.h" @@ -50,8 +51,7 @@ static void yelp_window_set_property (GObject *object, GParamSpec *pspec); static void window_construct (YelpWindow *window); -static void window_new (GtkAction *action, - YelpWindow *window); + static gboolean window_map_event (YelpWindow *window, GdkEvent *event, gpointer user_data); @@ -67,49 +67,55 @@ static void window_drag_received (YelpWindow *window, guint time, gpointer userdata); static gboolean window_resize_signal (YelpWindow *window); -static void window_close (GtkAction *action, - YelpWindow *window); -static void window_go_all (GtkAction *action, - YelpWindow *window); -static void window_add_bookmark (GtkAction *action, - YelpWindow *window); -static void window_remove_bookmark (GtkAction *action, - YelpWindow *window); -static void window_load_bookmark (GtkAction *action, + +static void bookmark_activated (GtkListBox *box, + GtkListBoxRow *row, YelpWindow *window); -static void window_find_in_page (GtkAction *action, +static void bookmark_removed (GtkButton *button, YelpWindow *window); -static void window_start_search (GtkAction *action, +static void bookmark_added (GtkButton *button, YelpWindow *window); + + +/* FIXME: all below */ static void window_open_location (GtkAction *action, YelpWindow *window); -static void window_read_later (GtkAction *action, - YelpWindow *window); -static gboolean read_later_clicked (GtkLinkButton *button, - YelpWindow *window); -static void app_read_later_changed (YelpApplication *app, - const gchar *doc_uri, - YelpWindow *window); + + + + static void app_bookmarks_changed (YelpApplication *app, const gchar *doc_uri, YelpWindow *window); static void window_set_bookmarks (YelpWindow *window, const gchar *doc_uri); -static void window_set_bookmark_action (YelpWindow *window); -static gboolean find_entry_focus_out (GtkEntry *entry, - GdkEventFocus *event, - YelpWindow *window); +static void window_set_bookmark_buttons (YelpWindow *window); + +static void action_new_window (GSimpleAction *action, + GVariant *parameter, + gpointer userdata); +static void action_close_window (GSimpleAction *action, + GVariant *parameter, + gpointer userdata); +static void action_search (GSimpleAction *action, + GVariant *parameter, + gpointer userdata); +static void action_find (GSimpleAction *action, + GVariant *parameter, + gpointer userdata); +static void action_go_all (GSimpleAction *action, + GVariant *parameter, + gpointer userdata); + + static gboolean find_entry_key_press (GtkEntry *entry, GdkEventKey *event, YelpWindow *window); static void find_entry_changed (GtkEntry *entry, YelpWindow *window); - -static gboolean entry_focus_in (GtkEntry *entry, - GdkEventFocus *event, +static void find_prev_clicked (GtkButton *button, YelpWindow *window); -static gboolean entry_focus_out (YelpLocationEntry *entry, - GdkEventFocus *event, +static void find_next_clicked (GtkButton *button, YelpWindow *window); static void view_new_window (YelpView *view, @@ -123,17 +129,14 @@ static void view_uri_selected (YelpView *view, static void view_root_title (YelpView *view, GParamSpec *pspec, YelpWindow *window); -static gboolean view_is_xref_uri (YelpView *view, - GtkAction *action, - const gchar *uri, - YelpWindow *window); - +#if 0 static void hidden_entry_activate (GtkEntry *entry, YelpWindow *window); static void hidden_entry_hide (YelpWindow *window); static gboolean hidden_key_press (GtkWidget *widget, GdkEventKey *event, YelpWindow *window); +#endif enum { PROP_0, @@ -147,15 +150,14 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -G_DEFINE_TYPE (YelpWindow, yelp_window, GTK_TYPE_WINDOW); +G_DEFINE_TYPE (YelpWindow, yelp_window, GTK_TYPE_APPLICATION_WINDOW); #define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_WINDOW, YelpWindowPrivate)) +#if 0 static const gchar *YELP_UI = "<ui>" "<menubar>" "<menu action='PageMenu'>" - "<menuitem action='NewWindow'/>" - "<menuitem action='Find'/>" "<separator/>" "<menuitem action='YelpViewPrint'/>" "<separator/>" @@ -167,108 +169,45 @@ static const gchar *YELP_UI = "<separator/>" "<menuitem action='ShowTextCursor'/>" "</menu>" - "<menu action='GoMenu'>" - "<menuitem action='YelpViewGoBack'/>" - "<menuitem action='YelpViewGoForward'/>" - "<separator/>" - "<menuitem action='YelpViewGoPrevious'/>" - "<menuitem action='YelpViewGoNext'/>" - "<separator/>" "<menuitem action='GoAll'/>" "</menu>" - "<menu action='BookmarksMenu'>" - "<menuitem action='AddBookmark'/>" - "<menuitem action='RemoveBookmark'/>" - "<separator/>" - "<placeholder name='Bookmarks'/>" - "</menu>" - "</menubar>" - "<accelerator action='Find'/>" - "<accelerator action='Search'/>" "<accelerator action='OpenLocation'/>" "</ui>"; +#endif typedef struct _YelpWindowPrivate YelpWindowPrivate; struct _YelpWindowPrivate { - GtkListStore *history; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; YelpApplication *application; gulong bookmarks_changed; - gulong read_later_changed; /* no refs on these, owned by containers */ - YelpView *view; + GtkWidget *header; GtkWidget *vbox_view; GtkWidget *vbox_full; - GtkWidget *hbox; - YelpLocationEntry *entry; - GtkWidget *hidden_entry; + GtkWidget *search_bar; + GtkWidget *search_entry; + GtkWidget *find_bar; GtkWidget *find_entry; - GtkWidget *find_label; - GtkWidget *read_later_vbox; + GtkWidget *bookmark_menu; + GtkWidget *bookmark_sw; + GtkWidget *bookmark_list; + GtkWidget *bookmark_add; + GtkWidget *bookmark_remove; + YelpView *view; - /* refs because we dynamically add & remove */ - GtkWidget *find_bar; - GtkWidget *align_location; - GtkWidget *align_hidden; - GtkWidget *read_later; + GtkWidget *hidden_entry; gchar *doc_uri; - GtkActionGroup *bookmark_actions; - guint bookmarks_merge_id; - guint resize_signal; gint width; gint height; - guint entry_color_animate; - gfloat entry_color_step; - gboolean configured; }; -static const GtkActionEntry entries[] = { - { "PageMenu", NULL, N_("_Page") }, - { "ViewMenu", NULL, N_("_View") }, - { "GoMenu", NULL, N_("_Go") }, - { "BookmarksMenu", NULL, N_("_Bookmarks") }, - - { "NewWindow", NULL, - N_("_New Window"), - "<Control>N", - NULL, - G_CALLBACK (window_new) }, - { "CloseWindow", NULL, - N_("_Close"), - "<Control>W", - NULL, - G_CALLBACK (window_close) }, - { "GoAll", NULL, - N_("_All Documents"), - NULL, NULL, - G_CALLBACK (window_go_all) }, - { "AddBookmark", NULL, - N_("_Add Bookmark"), - "<Control>D", - NULL, - G_CALLBACK (window_add_bookmark) }, - { "RemoveBookmark", NULL, - N_("_Remove Bookmark"), - NULL, NULL, - G_CALLBACK (window_remove_bookmark) }, - { "Find", NULL, - N_("Find in Page..."), - "<Control>F", - NULL, - G_CALLBACK (window_find_in_page) }, - { "Search", NULL, - N_("Search..."), - "<Control>S", - NULL, - G_CALLBACK (window_start_search) }, +static const GtkActionEntry gtkentries[] = { { "OpenLocation", NULL, N_("Open Location"), "<Control>L", @@ -319,51 +258,11 @@ yelp_window_dispose (GObject *object) { YelpWindowPrivate *priv = GET_PRIV (object); - if (priv->history) { - g_object_unref (priv->history); - priv->history = NULL; - } - - if (priv->action_group) { - g_object_unref (priv->action_group); - priv->action_group = NULL; - } - - if (priv->bookmark_actions) { - g_object_unref (priv->bookmark_actions); - priv->bookmark_actions = NULL; - } - - if (priv->read_later_changed) { - g_signal_handler_disconnect (priv->application, priv->read_later_changed); - priv->read_later_changed = 0; - } - if (priv->bookmarks_changed) { g_signal_handler_disconnect (priv->application, priv->bookmarks_changed); priv->bookmarks_changed = 0; } - if (priv->align_location) { - g_object_unref (priv->align_location); - priv->align_location = NULL; - } - - if (priv->align_hidden) { - g_object_unref (priv->align_hidden); - priv->align_hidden = NULL; - } - - if (priv->find_bar) { - g_object_unref (priv->find_bar); - priv->find_bar = NULL; - } - - if (priv->entry_color_animate != 0) { - g_source_remove (priv->entry_color_animate); - priv->entry_color_animate = 0; - } - G_OBJECT_CLASS (yelp_window_parent_class)->dispose (object); } @@ -414,153 +313,213 @@ static void window_construct (YelpWindow *window) { GtkWidget *scroll; - GtkActionGroup *view_actions; - GtkAction *action; - GtkWidget *vbox, *button, *label; - gchar *color, *text; + GtkWidget *box, *button; + GMenu *menu, *section; YelpWindowPrivate *priv = GET_PRIV (window); + gboolean rtl; - gtk_window_set_icon_name (GTK_WINDOW (window), "help-browser"); + const GActionEntry entries[] = { + { "yelp-window-new", action_new_window, NULL, NULL, NULL }, + { "yelp-window-close", action_close_window, NULL, NULL, NULL }, + { "yelp-window-search", action_search, NULL, NULL, NULL }, + { "yelp-window-find", action_find, NULL, NULL, NULL }, + { "yelp-window-go-all", action_go_all, NULL, NULL, NULL }, + }; + rtl = gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL; + + gtk_window_set_icon_name (GTK_WINDOW (window), "help-browser"); priv->view = (YelpView *) yelp_view_new (); - action = gtk_action_new ("ReadLinkLater", _("Read Link _Later"), NULL, NULL); - g_signal_connect (action, "activate", G_CALLBACK (window_read_later), window); - yelp_view_add_link_action (priv->view, action, - (YelpViewActionValidFunc) view_is_xref_uri, - window); - priv->read_later_changed = - g_signal_connect (priv->application, "read-later-changed", - G_CALLBACK (app_read_later_changed), window); + g_action_map_add_action_entries (G_ACTION_MAP (window), + entries, G_N_ELEMENTS (entries), window); + yelp_view_register_actions (priv->view, G_ACTION_MAP (window)); priv->vbox_full = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); gtk_container_add (GTK_CONTAINER (window), priv->vbox_full); + priv->header = gtk_header_bar_new (); + gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (priv->header), TRUE); + gtk_window_set_titlebar (GTK_WINDOW (window), priv->header); + + /** Back/Forward **/ + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_style_context_add_class (gtk_widget_get_style_context (box), "linked"); + gtk_header_bar_pack_start (GTK_HEADER_BAR (priv->header), box); + + button = gtk_button_new_from_icon_name (rtl ? "go-previous-rtl-symbolic" : "go-previous-symbolic", GTK_ICON_SIZE_MENU); + gtk_widget_set_tooltip_text (button, _("Back")); + gtk_widget_set_valign (button, GTK_ALIGN_CENTER); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "image-button"); + gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); + g_object_set (button, "action-name", "win.yelp-view-go-back", NULL); + + button = gtk_button_new_from_icon_name (rtl ? "go-next-rtl-symbolic" : "go-next-symbolic", GTK_ICON_SIZE_MENU); + gtk_widget_set_tooltip_text (button, _("Forward")); + gtk_widget_set_valign (button, GTK_ALIGN_CENTER); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "image-button"); + gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); + g_object_set (button, "action-name", "win.yelp-view-go-forward", NULL); + + /** Gear Menu **/ + button = gtk_menu_button_new (); + gtk_menu_button_set_use_popover (GTK_MENU_BUTTON (button), TRUE); + gtk_widget_set_valign (button, GTK_ALIGN_CENTER); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "image-button"); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_icon_name ("view-list-symbolic", + GTK_ICON_SIZE_MENU)); + gtk_widget_set_tooltip_text (button, _("Menu")); + gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->header), button); + + menu = g_menu_new (); + section = g_menu_new (); + g_menu_append (section, _("Find..."), "win.yelp-window-find"); + g_menu_append (section, _("Print..."), "win.yelp-view-print"); + g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); + g_object_unref (section); + + section = g_menu_new (); + g_menu_append (section, _("New Window"), "win.yelp-window-new"); + g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); + g_object_unref (section); + + section = g_menu_new (); + g_menu_append (section, _("Larger Text"), "app.yelp-application-larger-text"); + g_menu_append (section, _("Smaller Text"), "app.yelp-application-smaller-text"); + g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); + g_object_unref (section); + + section = g_menu_new (); + g_menu_append (section, _("Previous Page"), "win.yelp-view-go-previous"); + g_menu_append (section, _("Next Page"), "win.yelp-view-go-next"); + g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); + g_object_unref (section); + + section = g_menu_new (); + g_menu_append (section, _("All Help"), "win.yelp-window-go-all"); + g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); + g_object_unref (section); + + /* FIXME */ + /* open location */ + gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (button), G_MENU_MODEL (menu)); + + /** Search **/ priv->vbox_view = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_box_pack_start (GTK_BOX (priv->vbox_full), priv->vbox_view, TRUE, TRUE, 0); - priv->action_group = gtk_action_group_new ("YelpWindowActions"); - gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (priv->action_group, - entries, G_N_ELEMENTS (entries), - window); - - priv->bookmark_actions = gtk_action_group_new ("BookmarkActions"); - gtk_action_group_set_translate_func (priv->bookmark_actions, NULL, NULL, NULL); - - priv->ui_manager = gtk_ui_manager_new (); - gtk_ui_manager_insert_action_group (priv->ui_manager, priv->action_group, 0); - gtk_ui_manager_insert_action_group (priv->ui_manager, priv->bookmark_actions, 1); - gtk_ui_manager_insert_action_group (priv->ui_manager, - yelp_application_get_action_group (priv->application), - 2); - view_actions = yelp_view_get_action_group (priv->view); - gtk_ui_manager_insert_action_group (priv->ui_manager, view_actions, 3); - gtk_window_add_accel_group (GTK_WINDOW (window), - gtk_ui_manager_get_accel_group (priv->ui_manager)); - gtk_ui_manager_add_ui_from_string (priv->ui_manager, YELP_UI, -1, NULL); - gtk_box_pack_start (GTK_BOX (priv->vbox_view), - gtk_ui_manager_get_widget (priv->ui_manager, "/ui/menubar"), - FALSE, FALSE, 0); - - priv->bookmarks_merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager); + priv->search_bar = gtk_search_bar_new (); + gtk_box_pack_start (GTK_BOX (priv->vbox_view), priv->search_bar, FALSE, FALSE, 0); + priv->search_entry = yelp_search_entry_new (priv->view, + YELP_BOOKMARKS (priv->application)); + g_object_set (priv->search_entry, "width-request", 400, NULL); + gtk_container_add (GTK_CONTAINER (priv->search_bar), priv->search_entry); + button = gtk_toggle_button_new (); + gtk_widget_set_valign (button, GTK_ALIGN_CENTER); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "image-button"); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_icon_name ("edit-find-symbolic", + GTK_ICON_SIZE_MENU)); + gtk_widget_set_tooltip_text (button, _("Search (Ctrl+S)")); + g_object_bind_property (button, "active", + priv->search_bar, "search-mode-enabled", + G_BINDING_BIDIRECTIONAL); + gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->header), button); + + g_signal_connect_swapped (window, "key-press-event", + G_CALLBACK (gtk_search_bar_handle_event), priv->search_bar); + + /** Bookmarks **/ + button = gtk_menu_button_new (); + gtk_widget_set_valign (button, GTK_ALIGN_CENTER); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "image-button"); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_icon_name ("yelp-bookmark-remove-symbolic", + GTK_ICON_SIZE_MENU)); + gtk_widget_set_tooltip_text (button, _("Bookmarks")); + gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->header), button); + + priv->bookmark_menu = gtk_popover_new (button); + g_object_set (priv->bookmark_menu, "border-width", 12, NULL); + gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), priv->bookmark_menu); + + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_add (GTK_CONTAINER (priv->bookmark_menu), box); + priv->bookmark_sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->bookmark_sw), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + g_object_set (priv->bookmark_sw, "height-request", 200, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->bookmark_sw), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (box), priv->bookmark_sw, TRUE, TRUE, 0); + priv->bookmark_list = gtk_list_box_new (); + g_object_set (priv->bookmark_list, "selection-mode", GTK_SELECTION_NONE, NULL); + g_signal_connect (priv->bookmark_list, "row-activated", + G_CALLBACK (bookmark_activated), window); + gtk_container_add (GTK_CONTAINER (priv->bookmark_sw), priv->bookmark_list); + + priv->bookmark_add = gtk_button_new_with_label (_("Add Bookmark")); + g_signal_connect (priv->bookmark_add, "clicked", + G_CALLBACK (bookmark_added), window); + gtk_box_pack_end (GTK_BOX (box), priv->bookmark_add, FALSE, FALSE, 0); + gtk_widget_show_all (box); + + priv->bookmark_remove = gtk_button_new_with_label (_("Remove Bookmark")); + g_signal_connect (priv->bookmark_remove, "clicked", + G_CALLBACK (bookmark_removed), window); + gtk_box_pack_end (GTK_BOX (box), priv->bookmark_remove, FALSE, FALSE, 0); + gtk_widget_show_all (box); + priv->bookmarks_changed = g_signal_connect (priv->application, "bookmarks-changed", G_CALLBACK (app_bookmarks_changed), window); - priv->hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - g_object_set (priv->hbox, "border-width", 2, NULL); - gtk_box_pack_start (GTK_BOX (priv->vbox_view), priv->hbox, FALSE, FALSE, 0); - - action = gtk_action_group_get_action (view_actions, "YelpViewGoBack"); - button = gtk_action_create_tool_item (action); - gtk_box_pack_start (GTK_BOX (priv->hbox), - button, - FALSE, FALSE, 0); - action = gtk_action_group_get_action (view_actions, "YelpViewGoForward"); - button = gtk_action_create_tool_item (action); - gtk_box_pack_start (GTK_BOX (priv->hbox), - button, - FALSE, FALSE, 0); - - priv->entry = (YelpLocationEntry *) yelp_location_entry_new (priv->view, - YELP_BOOKMARKS (priv->application)); - g_signal_connect (gtk_bin_get_child (GTK_BIN (priv->entry)), "focus-in-event", - G_CALLBACK (entry_focus_in), window); - g_signal_connect (priv->entry, "focus-out-event", - G_CALLBACK (entry_focus_out), window); - - priv->align_location = g_object_ref_sink (gtk_alignment_new (0.0, 0.5, 1.0, 0.0)); - gtk_box_pack_start (GTK_BOX (priv->hbox), - GTK_WIDGET (priv->align_location), - TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (priv->align_location), GTK_WIDGET (priv->entry)); - - priv->hidden_entry = gtk_entry_new (); - priv->align_hidden = g_object_ref_sink (gtk_alignment_new (0.0, 0.5, 1.0, 0.0)); - gtk_container_add (GTK_CONTAINER (priv->align_hidden), GTK_WIDGET (priv->hidden_entry)); - - g_signal_connect (priv->hidden_entry, "activate", - G_CALLBACK (hidden_entry_activate), window); - g_signal_connect_swapped (priv->hidden_entry, "focus-out-event", - G_CALLBACK (hidden_entry_hide), window); - g_signal_connect (priv->hidden_entry, "key-press-event", - G_CALLBACK (hidden_key_press), window); - - scroll = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), - GTK_SHADOW_IN); - gtk_box_pack_start (GTK_BOX (priv->vbox_view), scroll, TRUE, TRUE, 0); - - priv->find_bar = g_object_ref_sink (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6)); - g_object_set (priv->find_bar, - "border-width", 2, - "margin-right", 16, - NULL); - - label = gtk_label_new (_("Find:")); - gtk_box_pack_start (GTK_BOX (priv->find_bar), label, FALSE, FALSE, 6); - - priv->find_entry = gtk_entry_new (); + /** Find **/ + priv->find_bar = gtk_search_bar_new (); + gtk_search_bar_set_show_close_button (GTK_SEARCH_BAR (priv->find_bar), TRUE); + gtk_box_pack_start (GTK_BOX (priv->vbox_view), priv->find_bar, FALSE, FALSE, 0); + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + g_object_set (box, "width-request", 300, NULL); + gtk_style_context_add_class (gtk_widget_get_style_context (box), "linked"); + gtk_container_add (GTK_CONTAINER (priv->find_bar), box); + + priv->find_entry = gtk_search_entry_new (); + gtk_box_pack_start (GTK_BOX (box), priv->find_entry, TRUE, TRUE, 0); + gtk_search_bar_connect_entry (GTK_SEARCH_BAR (priv->find_bar), GTK_ENTRY (priv->find_entry)); g_signal_connect (priv->find_entry, "changed", G_CALLBACK (find_entry_changed), window); g_signal_connect (priv->find_entry, "key-press-event", G_CALLBACK (find_entry_key_press), window); - g_signal_connect (priv->find_entry, "focus-out-event", - G_CALLBACK (find_entry_focus_out), window); - g_object_set (priv->find_entry, "width-request", 300, NULL); - gtk_box_pack_start (GTK_BOX (priv->find_bar), priv->find_entry, FALSE, FALSE, 0); - priv->find_label = gtk_label_new (""); - g_object_set (priv->find_label, "xalign", 0.0, NULL); - gtk_box_pack_start (GTK_BOX (priv->find_bar), priv->find_label, FALSE, FALSE, 0); + button = gtk_button_new_from_icon_name ("go-up-symbolic", GTK_ICON_SIZE_MENU); + gtk_widget_set_valign (button, GTK_ALIGN_CENTER); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "raised"); + gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", G_CALLBACK (find_prev_clicked), window); - priv->read_later = g_object_ref_sink (gtk_info_bar_new ()); - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - color = yelp_settings_get_color (yelp_settings_get_default (), - YELP_SETTINGS_COLOR_TEXT_LIGHT); - text = g_markup_printf_escaped ("<span weight='bold' color='%s'>%s</span>", - color, _("Read Later")); - button = gtk_label_new (text); - g_object_set (button, "use-markup", TRUE, "xalign", 0.0, NULL); - g_free (color); - g_free (text); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (priv->read_later))), - vbox, - FALSE, FALSE, 0); - priv->read_later_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_box_pack_start (GTK_BOX (vbox), priv->read_later_vbox, FALSE, FALSE, 0); + button = gtk_button_new_from_icon_name ("go-down-symbolic", GTK_ICON_SIZE_MENU); + gtk_widget_set_valign (button, GTK_ALIGN_CENTER); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "raised"); + gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", G_CALLBACK (find_next_clicked), window); + + gtk_widget_show_all (priv->find_bar); + + /** View **/ + scroll = gtk_scrolled_window_new (NULL, NULL); + g_object_set (scroll, "width-request", 420, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_box_pack_start (GTK_BOX (priv->vbox_view), scroll, TRUE, TRUE, 0); g_signal_connect (priv->view, "new-view-requested", G_CALLBACK (view_new_window), window); g_signal_connect (priv->view, "loaded", G_CALLBACK (view_loaded), window); g_signal_connect (priv->view, "notify::yelp-uri", G_CALLBACK (view_uri_selected), window); g_signal_connect_swapped (priv->view, "notify::page-id", - G_CALLBACK (window_set_bookmark_action), window); - window_set_bookmark_action (window); + G_CALLBACK (window_set_bookmark_buttons), window); + window_set_bookmark_buttons (window); g_signal_connect (priv->view, "notify::root-title", G_CALLBACK (view_root_title), window); gtk_container_add (GTK_CONTAINER (scroll), GTK_WIDGET (priv->view)); gtk_widget_grab_focus (GTK_WIDGET (priv->view)); @@ -617,10 +576,13 @@ yelp_window_get_geometry (YelpWindow *window, /******************************************************************************/ static void -window_new (GtkAction *action, YelpWindow *window) +action_new_window (GSimpleAction *action, + GVariant *parameter, + gpointer userdata) { YelpUri *yuri; gchar *uri = NULL; + YelpWindow *window = YELP_WINDOW (userdata); YelpWindowPrivate *priv = GET_PRIV (window); g_object_get (priv->view, "yelp-uri", &yuri, NULL); @@ -633,6 +595,51 @@ window_new (GtkAction *action, YelpWindow *window) } static void +action_close_window (GSimpleAction *action, + GVariant *parameter, + gpointer userdata) +{ + g_signal_emit_by_name (userdata, "delete-event", NULL, NULL); + gtk_widget_destroy (GTK_WIDGET (userdata)); +} + +static void +action_search (GSimpleAction *action, + GVariant *parameter, + gpointer userdata) +{ + YelpWindowPrivate *priv = GET_PRIV (userdata); + + gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->find_bar), FALSE); + gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->search_bar), TRUE); + gtk_widget_grab_focus (priv->search_entry); +} + +static void +action_find (GSimpleAction *action, + GVariant *parameter, + gpointer userdata) +{ + YelpWindowPrivate *priv = GET_PRIV (userdata); + + gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->search_bar), FALSE); + gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->find_bar), TRUE); + gtk_widget_grab_focus (priv->find_entry); +} + +static void +action_go_all (GSimpleAction *action, + GVariant *parameter, + gpointer userdata) +{ + YelpWindowPrivate *priv = GET_PRIV (userdata); + yelp_view_load (priv->view, "help-list:"); +} + + +/******************************************************************************/ + +static void window_drag_received (YelpWindow *window, GdkDragContext *context, gint x, @@ -704,24 +711,62 @@ window_resize_signal (YelpWindow *window) } static void -window_close (GtkAction *action, YelpWindow *window) +bookmark_activated (GtkListBox *box, + GtkListBoxRow *row, + YelpWindow *window) { - gboolean ret; - g_signal_emit_by_name (window, "delete-event", NULL, &ret); - gtk_widget_destroy (GTK_WIDGET (window)); + YelpUri *base, *uri; + gchar *xref; + YelpWindowPrivate *priv = GET_PRIV (window); + + gtk_widget_hide (priv->bookmark_menu); + + xref = g_strconcat ("xref:", + (gchar *) g_object_get_data (G_OBJECT (row), "page-id"), + NULL); + g_object_get (priv->view, "yelp-uri", &base, NULL); + uri = yelp_uri_new_relative (base, xref); + + yelp_view_load_uri (priv->view, uri); + + g_object_unref (base); + g_object_unref (uri); + g_free (xref); } static void -window_go_all (GtkAction *action, - YelpWindow *window) +bookmark_removed (GtkButton *button, + YelpWindow *window) { + YelpUri *uri; + gchar *doc_uri; + gchar *page_id = NULL; YelpWindowPrivate *priv = GET_PRIV (window); - yelp_view_load (priv->view, "help-list:"); + + g_object_get (priv->view, "yelp-uri", &uri, NULL); + doc_uri = yelp_uri_get_document_uri (uri); + + /* The 'Remove Bookmark' button removes a bookmark for the current page. + The buttons next to each bookmark have page_id attached to them. + */ + if ((gpointer) button == (gpointer) priv->bookmark_remove) + g_object_get (priv->view, + "page-id", &page_id, + NULL); + + yelp_application_remove_bookmark (YELP_BOOKMARKS (priv->application), + doc_uri, + page_id ? page_id : + g_object_get_data (G_OBJECT (button), "page-id")); + if (page_id) + g_free (page_id); + g_free (doc_uri); + g_object_unref (uri); } static void -window_add_bookmark (GtkAction *action, - YelpWindow *window) +bookmark_added (GtkButton *button, + YelpWindow *window) { YelpUri *uri; gchar *doc_uri, *page_id, *icon, *title; @@ -744,45 +789,6 @@ window_add_bookmark (GtkAction *action, } static void -window_remove_bookmark (GtkAction *action, - YelpWindow *window) -{ - YelpUri *uri; - gchar *doc_uri, *page_id; - YelpWindowPrivate *priv = GET_PRIV (window); - - g_object_get (priv->view, - "yelp-uri", &uri, - "page-id", &page_id, - NULL); - doc_uri = yelp_uri_get_document_uri (uri); - yelp_application_remove_bookmark (YELP_BOOKMARKS (priv->application), - doc_uri, page_id); - g_free (doc_uri); - g_free (page_id); - g_object_unref (uri); -} -static void -window_load_bookmark (GtkAction *action, - YelpWindow *window) -{ - YelpUri *base, *uri; - gchar *xref; - YelpWindowPrivate *priv = GET_PRIV (window); - - /* Bookmark action names are prefixed with 'LoadBookmark-' */ - xref = g_strconcat ("xref:", gtk_action_get_name (action) + 13, NULL); - g_object_get (priv->view, "yelp-uri", &base, NULL); - uri = yelp_uri_new_relative (base, xref); - - yelp_view_load_uri (priv->view, uri); - - g_object_unref (base); - g_object_unref (uri); - g_free (xref); -} - -static void app_bookmarks_changed (YelpApplication *app, const gchar *doc_uri, YelpWindow *window) @@ -834,91 +840,87 @@ window_set_bookmarks (YelpWindow *window, GVariantIter *iter; gchar *page_id, *icon, *title; YelpWindowPrivate *priv = GET_PRIV (window); + gboolean has_bookmarks = FALSE; + GList *children, *cur; GSList *entries = NULL; - window_set_bookmark_action (window); + window_set_bookmark_buttons (window); - gtk_ui_manager_remove_ui (priv->ui_manager, priv->bookmarks_merge_id); + children = gtk_container_get_children (GTK_CONTAINER (priv->bookmark_list)); + for (cur = children ; cur != NULL; cur = cur->next) { + gtk_container_remove (GTK_CONTAINER (priv->bookmark_list), + GTK_WIDGET (cur->data)); + } + g_list_free (children); value = yelp_application_get_bookmarks (priv->application, doc_uri); g_variant_get (value, "a(sss)", &iter); while (g_variant_iter_loop (iter, "(&s&s&s)", &page_id, &icon, &title)) { YelpMenuEntry *entry = g_new0 (YelpMenuEntry, 1); + has_bookmarks = TRUE; entry->page_id = page_id; entry->icon = g_strdup (icon); entry->title = title; entries = g_slist_insert_sorted (entries, entry, (GCompareFunc) entry_compare); } for ( ; entries != NULL; entries = g_slist_delete_link (entries, entries)) { - GSList *cur; - GtkAction *bookmark; + GtkWidget *row, *box, *button; YelpMenuEntry *entry = (YelpMenuEntry *) entries->data; - gchar *action_id = g_strconcat ("LoadBookmark-", entry->page_id, NULL); - - bookmark = gtk_action_group_get_action (priv->bookmark_actions, action_id); - if (bookmark) { - /* The action might have been set by a different document using - * the same page ID. We can just reuse the action, since it's - * just a page ID relative to the current URI, but we need to - * reset the title and icon. - */ - g_object_set (bookmark, - "label", entry->title, - "icon-name", entry->icon, - NULL); - } else { - bookmark = gtk_action_new (action_id, entry->title, NULL, NULL); - g_signal_connect (bookmark, "activate", - G_CALLBACK (window_load_bookmark), window); - gtk_action_set_icon_name (bookmark, entry->icon); - gtk_action_group_add_action (priv->bookmark_actions, bookmark); - } - gtk_ui_manager_add_ui (priv->ui_manager, - priv->bookmarks_merge_id, - "ui/menubar/BookmarksMenu/Bookmarks", - action_id, action_id, - GTK_UI_MANAGER_MENUITEM, - FALSE); - gtk_ui_manager_ensure_update (priv->ui_manager); - for (cur = gtk_action_get_proxies (bookmark); cur != NULL; cur = cur->next) { - if (GTK_IS_IMAGE_MENU_ITEM (cur->data)) - g_object_set (cur->data, "always-show-image", TRUE, NULL); - } - g_free (action_id); + + row = gtk_list_box_row_new (); + g_object_set_data_full (G_OBJECT (row), "page-id", + g_strdup (entry->page_id), (GDestroyNotify) g_free); + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); + gtk_container_add (GTK_CONTAINER (row), box); + button = gtk_label_new (entry->title); + g_object_set (button, "halign", GTK_ALIGN_START, NULL); + gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0); + button = gtk_button_new_from_icon_name ("edit-delete-symbolic", GTK_ICON_SIZE_MENU); + g_object_set (button, + "relief", GTK_RELIEF_NONE, + "focus-on-click", FALSE, + NULL); + g_object_set_data_full (G_OBJECT (button), "page-id", + g_strdup (entry->page_id), (GDestroyNotify) g_free); + g_signal_connect (button, "clicked", G_CALLBACK (bookmark_removed), window); + gtk_box_pack_end (GTK_BOX (box), button, FALSE, FALSE, 0); + gtk_box_pack_end (GTK_BOX (box), gtk_separator_new (GTK_ORIENTATION_VERTICAL), FALSE, FALSE, 0); + gtk_widget_show_all (row); + gtk_container_add (GTK_CONTAINER (priv->bookmark_list), row); g_free (entry->icon); g_free (entry); } + gtk_widget_set_visible (priv->bookmark_sw, has_bookmarks); + g_variant_iter_free (iter); g_variant_unref (value); } static void -window_set_bookmark_action (YelpWindow *window) +window_set_bookmark_buttons (YelpWindow *window) { YelpUri *uri = NULL; gchar *doc_uri = NULL, *page_id = NULL; - GtkAction *action_add, *action_del; gboolean bookmarked; YelpWindowPrivate *priv = GET_PRIV (window); - action_add = gtk_action_group_get_action (priv->action_group, "AddBookmark"); - action_del = gtk_action_group_get_action (priv->action_group, "RemoveBookmark"); g_object_get (priv->view, "yelp-uri", &uri, "page-id", &page_id, NULL); if (page_id == NULL || uri == NULL) { - gtk_action_set_sensitive (action_add, FALSE); - gtk_action_set_sensitive (action_del, FALSE); + gtk_widget_hide (priv->bookmark_add); + gtk_widget_hide (priv->bookmark_remove); goto done; } doc_uri = yelp_uri_get_document_uri (uri); bookmarked = yelp_application_is_bookmarked (YELP_BOOKMARKS (priv->application), doc_uri, page_id); - gtk_action_set_sensitive (action_add, !bookmarked); - gtk_action_set_sensitive (action_del, bookmarked); + + gtk_widget_set_visible (priv->bookmark_add, !bookmarked); + gtk_widget_set_visible (priv->bookmark_remove, bookmarked); done: g_free (page_id); @@ -928,29 +930,15 @@ window_set_bookmark_action (YelpWindow *window) } static void -window_start_search (GtkAction *action, YelpWindow *window) -{ - YelpWindowPrivate *priv = GET_PRIV (window); - - yelp_location_entry_start_search (priv->entry); -} - -static void window_open_location (GtkAction *action, YelpWindow *window) { +#if 0 YelpUri *yuri = NULL; gchar *uri = NULL; GdkColor yellow; gchar *color; YelpWindowPrivate *priv = GET_PRIV (window); - gtk_container_remove (GTK_CONTAINER (priv->hbox), - priv->align_location); - gtk_box_pack_start (GTK_BOX (priv->hbox), - priv->align_hidden, - TRUE, TRUE, 0); - - gtk_widget_show_all (priv->align_hidden); gtk_entry_set_text (GTK_ENTRY (priv->hidden_entry), ""); gtk_widget_grab_focus (priv->hidden_entry); @@ -978,145 +966,7 @@ window_open_location (GtkAction *action, YelpWindow *window) gtk_editable_select_region (GTK_EDITABLE (priv->hidden_entry), 5, -1); g_free (uri); } -} - -static void -read_later_resolved (YelpUri *uri, - YelpWindow *window) -{ - gchar *fulluri; - const gchar *text = (const gchar *) g_object_get_data ((GObject *) uri, "link-text"); - YelpWindowPrivate *priv = GET_PRIV (window); - YelpUri *base; - gchar *doc_uri; - - g_object_get (priv->view, "yelp-uri", &base, NULL); - doc_uri = yelp_uri_get_document_uri (uri); - fulluri = yelp_uri_get_canonical_uri (uri); - - yelp_application_add_read_later (priv->application, doc_uri, fulluri, text); - - g_object_unref (base); - g_free (doc_uri); - g_free (fulluri); -} - -static void -window_read_later (GtkAction *action, - YelpWindow *window) -{ - YelpWindowPrivate *priv = GET_PRIV (window); - YelpUri *uri; - gchar *text; - - uri = yelp_view_get_active_link_uri (priv->view); - text = yelp_view_get_active_link_text (priv->view); - - g_object_set_data_full ((GObject *) uri, "link-text", text, g_free); - - if (!yelp_uri_is_resolved (uri)) { - g_signal_connect (uri, "resolved", - G_CALLBACK (read_later_resolved), - window); - yelp_uri_resolve (uri); - } - else { - read_later_resolved (uri, window); - } -} - -static gboolean -read_later_clicked (GtkLinkButton *button, - YelpWindow *window) -{ - YelpWindowPrivate *priv = GET_PRIV (window); - YelpUri *base; - gchar *doc_uri; - gchar *fulluri; - - fulluri = g_strdup (gtk_link_button_get_uri (button)); - - g_object_get (priv->view, "yelp-uri", &base, NULL); - doc_uri = yelp_uri_get_document_uri (base); - - yelp_application_remove_read_later (priv->application, doc_uri, fulluri); - - g_object_unref (base); - g_free (doc_uri); - - yelp_view_load (priv->view, fulluri); - - g_free (fulluri); - return TRUE; -} - -static void -app_read_later_changed (YelpApplication *app, - const gchar *doc_uri, - YelpWindow *window) -{ - GVariant *value; - GVariantIter *viter; - gchar *uri, *title; /* do not free */ - GList *children; - gboolean has_children = FALSE; - YelpWindowPrivate *priv = GET_PRIV (window); - - children = gtk_container_get_children (GTK_CONTAINER (priv->read_later_vbox)); - while (children) { - gtk_container_remove (GTK_CONTAINER (priv->read_later_vbox), - GTK_WIDGET (children->data)); - children = g_list_delete_link (children, children); - } - - value = yelp_application_get_read_later (priv->application, doc_uri); - g_variant_get (value, "a(ss)", &viter); - while (g_variant_iter_loop (viter, "(&s&s)", &uri, &title)) { - GtkWidget *align, *link; - - align = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); - g_object_set (align, "left-padding", 6, NULL); - gtk_box_pack_start (GTK_BOX (priv->read_later_vbox), align, FALSE, FALSE, 0); - - link = gtk_link_button_new_with_label (uri, title); - g_object_set (link, "xalign", 0.0, NULL); - g_signal_connect (link, "activate-link", G_CALLBACK (read_later_clicked), window); - gtk_container_add (GTK_CONTAINER (align), link); - - gtk_widget_show_all (align); - has_children = TRUE; - } - g_variant_iter_free (viter); - g_variant_unref (value); - - if (has_children) { - if (gtk_widget_get_parent (priv->read_later) == NULL) { - gtk_box_pack_end (GTK_BOX (priv->vbox_full), priv->read_later, FALSE, FALSE, 0); - gtk_widget_show_all (priv->read_later); - } - } - else { - if (gtk_widget_get_parent (priv->read_later) != NULL) - gtk_container_remove (GTK_CONTAINER (priv->vbox_full), priv->read_later); - } -} - -static void -window_find_in_page (GtkAction *action, - YelpWindow *window) -{ - YelpWindowPrivate *priv = GET_PRIV (window); - - if (gtk_widget_get_parent (priv->find_bar) != NULL) { - gtk_widget_grab_focus (priv->find_entry); - return; - } - - g_object_set (priv->find_entry, "width-request", 2 * priv->width / 3, NULL); - - gtk_box_pack_end (GTK_BOX (priv->vbox_view), priv->find_bar, FALSE, FALSE, 0); - gtk_widget_show_all (priv->find_bar); - gtk_widget_grab_focus (priv->find_entry); +#endif } static gboolean @@ -1142,19 +992,6 @@ find_entry_key_press (GtkEntry *entry, return FALSE; } -static gboolean -find_entry_focus_out (GtkEntry *entry, - GdkEventFocus *event, - YelpWindow *window) -{ - YelpWindowPrivate *priv = GET_PRIV (window); - webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (priv->view)); - webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (priv->view), FALSE); - if (gtk_widget_get_parent (priv->find_bar) != NULL) - gtk_container_remove (GTK_CONTAINER (priv->vbox_view), priv->find_bar); - return FALSE; -} - static void find_entry_changed (GtkEntry *entry, YelpWindow *window) @@ -1167,86 +1004,40 @@ find_entry_changed (GtkEntry *entry, text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); - if (text[0] == '\0') { - gtk_label_set_text (GTK_LABEL (priv->find_label), ""); - return; - } - count = webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (priv->view), text, FALSE, 0); if (count > 0) { - gchar *label = g_strdup_printf (ngettext ("%i match", "%i matches", count), count); webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (priv->view), TRUE); webkit_web_view_search_text (WEBKIT_WEB_VIEW (priv->view), text, FALSE, TRUE, TRUE); - gtk_label_set_text (GTK_LABEL (priv->find_label), label); - g_free (label); } else { webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (priv->view), FALSE); - gtk_label_set_text (GTK_LABEL (priv->find_label), _("No matches")); } g_free (text); } -static gboolean -entry_color_animate (YelpWindow *window) -{ - gchar *color; - GdkColor yellow, base; - YelpWindowPrivate *priv = GET_PRIV (window); - - color = yelp_settings_get_color (yelp_settings_get_default (), - YELP_SETTINGS_COLOR_YELLOW_BASE); - gdk_color_parse (color, &yellow); - g_free (color); - - color = yelp_settings_get_color (yelp_settings_get_default (), - YELP_SETTINGS_COLOR_BASE); - gdk_color_parse (color, &base); - g_free (color); - - yellow.red = priv->entry_color_step * yellow.red + (1.0 - priv->entry_color_step) * base.red; - yellow.green = priv->entry_color_step * yellow.green + (1.0 - priv->entry_color_step) * base.green; - yellow.blue = priv->entry_color_step * yellow.blue + (1.0 - priv->entry_color_step) * base.blue; - - gtk_widget_modify_base (gtk_bin_get_child (GTK_BIN (priv->entry)), GTK_STATE_NORMAL, &yellow); - - priv->entry_color_step -= 0.05; - - if (priv->entry_color_step < 0.0) { - priv->entry_color_animate = 0; - return FALSE; - } - - return TRUE; -} - -static gboolean -entry_focus_in (GtkEntry *entry, - GdkEventFocus *event, - YelpWindow *window) +static void +find_prev_clicked (GtkButton *button, + YelpWindow *window) { YelpWindowPrivate *priv = GET_PRIV (window); - - if (priv->entry_color_animate != 0) - return FALSE; - - priv->entry_color_step = 1.0; - priv->entry_color_animate = g_timeout_add (40, (GSourceFunc) entry_color_animate, window); - - return FALSE; + gchar *text = gtk_editable_get_chars (GTK_EDITABLE (priv->find_entry), 0, -1); + webkit_web_view_search_text (WEBKIT_WEB_VIEW (priv->view), + text, FALSE, FALSE, TRUE); + g_free (text); } -static gboolean -entry_focus_out (YelpLocationEntry *entry, - GdkEventFocus *event, - YelpWindow *window) +static void +find_next_clicked (GtkButton *button, + YelpWindow *window) { YelpWindowPrivate *priv = GET_PRIV (window); - gtk_widget_grab_focus (GTK_WIDGET (priv->view)); - return FALSE; + gchar *text = gtk_editable_get_chars (GTK_EDITABLE (priv->find_entry), 0, -1); + webkit_web_view_search_text (WEBKIT_WEB_VIEW (priv->view), + text, FALSE, TRUE, TRUE); + g_free (text); } static void @@ -1286,12 +1077,14 @@ view_loaded (YelpView *view, "page-icon", &icon, "page-title", &title, NULL); + if (!g_str_has_prefix (page_id, "search=")) { + gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->search_bar), FALSE); + } yelp_application_update_bookmarks (priv->application, doc_uri, page_id, icon, title); - app_read_later_changed (priv->application, doc_uri, window); g_free (page_id); g_free (icon); g_free (title); @@ -1334,31 +1127,31 @@ view_uri_selected (YelpView *view, g_object_unref (uri); } -static gboolean -view_is_xref_uri (YelpView *view, - GtkAction *action, - const gchar *uri, - YelpWindow *window) -{ - return g_str_has_prefix (uri, "xref:"); -} - static void view_root_title (YelpView *view, GParamSpec *pspec, YelpWindow *window) { - gchar *title; - g_object_get (view, "root-title", &title, NULL); + YelpWindowPrivate *priv = GET_PRIV (window); + gchar *root_title, *page_title; + g_object_get (view, "root-title", &root_title, "page-title", &page_title, NULL); - if (title) { - gtk_window_set_title (GTK_WINDOW (window), title); - g_free (title); + if (page_title) { + gtk_header_bar_set_title (GTK_HEADER_BAR (priv->header), page_title); + g_free (page_title); } else { - gtk_window_set_title (GTK_WINDOW (window), _("Help")); + gtk_header_bar_set_title (GTK_HEADER_BAR (priv->header), _("Help")); + } + + if (root_title) { + gtk_header_bar_set_subtitle (GTK_HEADER_BAR (priv->header), root_title); + g_free (root_title); + } else { + gtk_header_bar_set_subtitle (GTK_HEADER_BAR (priv->header), NULL); } } +#if 0 static void hidden_entry_activate (GtkEntry *entry, YelpWindow *window) @@ -1377,13 +1170,6 @@ hidden_entry_hide (YelpWindow *window) { YelpWindowPrivate *priv = GET_PRIV (window); - if (gtk_widget_get_parent (priv->align_hidden) != NULL) { - gtk_container_remove (GTK_CONTAINER (priv->hbox), - priv->align_hidden); - gtk_box_pack_start (GTK_BOX (priv->hbox), - priv->align_location, - TRUE, TRUE, 0); - } } static gboolean @@ -1398,3 +1184,4 @@ hidden_key_press (GtkWidget *widget, } return FALSE; } +#endif diff --git a/src/yelp-window.h b/src/yelp-window.h index 64db4c0f..a1303068 100644 --- a/src/yelp-window.h +++ b/src/yelp-window.h @@ -36,12 +36,12 @@ typedef struct _YelpWindowClass YelpWindowClass; struct _YelpWindow { - GtkWindow parent; + GtkApplicationWindow parent; }; struct _YelpWindowClass { - GtkWindowClass parent_class; + GtkApplicationWindowClass parent_class; }; GType yelp_window_get_type (void); |