Merge lp:~noskcaj/ubuntu/trusty/yelp/3.10.2 into lp:ubuntu/trusty/yelp

Proposed by Jackson Doak
Status: Merged
Merge reported by: Sebastien Bacher
Merged at revision: not available
Proposed branch: lp:~noskcaj/ubuntu/trusty/yelp/3.10.2
Merge into: lp:ubuntu/trusty/yelp
Diff against target: 7240 lines (+153/-6459)
21 files modified
.pc/07_disable_package_search.patch/libyelp/yelp-view.c (+4/-4)
.pc/applied-patches (+0/-1)
.pc/git_signal_handler.patch/libyelp/yelp-location-entry.c (+0/-1650)
.pc/git_signal_handler.patch/libyelp/yelp-view.c (+0/-2220)
.pc/git_signal_handler.patch/src/yelp-window.c (+0/-1402)
NEWS (+7/-0)
configure (+10/-10)
configure.ac (+1/-1)
debian/changelog (+7/-0)
debian/patches/git_signal_handler.patch (+0/-93)
debian/patches/series (+0/-1)
docs/libyelp/html/YelpLocationEntry.html (+2/-2)
docs/libyelp/html/YelpView.html (+2/-2)
docs/libyelp/html/ch01.html (+3/-3)
docs/libyelp/html/ch01s02.html (+1/-1)
docs/libyelp/html/index.html (+2/-2)
docs/libyelp/html/libyelp.devhelp (+1/-1)
docs/libyelp/html/libyelp.devhelp2 (+1/-1)
docs/libyelp/version.xml (+1/-1)
po/kn.po (+45/-999)
po/zh_CN.po (+66/-65)
To merge this branch: bzr merge lp:~noskcaj/ubuntu/trusty/yelp/3.10.2
Reviewer Review Type Date Requested Status
Sebastien Bacher Approve
Review via email: mp+210061@code.launchpad.net

Description of the change

New upstream bugfix release

To post a comment you must log in.
139. By Jackson Doak

target trusty

Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks, but please be careful with packaging Vcs (those are indicated in debian/control or by apt-get source), the location for this one is ~ubuntu-desktop/yelp/ubuntu (debian dir only). I'm merging your changes by hand for this time but it would be nice if you could target the right vcs next time

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.pc/07_disable_package_search.patch/libyelp/yelp-view.c'
2--- .pc/07_disable_package_search.patch/libyelp/yelp-view.c 2013-12-17 10:40:39 +0000
3+++ .pc/07_disable_package_search.patch/libyelp/yelp-view.c 2014-03-08 22:22:39 +0000
4@@ -308,12 +308,12 @@
5 view_clear_load (YELP_VIEW (object));
6
7 if (priv->vadjuster > 0) {
8- g_source_remove (priv->vadjuster);
9+ g_signal_handler_disconnect (priv->vadjustment, priv->vadjuster);
10 priv->vadjuster = 0;
11 }
12
13 if (priv->hadjuster > 0) {
14- g_source_remove (priv->hadjuster);
15+ g_signal_handler_disconnect (priv->hadjustment, priv->hadjuster);
16 priv->hadjuster = 0;
17 }
18
19@@ -885,7 +885,7 @@
20 YelpViewPrivate *priv = GET_PRIV (view);
21 priv->hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (view));
22 if (priv->hadjuster > 0)
23- g_source_remove (priv->hadjuster);
24+ g_signal_handler_disconnect (priv->hadjustment, priv->hadjuster);
25 priv->hadjuster = 0;
26 if (priv->hadjustment)
27 priv->hadjuster = g_signal_connect (priv->hadjustment, "value-changed",
28@@ -900,7 +900,7 @@
29 YelpViewPrivate *priv = GET_PRIV (view);
30 priv->vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (view));
31 if (priv->vadjuster > 0)
32- g_source_remove (priv->vadjuster);
33+ g_signal_handler_disconnect (priv->vadjustment, priv->vadjuster);
34 priv->vadjuster = 0;
35 if (priv->vadjustment)
36 priv->vadjuster = g_signal_connect (priv->vadjustment, "value-changed",
37
38=== modified file '.pc/applied-patches'
39--- .pc/applied-patches 2014-02-27 13:28:05 +0000
40+++ .pc/applied-patches 2014-03-08 22:22:39 +0000
41@@ -2,4 +2,3 @@
42 05_menu_tooltip.patch
43 06_make_ubuntu_docs_default.patch
44 07_disable_package_search.patch
45-git_signal_handler.patch
46
47=== removed directory '.pc/git_signal_handler.patch'
48=== removed directory '.pc/git_signal_handler.patch/libyelp'
49=== removed file '.pc/git_signal_handler.patch/libyelp/yelp-location-entry.c'
50--- .pc/git_signal_handler.patch/libyelp/yelp-location-entry.c 2014-02-27 13:28:05 +0000
51+++ .pc/git_signal_handler.patch/libyelp/yelp-location-entry.c 1970-01-01 00:00:00 +0000
52@@ -1,1650 +0,0 @@
53-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
54-/*
55- * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
56- *
57- * This program is free software; you can redistribute it and/or
58- * modify it under the terms of the GNU General Public License as
59- * published by the Free Software Foundation; either version 2 of the
60- * License, or (at your option) any later version.
61- *
62- * This program is distributed in the hope that it will be useful,
63- * but WITHOUT ANY WARRANTY; without even the implied warranty of
64- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
65- * General Public License for more details.
66- *
67- * You should have received a copy of the GNU General Public
68- * License along with this program; if not, write to the
69- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
70- * Boston, MA 02111-1307, USA.
71- *
72- * Author: Shaun McCance <shaunm@gnome.org>
73- */
74-
75-#ifdef HAVE_CONFIG_H
76-#include <config.h>
77-#endif
78-
79-#include <gdk/gdkkeysyms.h>
80-#include <gtk/gtk.h>
81-#include <glib/gi18n.h>
82-
83-#include "yelp-location-entry.h"
84-#include "yelp-marshal.h"
85-#include "yelp-settings.h"
86-
87-/**
88- * SECTION:yelp-location-entry
89- * @short_description: A location entry with history and search
90- * @include: yelp.h
91- *
92- * #YelpLocationEntry is a #GtkComboBox designed to show the current location,
93- * provide a drop-down menu of previous locations, and allow the user to perform
94- * searches.
95- *
96- * The #GtkTreeModel used by a #YelpLocationEntry is expected to have at least
97- * four columns: #GtkComboBox::entry-text-column contains the displayed name
98- * of the location, #YelpLocationEntry::desc-column contains a description
99- * for each entry, #YelpLocationEntry::icon-column contains an icon name for
100- * the location, and #YelpLocationEntry::flags-column contains a bit field
101- * of #YelpLocationEntryFlags. These columns are specified when creating a
102- * #YelpLocationEntry widget with yelp_location_entry_new_with_model().
103- *
104- * Usually, a single row in the #GtkTreeModel corresponds to a location. When
105- * a user selects a row from the drop-down menu, the icon and text for that
106- * row will be placed in the embedded text entry, and the
107- * #YelpLocationEntry:location-selected signal will be emitted.
108- *
109- * If a row has the %YELP_LOCATION_ENTRY_IS_SEARCH flag set, selecting that
110- * row will not emit the #YelpLocationEntry::location-selected signal. Instead,
111- * the #YelpLocationEntry widget will be placed into search mode, as if by a
112- * call to yelp_location_entry_start_search().
113- *
114- * When a row has the %YELP_LOCATION_ENTRY_CAN_BOOKMARK flag set, an icon
115- * will be displayed in the secondary icon position of the embedded text
116- * entry allowing the user to bookmark the location. Clicking this icon
117- * will cause the FIXME signal to be emitted.
118- **/
119-
120-static void location_entry_constructed (GObject *object);
121-static void location_entry_dispose (GObject *object);
122-static void location_entry_finalize (GObject *object);
123-static void location_entry_get_property (GObject *object,
124- guint prop_id,
125- GValue *value,
126- GParamSpec *pspec);
127-static void location_entry_set_property (GObject *object,
128- guint prop_id,
129- const GValue *value,
130- GParamSpec *pspec);
131-
132-/* Signals */
133-static void location_entry_location_selected (YelpLocationEntry *entry);
134-static void location_entry_search_activated (YelpLocationEntry *entry);
135-static void location_entry_bookmark_clicked (YelpLocationEntry *entry);
136-
137-/* Utilities */
138-static void location_entry_start_search (YelpLocationEntry *entry,
139- gboolean clear);
140-static void location_entry_cancel_search (YelpLocationEntry *entry);
141-static void location_entry_set_entry (YelpLocationEntry *entry,
142- gboolean emit);
143-static gboolean location_entry_start_pulse (gpointer data);
144-static gboolean location_entry_pulse (gpointer data);
145-static void location_entry_set_completion (YelpLocationEntry *entry,
146- GtkTreeModel *model);
147-
148-
149-/* GtkTreeModel callbacks */
150-static void history_row_changed (GtkTreeModel *model,
151- GtkTreePath *path,
152- GtkTreeIter *iter,
153- gpointer user_data);
154-/* GtkComboBox callbacks */
155-static void combo_box_changed_cb (GtkComboBox *widget,
156- gpointer user_data);
157-static gboolean combo_box_row_separator_func (GtkTreeModel *model,
158- GtkTreeIter *iter,
159- gpointer user_data);
160-/* GtkEntry callbacks */
161-static gboolean entry_focus_in_cb (GtkWidget *widget,
162- GdkEventFocus *event,
163- gpointer user_data);
164-static gboolean entry_focus_out_cb (GtkWidget *widget,
165- GdkEventFocus *event,
166- gpointer user_data);
167-static void entry_activate_cb (GtkEntry *text_entry,
168- gpointer user_data);
169-static void entry_icon_press_cb (GtkEntry *gtkentry,
170- GtkEntryIconPosition icon_pos,
171- GdkEvent *event,
172- YelpLocationEntry *entry);
173-static gboolean entry_key_press_cb (GtkWidget *widget,
174- GdkEventKey *event,
175- YelpLocationEntry *entry);
176-/* GtkCellLayout callbacks */
177-static void cell_set_text_cell (GtkCellLayout *layout,
178- GtkCellRenderer *cell,
179- GtkTreeModel *model,
180- GtkTreeIter *iter,
181- YelpLocationEntry *entry);
182-static void cell_set_bookmark_icon (GtkCellLayout *layout,
183- GtkCellRenderer *cell,
184- GtkTreeModel *model,
185- GtkTreeIter *iter,
186- YelpLocationEntry *entry);
187-/* GtkEntryCompletion callbacks */
188-static void cell_set_completion_bookmark_icon (GtkCellLayout *layout,
189- GtkCellRenderer *cell,
190- GtkTreeModel *model,
191- GtkTreeIter *iter,
192- YelpLocationEntry *entry);
193-static void cell_set_completion_text_cell (GtkCellLayout *layout,
194- GtkCellRenderer *cell,
195- GtkTreeModel *model,
196- GtkTreeIter *iter,
197- YelpLocationEntry *entry);
198-static gboolean entry_match_func (GtkEntryCompletion *completion,
199- const gchar *key,
200- GtkTreeIter *iter,
201- YelpLocationEntry *entry);
202-static gint entry_completion_sort (GtkTreeModel *model,
203- GtkTreeIter *iter1,
204- GtkTreeIter *iter2,
205- gpointer user_data);
206-static gboolean entry_match_selected (GtkEntryCompletion *completion,
207- GtkTreeModel *model,
208- GtkTreeIter *iter,
209- YelpLocationEntry *entry);
210-/* YelpView callbacks */
211-static void view_loaded (YelpView *view,
212- YelpLocationEntry *entry);
213-static void view_uri_selected (YelpView *view,
214- GParamSpec *pspec,
215- YelpLocationEntry *entry);
216-static void view_page_title (YelpView *view,
217- GParamSpec *pspec,
218- YelpLocationEntry *entry);
219-static void view_page_desc (YelpView *view,
220- GParamSpec *pspec,
221- YelpLocationEntry *entry);
222-static void view_page_icon (YelpView *view,
223- GParamSpec *pspec,
224- YelpLocationEntry *entry);
225-/* YelpBookmarks callbacks */
226-static void bookmarks_changed (YelpBookmarks *bookmarks,
227- const gchar *doc_uri,
228- YelpLocationEntry *entry);
229-
230-
231-
232-typedef struct _YelpLocationEntryPrivate YelpLocationEntryPrivate;
233-struct _YelpLocationEntryPrivate
234-{
235- YelpView *view;
236- YelpBookmarks *bookmarks;
237- GtkTreeRowReference *row;
238- gchar *completion_uri;
239-
240- /* do not free below */
241- GtkWidget *text_entry;
242- GtkCellRenderer *icon_cell;
243- GtkListStore *history;
244- GtkEntryCompletion *completion;
245-
246- gboolean enable_search;
247- gboolean view_uri_selected;
248- gboolean search_mode;
249- guint pulse;
250- gulong bookmarks_changed;
251-
252- gboolean icon_is_clear;
253-};
254-
255-enum {
256- LOCATION_ENTRY_IS_LOADING = 1 << 0,
257- LOCATION_ENTRY_IS_SEPARATOR = 1 << 1,
258- LOCATION_ENTRY_IS_SEARCH = 1 << 2
259-};
260-
261-enum {
262- HISTORY_COL_TITLE,
263- HISTORY_COL_DESC,
264- HISTORY_COL_ICON,
265- HISTORY_COL_URI,
266- HISTORY_COL_DOC,
267- HISTORY_COL_PAGE,
268- HISTORY_COL_FLAGS,
269- HISTORY_COL_TERMS
270-};
271-
272-enum {
273- COMPLETION_COL_TITLE,
274- COMPLETION_COL_DESC,
275- COMPLETION_COL_ICON,
276- COMPLETION_COL_PAGE,
277- COMPLETION_COL_FLAGS
278-};
279-
280-enum {
281- COMPLETION_FLAG_ACTIVATE_SEARCH = 1<<0
282-};
283-
284-enum {
285- LOCATION_SELECTED,
286- SEARCH_ACTIVATED,
287- BOOKMARK_CLICKED,
288- LAST_SIGNAL
289-};
290-
291-enum {
292- PROP_0,
293- PROP_VIEW,
294- PROP_BOOKMARKS,
295- PROP_ENABLE_SEARCH
296-};
297-
298-static GHashTable *completions;
299-
300-static guint location_entry_signals[LAST_SIGNAL] = {0,};
301-
302-#define MAX_HISTORY 8
303-
304-G_DEFINE_TYPE (YelpLocationEntry, yelp_location_entry, GTK_TYPE_COMBO_BOX)
305-#define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE((object), YELP_TYPE_LOCATION_ENTRY, YelpLocationEntryPrivate))
306-
307-static void
308-yelp_location_entry_class_init (YelpLocationEntryClass *klass)
309-{
310- GObjectClass *object_class;
311-
312- klass->location_selected = location_entry_location_selected;
313- klass->search_activated = location_entry_search_activated;
314- klass->bookmark_clicked = location_entry_bookmark_clicked;
315-
316- object_class = G_OBJECT_CLASS (klass);
317-
318- object_class->constructed = location_entry_constructed;
319- object_class->dispose = location_entry_dispose;
320- object_class->finalize = location_entry_finalize;
321- object_class->get_property = location_entry_get_property;
322- object_class->set_property = location_entry_set_property;
323-
324- /**
325- * YelpLocationEntry::location-selected
326- * @widget: The #YelpLocationEntry for which the signal was emitted.
327- * @user_data: User data set when the handler was connected.
328- *
329- * This signal will be emitted whenever a user selects a normal row from the
330- * drop-down menu. Note that if a row has the flag %YELP_LOCATION_ENTRY_IS_SEARCH,
331- * clicking the row will cause @widget to enter search mode, and this signal
332- * will not be emitted.
333- **/
334- location_entry_signals[LOCATION_SELECTED] =
335- g_signal_new ("location-selected",
336- G_OBJECT_CLASS_TYPE (klass),
337- G_SIGNAL_RUN_LAST,
338- G_STRUCT_OFFSET (YelpLocationEntryClass, location_selected),
339- NULL, NULL,
340- g_cclosure_marshal_VOID__VOID,
341- G_TYPE_NONE, 0);
342-
343- /**
344- * YelpLocationEntry::search-activated
345- * @widget: The #YelpLocationEntry for which the signal was emitted.
346- * @text: The search text.
347- * @user_data: User data set when the handler was connected.
348- *
349- * This signal will be emitted whenever the user activates a search, generally
350- * by pressing <keycap>Enter</keycap> in the embedded text entry while @widget
351- * is in search mode.
352- **/
353- location_entry_signals[SEARCH_ACTIVATED] =
354- g_signal_new ("search-activated",
355- G_OBJECT_CLASS_TYPE (klass),
356- G_SIGNAL_RUN_LAST,
357- G_STRUCT_OFFSET (YelpLocationEntryClass, search_activated),
358- NULL, NULL,
359- g_cclosure_marshal_VOID__STRING,
360- G_TYPE_NONE, 1,
361- G_TYPE_STRING);
362-
363- /**
364- * YelpLocationEntry::bookmark-clicked
365- * @widget: The #YelpLocationEntry for which the signal was emitted.
366- * @user_data: User data set when the handler was connected.
367- *
368- * This signal will be emitted whenever a user clicks the bookmark icon
369- * embedded in the location entry.
370- **/
371- location_entry_signals[BOOKMARK_CLICKED] =
372- g_signal_new ("bookmark-clicked",
373- G_OBJECT_CLASS_TYPE (klass),
374- G_SIGNAL_RUN_LAST,
375- G_STRUCT_OFFSET (YelpLocationEntryClass, bookmark_clicked),
376- NULL, NULL,
377- g_cclosure_marshal_VOID__VOID,
378- G_TYPE_NONE, 0);
379-
380- /**
381- * YelpLocationEntry:view
382- *
383- * The YelpView instance that this location entry controls.
384- **/
385- g_object_class_install_property (object_class,
386- PROP_VIEW,
387- g_param_spec_object ("view",
388- _("View"),
389- _("A YelpView instance to control"),
390- YELP_TYPE_VIEW,
391- G_PARAM_CONSTRUCT_ONLY |
392- G_PARAM_READWRITE |
393- G_PARAM_STATIC_STRINGS));
394-
395- /**
396- * YelpLocationEntry:bookmarks
397- *
398- * An instance of an implementation of YelpBookmarks to provide
399- * bookmark information for this location entry.
400- **/
401- g_object_class_install_property (object_class,
402- PROP_BOOKMARKS,
403- g_param_spec_object ("bookmarks",
404- _("Bookmarks"),
405- _("A YelpBookmarks implementation instance"),
406- YELP_TYPE_BOOKMARKS,
407- G_PARAM_CONSTRUCT_ONLY |
408- G_PARAM_READWRITE |
409- G_PARAM_STATIC_STRINGS));
410-
411- /**
412- * YelpLocationEntry:enable-search
413- *
414- * Whether the location entry can act as a search entry. If search is not
415- * enabled, the user will not be able to initiate a search by clicking in
416- * the embedded text entry or selecting a search row in the drop-down menu.
417- **/
418- g_object_class_install_property (object_class,
419- PROP_ENABLE_SEARCH,
420- g_param_spec_boolean ("enable-search",
421- N_("Enable Search"),
422- N_("Whether the location entry can be used as a search field"),
423- TRUE,
424- G_PARAM_CONSTRUCT |
425- G_PARAM_READWRITE |
426- G_PARAM_STATIC_STRINGS));
427-
428- g_type_class_add_private ((GObjectClass *) klass,
429- sizeof (YelpLocationEntryPrivate));
430-
431- completions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
432-}
433-
434-static void
435-yelp_location_entry_init (YelpLocationEntry *entry)
436-{
437- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
438-
439- priv->search_mode = FALSE;
440- g_object_set (entry, "entry-text-column", HISTORY_COL_TITLE, NULL);
441-}
442-
443-static void
444-location_entry_constructed (GObject *object)
445-{
446- GtkCellRenderer *bookmark_cell;
447- GList *cells;
448- GtkTreeIter iter;
449- YelpLocationEntryPrivate *priv = GET_PRIV (object);
450-
451- /* Set up the text entry child */
452- priv->text_entry = gtk_bin_get_child (GTK_BIN (object));
453- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
454- GTK_ENTRY_ICON_PRIMARY,
455- "help-browser");
456- gtk_entry_set_icon_activatable (GTK_ENTRY (priv->text_entry),
457- GTK_ENTRY_ICON_PRIMARY,
458- FALSE);
459- gtk_entry_set_icon_activatable (GTK_ENTRY (priv->text_entry),
460- GTK_ENTRY_ICON_SECONDARY,
461- TRUE);
462- gtk_editable_set_editable (GTK_EDITABLE (priv->text_entry),
463- priv->enable_search);
464- if (!priv->enable_search) {
465- priv->search_mode = FALSE;
466- location_entry_set_entry ((YelpLocationEntry *) object, FALSE);
467- }
468-
469- /* Set up the history model */
470- priv->history = gtk_list_store_new (8,
471- G_TYPE_STRING, /* title */
472- G_TYPE_STRING, /* desc */
473- G_TYPE_STRING, /* icon */
474- G_TYPE_STRING, /* uri */
475- G_TYPE_STRING, /* doc */
476- G_TYPE_STRING, /* page */
477- G_TYPE_INT, /* flags */
478- G_TYPE_STRING /* search terms */
479- );
480- g_signal_connect (priv->history, "row-changed",
481- G_CALLBACK (history_row_changed),
482- object);
483- g_object_set (object, "model", priv->history, NULL);
484- if (priv->enable_search) {
485- gtk_list_store_append (priv->history, &iter);
486- gtk_list_store_set (priv->history, &iter,
487- HISTORY_COL_FLAGS, LOCATION_ENTRY_IS_SEPARATOR,
488- -1);
489- gtk_list_store_append (priv->history, &iter);
490- gtk_list_store_set (priv->history, &iter,
491- HISTORY_COL_ICON, "edit-find-symbolic",
492- HISTORY_COL_TITLE, _("Search..."),
493- HISTORY_COL_FLAGS, LOCATION_ENTRY_IS_SEARCH,
494- -1);
495- }
496-
497- /* Set up the history drop-down */
498- /* Trying to get the text to line up with the text in the GtkEntry.
499- * The text cell is the zeroeth cell right now, since we haven't
500- * yet called reorder. I realize using a guesstimate pixel value
501- * won't be perfect all the time, but 4 looks niceish.
502- */
503- cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (object));
504- g_object_set (cells->data, "xpad", 4, NULL);
505- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (object),
506- GTK_CELL_RENDERER (cells->data),
507- (GtkCellLayoutDataFunc) cell_set_text_cell,
508- object, NULL);
509- g_object_set (cells->data, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
510- g_list_free (cells);
511-
512- priv->icon_cell = gtk_cell_renderer_pixbuf_new ();
513- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), priv->icon_cell, FALSE);
514- g_object_set (priv->icon_cell, "yalign", 0.2, NULL);
515- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object),
516- priv->icon_cell,
517- "icon-name",
518- HISTORY_COL_ICON,
519- NULL);
520- gtk_cell_layout_reorder (GTK_CELL_LAYOUT (object), priv->icon_cell, 0);
521-
522- if (priv->bookmarks) {
523- bookmark_cell = gtk_cell_renderer_pixbuf_new ();
524- gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (object), bookmark_cell, FALSE);
525- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (object),
526- bookmark_cell,
527- (GtkCellLayoutDataFunc) cell_set_bookmark_icon,
528- object, NULL);
529- }
530- gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (object),
531- (GtkTreeViewRowSeparatorFunc)
532- combo_box_row_separator_func,
533- object, NULL);
534- /* Without this, you get a warning about the popup widget
535- * being NULL the firt time you click the arrow.
536- */
537- gtk_widget_show_all (GTK_WIDGET (object));
538-
539- /* Connect signals */
540- g_signal_connect (object, "changed",
541- G_CALLBACK (combo_box_changed_cb), NULL);
542-
543- g_signal_connect (priv->text_entry, "focus-in-event",
544- G_CALLBACK (entry_focus_in_cb), object);
545- g_signal_connect (priv->text_entry, "focus-out-event",
546- G_CALLBACK (entry_focus_out_cb), object);
547- g_signal_connect (priv->text_entry, "icon-press",
548- G_CALLBACK (entry_icon_press_cb), object);
549- g_signal_connect (priv->text_entry, "key-press-event",
550- G_CALLBACK (entry_key_press_cb), object);
551- g_signal_connect (priv->text_entry, "activate",
552- G_CALLBACK (entry_activate_cb), object);
553-
554- if (priv->bookmarks)
555- priv->bookmarks_changed = g_signal_connect (priv->bookmarks,
556- "bookmarks-changed",
557- G_CALLBACK (bookmarks_changed),
558- object);
559-
560- g_signal_connect (priv->view, "loaded", G_CALLBACK (view_loaded), object);
561- g_signal_connect (priv->view, "notify::yelp-uri", G_CALLBACK (view_uri_selected), object);
562- g_signal_connect (priv->view, "notify::page-title", G_CALLBACK (view_page_title), object);
563- g_signal_connect (priv->view, "notify::page-desc", G_CALLBACK (view_page_desc), object);
564- g_signal_connect (priv->view, "notify::page-icon", G_CALLBACK (view_page_icon), object);
565-}
566-
567-static void
568-location_entry_dispose (GObject *object)
569-{
570- YelpLocationEntryPrivate *priv = GET_PRIV (object);
571-
572- if (priv->view) {
573- g_object_unref (priv->view);
574- priv->view = NULL;
575- }
576-
577- if (priv->bookmarks) {
578- g_object_unref (priv->bookmarks);
579- priv->bookmarks = NULL;
580- }
581-
582- if (priv->bookmarks_changed) {
583- g_source_remove (priv->bookmarks_changed);
584- priv->bookmarks_changed = 0;
585- }
586-
587- if (priv->row) {
588- gtk_tree_row_reference_free (priv->row);
589- priv->row = NULL;
590- }
591-
592- if (priv->pulse > 0) {
593- g_source_remove (priv->pulse);
594- priv->pulse = 0;
595- }
596-
597- G_OBJECT_CLASS (yelp_location_entry_parent_class)->dispose (object);
598-}
599-
600-static void
601-location_entry_finalize (GObject *object)
602-{
603- YelpLocationEntryPrivate *priv = GET_PRIV (object);
604-
605- g_free (priv->completion_uri);
606-
607- G_OBJECT_CLASS (yelp_location_entry_parent_class)->finalize (object);
608-}
609-
610-static void
611-location_entry_get_property (GObject *object,
612- guint prop_id,
613- GValue *value,
614- GParamSpec *pspec)
615-{
616- YelpLocationEntryPrivate *priv = GET_PRIV (object);
617-
618- switch (prop_id) {
619- case PROP_VIEW:
620- g_value_set_object (value, priv->view);
621- break;
622- case PROP_BOOKMARKS:
623- g_value_set_object (value, priv->bookmarks);
624- break;
625- case PROP_ENABLE_SEARCH:
626- g_value_set_boolean (value, priv->enable_search);
627- break;
628- default:
629- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
630- break;
631- }
632-}
633-
634-static void
635-location_entry_set_property (GObject *object,
636- guint prop_id,
637- const GValue *value,
638- GParamSpec *pspec)
639-{
640- YelpLocationEntryPrivate *priv = GET_PRIV (object);
641-
642- switch (prop_id) {
643- case PROP_VIEW:
644- priv->view = g_value_dup_object (value);
645- break;
646- case PROP_BOOKMARKS:
647- priv->bookmarks = g_value_dup_object (value);
648- break;
649- case PROP_ENABLE_SEARCH:
650- priv->enable_search = g_value_get_boolean (value);
651- break;
652- default:
653- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
654- break;
655- }
656-}
657-
658-static void
659-location_entry_location_selected (YelpLocationEntry *entry)
660-{
661- GtkTreeIter iter;
662- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
663-
664- if (priv->view_uri_selected)
665- return;
666-
667- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (entry), &iter)) {
668- gchar *uri;
669- gtk_tree_model_get (GTK_TREE_MODEL (priv->history), &iter,
670- HISTORY_COL_URI, &uri,
671- -1);
672- yelp_view_load (priv->view, uri);
673- g_free (uri);
674- }
675-}
676-
677-static void
678-location_entry_search_activated (YelpLocationEntry *entry)
679-{
680- YelpUri *base, *uri;
681- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
682-
683- g_object_get (priv->view, "yelp-uri", &base, NULL);
684- if (base == NULL)
685- return;
686- uri = yelp_uri_new_search (base,
687- gtk_entry_get_text (GTK_ENTRY (priv->text_entry)));
688- g_object_unref (base);
689- yelp_view_load_uri (priv->view, uri);
690- gtk_widget_grab_focus (GTK_WIDGET (priv->view));
691-}
692-
693-static void
694-location_entry_bookmark_clicked (YelpLocationEntry *entry)
695-{
696- YelpUri *uri;
697- gchar *doc_uri, *page_id;
698- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
699-
700- g_object_get (priv->view,
701- "yelp-uri", &uri,
702- "page-id", &page_id,
703- NULL);
704- doc_uri = yelp_uri_get_document_uri (uri);
705- if (priv->bookmarks && doc_uri && page_id) {
706- if (!yelp_bookmarks_is_bookmarked (priv->bookmarks, doc_uri, page_id)) {
707- gchar *icon, *title;
708- g_object_get (priv->view,
709- "page-icon", &icon,
710- "page-title", &title,
711- NULL);
712- yelp_bookmarks_add_bookmark (priv->bookmarks, doc_uri, page_id, icon, title);
713- g_free (icon);
714- g_free (title);
715- }
716- else {
717- yelp_bookmarks_remove_bookmark (priv->bookmarks, doc_uri, page_id);
718- }
719- }
720- g_free (doc_uri);
721- g_free (page_id);
722- g_object_unref (uri);
723-}
724-
725-static void
726-location_entry_start_search (YelpLocationEntry *entry,
727- gboolean clear)
728-{
729- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
730-
731- if (!priv->enable_search)
732- return;
733- if (clear && !priv->search_mode) {
734- const gchar *icon = gtk_entry_get_icon_name (GTK_ENTRY (priv->text_entry),
735- GTK_ENTRY_ICON_PRIMARY);
736- if (!g_str_equal (icon, "folder-saved-search"))
737- gtk_entry_set_text (GTK_ENTRY (priv->text_entry), "");
738- }
739- priv->search_mode = TRUE;
740- location_entry_set_entry (entry, FALSE);
741- gtk_widget_grab_focus (priv->text_entry);
742-}
743-
744-static void
745-location_entry_cancel_search (YelpLocationEntry *entry)
746-{
747- gboolean ret;
748- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
749- GdkEventFocus *event = g_new0 (GdkEventFocus, 1);
750- priv->search_mode = FALSE;
751- location_entry_set_entry (entry, FALSE);
752- event->type = GDK_FOCUS_CHANGE;
753- event->window = gtk_widget_get_window (GTK_WIDGET (entry));
754- event->send_event = FALSE;
755- event->in = FALSE;
756- g_signal_emit_by_name (entry, "focus-out-event", event, &ret);
757- g_free (event);
758- /* Hack: This makes the popup disappear when you hit Esc. */
759- if (priv->completion) {
760- g_object_ref (priv->completion);
761- gtk_entry_set_completion (GTK_ENTRY (priv->text_entry), NULL);
762- gtk_entry_set_completion (GTK_ENTRY (priv->text_entry),
763- priv->completion);
764- g_object_unref (priv->completion);
765- }
766- gtk_editable_select_region (GTK_EDITABLE (priv->text_entry), 0, 0);
767-}
768-
769-static void
770-location_entry_set_completion (YelpLocationEntry *entry,
771- GtkTreeModel *model)
772-{
773- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
774- GList *cells;
775- GtkCellRenderer *icon_cell, *bookmark_cell;
776-
777- priv->completion = gtk_entry_completion_new ();
778- gtk_entry_completion_set_minimum_key_length (priv->completion, 3);
779- gtk_entry_completion_set_model (priv->completion, model);
780- gtk_entry_completion_set_text_column (priv->completion, COMPLETION_COL_TITLE);
781- gtk_entry_completion_set_match_func (priv->completion,
782- (GtkEntryCompletionMatchFunc) entry_match_func,
783- entry, NULL);
784- g_signal_connect (priv->completion, "match-selected",
785- G_CALLBACK (entry_match_selected), entry);
786-
787- cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->completion));
788- g_object_set (cells->data, "xpad", 4, NULL);
789- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->completion),
790- GTK_CELL_RENDERER (cells->data),
791- (GtkCellLayoutDataFunc) cell_set_completion_text_cell,
792- entry, NULL);
793- g_object_set (cells->data, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
794- g_list_free (cells);
795-
796- icon_cell = gtk_cell_renderer_pixbuf_new ();
797- g_object_set (priv->icon_cell, "yalign", 0.2, NULL);
798- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->completion), icon_cell, FALSE);
799- gtk_cell_layout_reorder (GTK_CELL_LAYOUT (priv->completion), icon_cell, 0);
800- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->completion),
801- icon_cell,
802- "icon-name",
803- COMPLETION_COL_ICON,
804- NULL);
805- if (priv->bookmarks) {
806- bookmark_cell = gtk_cell_renderer_pixbuf_new ();
807- gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (priv->completion), bookmark_cell, FALSE);
808- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->completion),
809- bookmark_cell,
810- (GtkCellLayoutDataFunc) cell_set_completion_bookmark_icon,
811- entry, NULL);
812- }
813- gtk_entry_set_completion (GTK_ENTRY (priv->text_entry),
814- priv->completion);
815-}
816-
817-static void
818-location_entry_set_entry (YelpLocationEntry *entry, gboolean emit)
819-{
820- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
821- GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (entry));
822- GtkTreePath *path = NULL;
823- GtkTreeIter iter;
824- gchar *icon_name;
825-
826- if (priv->search_mode) {
827- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
828- GTK_ENTRY_ICON_PRIMARY,
829- "edit-find-symbolic");
830- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
831- GTK_ENTRY_ICON_SECONDARY,
832- "edit-clear-symbolic");
833- gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->text_entry),
834- GTK_ENTRY_ICON_SECONDARY,
835- _("Clear the search text"));
836- priv->icon_is_clear = TRUE;
837- return;
838- }
839- else {
840- priv->icon_is_clear = FALSE;
841- }
842-
843-
844- if (priv->row)
845- path = gtk_tree_row_reference_get_path (priv->row);
846-
847- if (path) {
848- gchar *text, *doc_uri, *page_id;
849- gint flags;
850- gtk_tree_model_get_iter (model, &iter, path);
851- gtk_tree_model_get (model, &iter,
852- HISTORY_COL_TITLE, &text,
853- HISTORY_COL_ICON, &icon_name,
854- HISTORY_COL_FLAGS, &flags,
855- HISTORY_COL_DOC, &doc_uri,
856- HISTORY_COL_PAGE, &page_id,
857- -1);
858- if (flags & LOCATION_ENTRY_IS_LOADING) {
859- /* Would be nice to have a "loading" icon. I was using image-loading,
860- * but it look out of place with symbolic page icons. Plus, using
861- * image-loading-symbolic shows a broken image, because GtkEntry
862- * doesn't correctly use symbolic icons as of GNOME 3.0.
863- */
864- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
865- GTK_ENTRY_ICON_PRIMARY,
866- "yelp-page-symbolic");
867- if (priv->pulse == 0)
868- priv->pulse = g_timeout_add (500, location_entry_start_pulse, entry);
869- }
870- else {
871- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
872- GTK_ENTRY_ICON_PRIMARY,
873- icon_name);
874- }
875- if (priv->bookmarks && doc_uri && page_id) {
876- GdkPixbuf *pixbuf;
877- if (!yelp_bookmarks_is_bookmarked (priv->bookmarks, doc_uri, page_id)) {
878- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
879- GTK_ENTRY_ICON_SECONDARY,
880- "yelp-bookmark-add-symbolic");
881- gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->text_entry),
882- GTK_ENTRY_ICON_SECONDARY,
883- _("Bookmark this page"));
884- }
885- else {
886- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
887- GTK_ENTRY_ICON_SECONDARY,
888- "yelp-bookmark-remove-symbolic");
889- gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->text_entry),
890- GTK_ENTRY_ICON_SECONDARY,
891- _("Remove bookmark"));
892- }
893- }
894- else {
895- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
896- GTK_ENTRY_ICON_SECONDARY,
897- NULL);
898- }
899- g_free (doc_uri);
900- g_free (page_id);
901- gtk_entry_set_text (GTK_ENTRY (priv->text_entry), text);
902- if (emit)
903- g_signal_emit (entry, location_entry_signals[LOCATION_SELECTED], 0);
904- g_free (text);
905- gtk_tree_path_free (path);
906- }
907- else {
908- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
909- GTK_ENTRY_ICON_PRIMARY,
910- "help-browser");
911- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
912- GTK_ENTRY_ICON_SECONDARY,
913- NULL);
914- }
915-}
916-
917-static gboolean
918-location_entry_start_pulse (gpointer data)
919-{
920- YelpLocationEntryPrivate *priv = GET_PRIV (data);
921- priv->pulse = g_timeout_add (80, location_entry_pulse, data);
922- return FALSE;
923-}
924-
925-static gboolean
926-location_entry_pulse (gpointer data)
927-{
928- YelpLocationEntryPrivate *priv = GET_PRIV (data);
929- GtkTreeModel *model;
930- GtkTreePath *path;
931- GtkTreeIter iter;
932- gint flags;
933-
934- model = gtk_tree_row_reference_get_model (priv->row);
935- path = gtk_tree_row_reference_get_path (priv->row);
936- if (path) {
937- gtk_tree_model_get_iter (model, &iter, path);
938- gtk_tree_model_get (model, &iter,
939- HISTORY_COL_FLAGS, &flags,
940- -1);
941- gtk_tree_path_free (path);
942- }
943-
944- if (flags & LOCATION_ENTRY_IS_LOADING && !priv->search_mode) {
945- gtk_entry_progress_pulse (GTK_ENTRY (priv->text_entry));
946- }
947- else {
948- gtk_entry_set_progress_fraction (GTK_ENTRY (priv->text_entry), 0.0);
949- priv->pulse = 0;
950- }
951-
952- return flags & LOCATION_ENTRY_IS_LOADING;
953-}
954-
955-static void
956-combo_box_changed_cb (GtkComboBox *widget,
957- gpointer user_data)
958-{
959- YelpLocationEntryPrivate *priv = GET_PRIV (widget);
960- GtkTreeIter iter;
961- GtkTreeModel *model;
962-
963- model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
964-
965- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
966- gint flags;
967- gtk_tree_model_get (model, &iter,
968- HISTORY_COL_FLAGS, &flags,
969- -1);
970- if (flags & LOCATION_ENTRY_IS_SEARCH) {
971- location_entry_start_search ((YelpLocationEntry *) widget, TRUE);
972- }
973- else {
974- GtkTreePath *cur, *path;
975- path = gtk_tree_model_get_path (model, &iter);
976- if (priv->row) {
977- cur = gtk_tree_row_reference_get_path (priv->row);
978- if (gtk_tree_path_compare (cur, path) == 0) {
979- gtk_tree_path_free (cur);
980- gtk_tree_path_free (path);
981- return;
982- }
983- gtk_tree_path_free (cur);
984- gtk_tree_row_reference_free (priv->row);
985- }
986- priv->row = gtk_tree_row_reference_new (model, path);
987- gtk_tree_path_free (path);
988- priv->search_mode = FALSE;
989- location_entry_set_entry ((YelpLocationEntry *) widget, TRUE);
990- }
991- }
992-}
993-
994-static gboolean
995-combo_box_row_separator_func (GtkTreeModel *model,
996- GtkTreeIter *iter,
997- gpointer user_data)
998-{
999- YelpLocationEntryPrivate *priv = GET_PRIV (user_data);
1000- gint flags;
1001- gtk_tree_model_get (model, iter,
1002- HISTORY_COL_FLAGS, &flags,
1003- -1);
1004- return (flags & LOCATION_ENTRY_IS_SEPARATOR);
1005-}
1006-
1007-static void
1008-history_row_changed (GtkTreeModel *model,
1009- GtkTreePath *path,
1010- GtkTreeIter *iter,
1011- gpointer user_data)
1012-{
1013- /* FIXME: Should we bother checking path/iter against priv->row?
1014- It doesn't really make a difference, since set_entry is pretty much
1015- safe to call whenever. Does it make a performance impact?
1016- */
1017- location_entry_set_entry (YELP_LOCATION_ENTRY (user_data), FALSE);
1018-}
1019-
1020-static gboolean
1021-entry_focus_in_cb (GtkWidget *widget,
1022- GdkEventFocus *event,
1023- gpointer user_data)
1024-{
1025- GtkEntry *text_entry = GTK_ENTRY (widget);
1026- YelpLocationEntryPrivate *priv = GET_PRIV (user_data);
1027-
1028- if (priv->enable_search && !priv->search_mode)
1029- location_entry_start_search ((YelpLocationEntry *) user_data, TRUE);
1030-
1031- return FALSE;
1032-}
1033-
1034-static gboolean
1035-entry_focus_out_cb (GtkWidget *widget,
1036- GdkEventFocus *event,
1037- gpointer user_data)
1038-{
1039- YelpLocationEntryPrivate *priv = GET_PRIV (user_data);
1040-
1041- if (gtk_entry_get_text_length (GTK_ENTRY (widget)) == 0) {
1042- priv->search_mode = FALSE;
1043- location_entry_set_entry ((YelpLocationEntry *) user_data, FALSE);
1044- }
1045-
1046- return FALSE;
1047-}
1048-
1049-static void
1050-entry_activate_cb (GtkEntry *text_entry,
1051- gpointer user_data)
1052-{
1053- YelpLocationEntryPrivate *priv = GET_PRIV (user_data);
1054- gchar *text = g_strdup (gtk_entry_get_text (text_entry));
1055-
1056- if (!priv->enable_search)
1057- return;
1058-
1059- if (!priv->search_mode || text == NULL || strlen(text) == 0)
1060- return;
1061-
1062- g_signal_emit (user_data, location_entry_signals[SEARCH_ACTIVATED], 0, text);
1063-
1064- g_free (text);
1065-}
1066-
1067-static void
1068-entry_icon_press_cb (GtkEntry *gtkentry,
1069- GtkEntryIconPosition icon_pos,
1070- GdkEvent *event,
1071- YelpLocationEntry *entry)
1072-{
1073- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1074-
1075- if (icon_pos == GTK_ENTRY_ICON_SECONDARY) {
1076- if (priv->icon_is_clear)
1077- location_entry_cancel_search (entry);
1078- else
1079- g_signal_emit (entry, location_entry_signals[BOOKMARK_CLICKED], 0);
1080- }
1081-}
1082-
1083-static gboolean
1084-entry_key_press_cb (GtkWidget *widget,
1085- GdkEventKey *event,
1086- YelpLocationEntry *entry)
1087-{
1088- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1089- if (event->keyval == GDK_KEY_Escape) {
1090- location_entry_cancel_search (entry);
1091- return TRUE;
1092- }
1093- else if (!priv->search_mode) {
1094- location_entry_start_search (entry, FALSE);
1095- }
1096-
1097- return FALSE;
1098-}
1099-
1100-static void
1101-cell_set_text_cell (GtkCellLayout *layout,
1102- GtkCellRenderer *cell,
1103- GtkTreeModel *model,
1104- GtkTreeIter *iter,
1105- YelpLocationEntry *entry)
1106-{
1107- gchar *title, *desc, *color, *text;
1108- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1109-
1110- gtk_tree_model_get (model, iter,
1111- HISTORY_COL_TITLE, &title,
1112- HISTORY_COL_DESC, &desc,
1113- -1);
1114- if (desc) {
1115- color = yelp_settings_get_color (yelp_settings_get_default (),
1116- YELP_SETTINGS_COLOR_TEXT_LIGHT);
1117- text = g_markup_printf_escaped ("<span size='larger'>%s</span>\n<span color='%s'>%s</span>",
1118- title, color, desc);
1119- g_free (color);
1120- g_free (desc);
1121- }
1122- else {
1123- text = g_markup_printf_escaped ("<span size='larger'>%s</span>", title);
1124- }
1125-
1126- g_object_set (cell, "markup", text, NULL);
1127- g_free (text);
1128- g_free (title);
1129-}
1130-
1131-static void
1132-cell_set_bookmark_icon (GtkCellLayout *layout,
1133- GtkCellRenderer *cell,
1134- GtkTreeModel *model,
1135- GtkTreeIter *iter,
1136- YelpLocationEntry *entry)
1137-{
1138- gint flags;
1139- gchar *doc_uri, *page_id;
1140- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1141-
1142- if (priv->bookmarks == NULL) {
1143- g_object_set (cell, "icon-name", NULL, NULL);
1144- return;
1145- }
1146-
1147- gtk_tree_model_get (model, iter, HISTORY_COL_FLAGS, &flags, -1);
1148- if (flags & (LOCATION_ENTRY_IS_SEPARATOR | LOCATION_ENTRY_IS_SEARCH)) {
1149- g_object_set (cell, "icon-name", NULL, NULL);
1150- return;
1151- }
1152-
1153- gtk_tree_model_get (model, iter,
1154- HISTORY_COL_DOC, &doc_uri,
1155- HISTORY_COL_PAGE, &page_id,
1156- -1);
1157- if (doc_uri && page_id &&
1158- yelp_bookmarks_is_bookmarked (priv->bookmarks, doc_uri, page_id))
1159- g_object_set (cell, "icon-name", "yelp-bookmark-remove-symbolic", NULL);
1160- else
1161- g_object_set (cell, "icon-name", NULL, NULL);
1162-
1163- g_free (doc_uri);
1164- g_free (page_id);
1165-}
1166-
1167-static void
1168-cell_set_completion_bookmark_icon (GtkCellLayout *layout,
1169- GtkCellRenderer *cell,
1170- GtkTreeModel *model,
1171- GtkTreeIter *iter,
1172- YelpLocationEntry *entry)
1173-{
1174- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1175-
1176- if (priv->completion_uri) {
1177- gchar *page_id = NULL;
1178- gtk_tree_model_get (model, iter,
1179- COMPLETION_COL_PAGE, &page_id,
1180- -1);
1181-
1182- if (page_id && yelp_bookmarks_is_bookmarked (priv->bookmarks,
1183- priv->completion_uri, page_id))
1184- g_object_set (cell, "icon-name", "yelp-bookmark-remove-symbolic", NULL);
1185- else
1186- g_object_set (cell, "icon-name", NULL, NULL);
1187-
1188- g_free (page_id);
1189- }
1190-}
1191-
1192-static void
1193-cell_set_completion_text_cell (GtkCellLayout *layout,
1194- GtkCellRenderer *cell,
1195- GtkTreeModel *model,
1196- GtkTreeIter *iter,
1197- YelpLocationEntry *entry)
1198-{
1199- gchar *title, *desc, *color, *text;
1200- gint flags;
1201- GList *cells, *cur;
1202- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1203-
1204- gtk_tree_model_get (model, iter, COMPLETION_COL_FLAGS, &flags, -1);
1205- if (flags & COMPLETION_FLAG_ACTIVATE_SEARCH) {
1206- title = g_strdup_printf (_("Search for “%s”"),
1207- gtk_entry_get_text (GTK_ENTRY (priv->text_entry)));
1208- text = g_markup_printf_escaped ("<span size='larger' font_weight='bold'>%s</span>", title);
1209- g_object_set (cell, "markup", text, NULL);
1210- g_free (text);
1211- g_free (title);
1212-
1213- color = yelp_settings_get_color (yelp_settings_get_default (),
1214- YELP_SETTINGS_COLOR_YELLOW_BASE);
1215- cells = gtk_cell_layout_get_cells (layout);
1216- for (cur = cells; cur; cur = cur->next) {
1217- g_object_set (cur->data,
1218- "cell-background", color,
1219- "cell-background-set", TRUE,
1220- NULL);
1221- }
1222- g_list_free (cells);
1223- g_free (color);
1224- return;
1225- }
1226-
1227- gtk_tree_model_get (model, iter,
1228- COMPLETION_COL_TITLE, &title,
1229- COMPLETION_COL_DESC, &desc,
1230- -1);
1231- if (desc) {
1232- color = yelp_settings_get_color (yelp_settings_get_default (),
1233- YELP_SETTINGS_COLOR_TEXT_LIGHT);
1234- text = g_markup_printf_escaped ("<span size='larger'>%s</span>\n<span color='%s'>%s</span>",
1235- title, color, desc);
1236- g_free (color);
1237- g_free (desc);
1238- }
1239- else {
1240- text = g_markup_printf_escaped ("<span size='larger'>%s</span>", title);
1241- }
1242-
1243- g_object_set (cell, "markup", text, NULL);
1244- g_free (text);
1245- g_free (title);
1246-
1247- cells = gtk_cell_layout_get_cells (layout);
1248- for (cur = cells; cur; cur = cur->next)
1249- g_object_set (cur->data, "cell-background-set", FALSE, NULL);
1250- g_list_free (cells);
1251-}
1252-
1253-static gboolean
1254-entry_match_func (GtkEntryCompletion *completion,
1255- const gchar *key,
1256- GtkTreeIter *iter,
1257- YelpLocationEntry *entry)
1258-{
1259- gint stri;
1260- gchar *title, *desc, *titlecase = NULL, *desccase = NULL;
1261- gboolean ret = FALSE;
1262- gchar **strs;
1263- gint flags;
1264- GtkTreeModel *model = gtk_entry_completion_get_model (completion);
1265- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1266- static GRegex *nonword = NULL;
1267-
1268- if (nonword == NULL)
1269- nonword = g_regex_new ("\\W", 0, 0, NULL);
1270- if (nonword == NULL)
1271- return FALSE;
1272-
1273- gtk_tree_model_get (model, iter, COMPLETION_COL_FLAGS, &flags, -1);
1274- if (flags & COMPLETION_FLAG_ACTIVATE_SEARCH)
1275- return TRUE;
1276-
1277- gtk_tree_model_get (model, iter,
1278- COMPLETION_COL_TITLE, &title,
1279- COMPLETION_COL_DESC, &desc,
1280- -1);
1281- if (title) {
1282- titlecase = g_utf8_casefold (title, -1);
1283- g_free (title);
1284- }
1285- if (desc) {
1286- desccase = g_utf8_casefold (desc, -1);
1287- g_free (desc);
1288- }
1289-
1290- strs = g_regex_split (nonword, key, 0);
1291- ret = TRUE;
1292- for (stri = 0; strs[stri]; stri++) {
1293- if (!titlecase || !strstr (titlecase, strs[stri])) {
1294- if (!desccase || !strstr (desccase, strs[stri])) {
1295- ret = FALSE;
1296- break;
1297- }
1298- }
1299- }
1300-
1301- g_free (titlecase);
1302- g_free (desccase);
1303- g_strfreev (strs);
1304-
1305- return ret;
1306-}
1307-
1308-static gint
1309-entry_completion_sort (GtkTreeModel *model,
1310- GtkTreeIter *iter1,
1311- GtkTreeIter *iter2,
1312- gpointer user_data)
1313-{
1314- gint ret = 0;
1315- gint flags1, flags2;
1316- gchar *key1, *key2;
1317-
1318- gtk_tree_model_get (model, iter1, COMPLETION_COL_FLAGS, &flags1, -1);
1319- gtk_tree_model_get (model, iter2, COMPLETION_COL_FLAGS, &flags2, -1);
1320- if (flags1 & COMPLETION_FLAG_ACTIVATE_SEARCH)
1321- return 1;
1322- else if (flags2 & COMPLETION_FLAG_ACTIVATE_SEARCH)
1323- return -1;
1324-
1325- gtk_tree_model_get (model, iter1, COMPLETION_COL_ICON, &key1, -1);
1326- gtk_tree_model_get (model, iter2, COMPLETION_COL_ICON, &key2, -1);
1327- ret = yelp_settings_cmp_icons (key1, key2);
1328- g_free (key1);
1329- g_free (key2);
1330-
1331- if (ret)
1332- return ret;
1333-
1334- gtk_tree_model_get (model, iter1, COMPLETION_COL_TITLE, &key1, -1);
1335- gtk_tree_model_get (model, iter2, COMPLETION_COL_TITLE, &key2, -1);
1336- if (key1 && key2)
1337- ret = g_utf8_collate (key1, key2);
1338- else if (key2 == NULL)
1339- return -1;
1340- else if (key1 == NULL)
1341- return 1;
1342- g_free (key1);
1343- g_free (key2);
1344-
1345- return ret;
1346-}
1347-
1348-static gboolean
1349-entry_match_selected (GtkEntryCompletion *completion,
1350- GtkTreeModel *model,
1351- GtkTreeIter *iter,
1352- YelpLocationEntry *entry)
1353-{
1354- YelpUri *base, *uri;
1355- gchar *page, *xref;
1356- gint flags;
1357- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1358-
1359- gtk_tree_model_get (model, iter, COMPLETION_COL_FLAGS, &flags, -1);
1360- if (flags & COMPLETION_FLAG_ACTIVATE_SEARCH) {
1361- entry_activate_cb (GTK_ENTRY (priv->text_entry), entry);
1362- return TRUE;
1363- }
1364-
1365- g_object_get (priv->view, "yelp-uri", &base, NULL);
1366- gtk_tree_model_get (model, iter, COMPLETION_COL_PAGE, &page, -1);
1367-
1368- xref = g_strconcat ("xref:", page, NULL);
1369- uri = yelp_uri_new_relative (base, xref);
1370-
1371- yelp_view_load_uri (priv->view, uri);
1372-
1373- g_free (page);
1374- g_free (xref);
1375- g_object_unref (uri);
1376- g_object_unref (base);
1377-
1378- gtk_widget_grab_focus (GTK_WIDGET (priv->view));
1379- return TRUE;
1380-}
1381-
1382-static void
1383-view_loaded (YelpView *view,
1384- YelpLocationEntry *entry)
1385-{
1386- gchar **ids;
1387- gint i;
1388- GtkTreeIter iter;
1389- gint flags;
1390- YelpUri *uri;
1391- gchar *doc_uri, *page_id;
1392- GtkTreeModel *completion;
1393- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1394- YelpDocument *document = yelp_view_get_document (view);
1395-
1396- gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->history), &iter);
1397- gtk_tree_model_get (GTK_TREE_MODEL (priv->history), &iter,
1398- HISTORY_COL_FLAGS, &flags,
1399- -1);
1400- if (flags & LOCATION_ENTRY_IS_LOADING) {
1401- flags = flags & ~LOCATION_ENTRY_IS_LOADING;
1402- gtk_list_store_set (priv->history, &iter, HISTORY_COL_FLAGS, flags, -1);
1403- }
1404-
1405- g_object_get (view,
1406- "yelp-uri", &uri,
1407- "page-id", &page_id,
1408- NULL);
1409- doc_uri = yelp_uri_get_document_uri (uri);
1410- gtk_list_store_set (priv->history, &iter,
1411- HISTORY_COL_DOC, doc_uri,
1412- HISTORY_COL_PAGE, page_id,
1413- -1);
1414- g_free (page_id);
1415-
1416- if ((priv->completion_uri == NULL) ||
1417- !g_str_equal (doc_uri, priv->completion_uri)) {
1418- completion = (GtkTreeModel *) g_hash_table_lookup (completions, doc_uri);
1419- if (completion == NULL) {
1420- GtkListStore *base = gtk_list_store_new (5,
1421- G_TYPE_STRING, /* title */
1422- G_TYPE_STRING, /* desc */
1423- G_TYPE_STRING, /* icon */
1424- G_TYPE_STRING, /* uri */
1425- G_TYPE_INT /* flags */
1426- );
1427- completion = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (base));
1428- gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (completion),
1429- entry_completion_sort,
1430- NULL, NULL);
1431- g_hash_table_insert (completions, g_strdup (doc_uri), completion);
1432- if (document != NULL) {
1433- GtkTreeIter iter;
1434- ids = yelp_document_list_page_ids (document);
1435- for (i = 0; ids[i]; i++) {
1436- gchar *title, *desc, *icon;
1437- gtk_list_store_insert (GTK_LIST_STORE (base), &iter, 0);
1438- title = yelp_document_get_page_title (document, ids[i]);
1439- desc = yelp_document_get_page_desc (document, ids[i]);
1440- icon = yelp_document_get_page_icon (document, ids[i]);
1441- gtk_list_store_set (base, &iter,
1442- COMPLETION_COL_TITLE, title,
1443- COMPLETION_COL_DESC, desc,
1444- COMPLETION_COL_ICON, icon,
1445- COMPLETION_COL_PAGE, ids[i],
1446- -1);
1447- g_free (icon);
1448- g_free (desc);
1449- g_free (title);
1450- }
1451- g_strfreev (ids);
1452- gtk_list_store_insert (GTK_LIST_STORE (base), &iter, 0);
1453- gtk_list_store_set (base, &iter,
1454- COMPLETION_COL_ICON, "edit-find-symbolic",
1455- COMPLETION_COL_FLAGS, COMPLETION_FLAG_ACTIVATE_SEARCH,
1456- -1);
1457- }
1458- g_object_unref (base);
1459- }
1460- g_free (priv->completion_uri);
1461- priv->completion_uri = doc_uri;
1462- location_entry_set_completion (entry, completion);
1463- }
1464-
1465- g_object_unref (uri);
1466-}
1467-
1468-static void
1469-view_uri_selected (YelpView *view,
1470- GParamSpec *pspec,
1471- YelpLocationEntry *entry)
1472-{
1473- GtkTreeIter iter;
1474- gchar *iter_uri;
1475- gboolean cont;
1476- YelpUri *uri;
1477- gchar *struri, *doc_uri;
1478- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1479-
1480- g_object_get (G_OBJECT (view), "yelp-uri", &uri, NULL);
1481- if (uri == NULL)
1482- return;
1483-
1484- struri = yelp_uri_get_canonical_uri (uri);
1485-
1486- cont = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->history), &iter);
1487- while (cont) {
1488- gtk_tree_model_get (GTK_TREE_MODEL (priv->history), &iter,
1489- HISTORY_COL_URI, &iter_uri,
1490- -1);
1491- if (iter_uri && g_str_equal (struri, iter_uri)) {
1492- g_free (iter_uri);
1493- break;
1494- }
1495- else {
1496- g_free (iter_uri);
1497- cont = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->history), &iter);
1498- }
1499- }
1500- if (cont) {
1501- GtkTreeIter first;
1502- gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->history), &first);
1503- gtk_list_store_move_before (priv->history, &iter, &first);
1504- }
1505- else {
1506- gint num;
1507- GtkTreeIter last;
1508- gtk_list_store_prepend (priv->history, &iter);
1509- gtk_list_store_set (priv->history, &iter,
1510- HISTORY_COL_TITLE, _("Loading"),
1511- HISTORY_COL_ICON, "help-contents",
1512- HISTORY_COL_URI, struri,
1513- HISTORY_COL_FLAGS, LOCATION_ENTRY_IS_LOADING,
1514- -1);
1515- /* Limit to MAX_HISTORY entries. There are two extra for the search entry
1516- * and the separator above it.
1517- */
1518- num = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->history), NULL);
1519- if (num > MAX_HISTORY + 2) {
1520- if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (priv->history),
1521- &last, NULL,
1522- num - 3)) {
1523- gtk_list_store_remove (priv->history, &last);
1524- }
1525- }
1526- }
1527- priv->view_uri_selected = TRUE;
1528- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (entry), &iter);
1529- priv->view_uri_selected = FALSE;
1530-
1531- g_free (struri);
1532- g_object_unref (uri);
1533-}
1534-
1535-static void
1536-view_page_title (YelpView *view,
1537- GParamSpec *pspec,
1538- YelpLocationEntry *entry)
1539-{
1540- GtkTreeIter first;
1541- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1542-
1543- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->history), &first)) {
1544- gchar *title, *frag = NULL;
1545- YelpViewState state;
1546- YelpUri *uri;
1547-
1548- g_object_get (view,
1549- "page-title", &title,
1550- "state", &state,
1551- NULL);
1552- if (title == NULL)
1553- return;
1554-
1555- if (state != YELP_VIEW_STATE_ERROR) {
1556- YelpUri *uri;
1557- g_object_get (view, "yelp-uri", &uri, NULL);
1558- frag = yelp_uri_get_frag_id (uri);
1559- g_object_unref (uri);
1560- }
1561-
1562- if (frag) {
1563- gchar *tmp = g_strdup_printf ("%s (#%s)", title, frag);
1564- gtk_list_store_set (priv->history, &first,
1565- HISTORY_COL_TITLE, tmp,
1566- -1);
1567- g_free (tmp);
1568- g_free (frag);
1569- }
1570- else {
1571- gtk_list_store_set (priv->history, &first,
1572- HISTORY_COL_TITLE, title,
1573- -1);
1574- }
1575- g_free (title);
1576- }
1577-}
1578-
1579-static void
1580-view_page_desc (YelpView *view,
1581- GParamSpec *pspec,
1582- YelpLocationEntry *entry)
1583-{
1584- GtkTreeIter first;
1585- gchar *desc;
1586- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1587-
1588- g_object_get (view, "page-desc", &desc, NULL);
1589- if (desc == NULL)
1590- return;
1591-
1592- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->history), &first))
1593- gtk_list_store_set (priv->history, &first,
1594- HISTORY_COL_DESC, desc,
1595- -1);
1596- g_free (desc);
1597-}
1598-
1599-static void
1600-view_page_icon (YelpView *view,
1601- GParamSpec *pspec,
1602- YelpLocationEntry *entry)
1603-{
1604- GtkTreeIter first;
1605- gchar *icon;
1606- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1607-
1608- g_object_get (view, "page-icon", &icon, NULL);
1609- if (icon == NULL)
1610- return;
1611-
1612- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->history), &first))
1613- gtk_list_store_set (priv->history, &first,
1614- HISTORY_COL_ICON, icon,
1615- -1);
1616- g_free (icon);
1617-}
1618-
1619-static void
1620-bookmarks_changed (YelpBookmarks *bookmarks,
1621- const gchar *doc_uri,
1622- YelpLocationEntry *entry)
1623-{
1624- GtkTreePath *path;
1625- YelpLocationEntryPrivate *priv = GET_PRIV (entry);
1626-
1627- if (priv->row)
1628- path = gtk_tree_row_reference_get_path (priv->row);
1629-
1630- if (path) {
1631- GtkTreeIter iter;
1632- gchar *this_uri, *page_id;
1633- gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->history), &iter, path);
1634- gtk_tree_model_get (GTK_TREE_MODEL (priv->history), &iter,
1635- HISTORY_COL_DOC, &this_uri,
1636- HISTORY_COL_PAGE, &page_id,
1637- -1);
1638- if (this_uri && g_str_equal (this_uri, doc_uri) && page_id) {
1639- if (!yelp_bookmarks_is_bookmarked (priv->bookmarks, doc_uri, page_id)) {
1640- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
1641- GTK_ENTRY_ICON_SECONDARY,
1642- "yelp-bookmark-add-symbolic");
1643- gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->text_entry),
1644- GTK_ENTRY_ICON_SECONDARY,
1645- _("Bookmark this page"));
1646- }
1647- else {
1648- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
1649- GTK_ENTRY_ICON_SECONDARY,
1650- "yelp-bookmark-remove-symbolic");
1651- gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->text_entry),
1652- GTK_ENTRY_ICON_SECONDARY,
1653- _("Remove bookmark"));
1654- }
1655- }
1656- else {
1657- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->text_entry),
1658- GTK_ENTRY_ICON_SECONDARY,
1659- NULL);
1660- }
1661- g_free (this_uri);
1662- g_free (page_id);
1663- }
1664-}
1665-
1666-/**
1667- * yelp_location_entry_new:
1668- * @view: A #YelpView.
1669- *
1670- * Creates a new #YelpLocationEntry widget to control @view.
1671- *
1672- * Returns: A new #YelpLocationEntry.
1673- **/
1674-GtkWidget*
1675-yelp_location_entry_new (YelpView *view,
1676- YelpBookmarks *bookmarks)
1677-{
1678- GtkWidget *ret;
1679- g_return_val_if_fail (YELP_IS_VIEW (view), NULL);
1680-
1681- ret = GTK_WIDGET (g_object_new (YELP_TYPE_LOCATION_ENTRY,
1682- "has-entry", TRUE,
1683- "view", view,
1684- "bookmarks", bookmarks,
1685- NULL));
1686-
1687- return ret;
1688-}
1689-
1690-/**
1691- * yelp_location_entry_start_search:
1692- * @entry: A #YelpLocationEntry.
1693- *
1694- * Puts @entry into search mode. This focuses the entry and clears its text
1695- * contents. When the user activates the search, the
1696- * #YelpLocationEntry::search-activated signal will be emitted.
1697- **/
1698-void
1699-yelp_location_entry_start_search (YelpLocationEntry *entry)
1700-{
1701- location_entry_start_search (entry, TRUE);
1702-}
1703
1704=== removed file '.pc/git_signal_handler.patch/libyelp/yelp-view.c'
1705--- .pc/git_signal_handler.patch/libyelp/yelp-view.c 2014-02-27 13:28:05 +0000
1706+++ .pc/git_signal_handler.patch/libyelp/yelp-view.c 1970-01-01 00:00:00 +0000
1707@@ -1,2220 +0,0 @@
1708-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
1709-/*
1710- * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
1711- *
1712- * This program is free software; you can redistribute it and/or
1713- * modify it under the terms of the GNU General Public License as
1714- * published by the Free Software Foundation; either version 2 of the
1715- * License, or (at your option) any later version.
1716- *
1717- * This program is distributed in the hope that it will be useful,
1718- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1719- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1720- * General Public License for more details.
1721- *
1722- * You should have received a copy of the GNU General Public
1723- * License along with this program; if not, write to the
1724- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1725- * Boston, MA 02111-1307, USA.
1726- *
1727- * Author: Shaun McCance <shaunm@gnome.org>
1728- */
1729-
1730-#ifdef HAVE_CONFIG_H
1731-#include <config.h>
1732-#endif
1733-
1734-#include <glib/gi18n.h>
1735-#include <glib-object.h>
1736-#include <gio/gio.h>
1737-#include <gtk/gtk.h>
1738-#include <gdk/gdkx.h>
1739-#include <webkit/webkit.h>
1740-
1741-#include "yelp-debug.h"
1742-#include "yelp-docbook-document.h"
1743-#include "yelp-error.h"
1744-#include "yelp-marshal.h"
1745-#include "yelp-settings.h"
1746-#include "yelp-types.h"
1747-#include "yelp-view.h"
1748-
1749-#define BOGUS_URI "file:///bogus/"
1750-#define BOGUS_URI_LEN 14
1751-
1752-static void yelp_view_init (YelpView *view);
1753-static void yelp_view_class_init (YelpViewClass *klass);
1754-static void yelp_view_dispose (GObject *object);
1755-static void yelp_view_finalize (GObject *object);
1756-static void yelp_view_get_property (GObject *object,
1757- guint prop_id,
1758- GValue *value,
1759- GParamSpec *pspec);
1760-static void yelp_view_set_property (GObject *object,
1761- guint prop_id,
1762- const GValue *value,
1763- GParamSpec *pspec);
1764-
1765-static gboolean view_external_uri (YelpView *view,
1766- YelpUri *uri);
1767-static void view_install_uri (YelpView *view,
1768- const gchar *uri);
1769-static void view_scrolled (GtkAdjustment *adjustment,
1770- YelpView *view);
1771-static void view_set_hadjustment (YelpView *view,
1772- GParamSpec *pspec,
1773- gpointer data);
1774-static void view_set_vadjustment (YelpView *view,
1775- GParamSpec *pspec,
1776- gpointer data);
1777-static void popup_open_link (GtkMenuItem *item,
1778- YelpView *view);
1779-static void popup_open_link_new (GtkMenuItem *item,
1780- YelpView *view);
1781-static void popup_copy_link (GtkMenuItem *item,
1782- YelpView *view);
1783-static void popup_save_image (GtkMenuItem *item,
1784- YelpView *view);
1785-static void popup_send_image (GtkMenuItem *item,
1786- YelpView *view);
1787-static void popup_copy_code (GtkMenuItem *item,
1788- YelpView *view);
1789-static void popup_save_code (GtkMenuItem *item,
1790- YelpView *view);
1791-static void view_populate_popup (YelpView *view,
1792- GtkMenu *menu,
1793- gpointer data);
1794-static void view_script_alert (YelpView *view,
1795- WebKitWebFrame *frame,
1796- gchar *message,
1797- gpointer data);
1798-static gboolean view_navigation_requested (WebKitWebView *view,
1799- WebKitWebFrame *frame,
1800- WebKitNetworkRequest *request,
1801- WebKitWebNavigationAction *action,
1802- WebKitWebPolicyDecision *decision,
1803- gpointer user_data);
1804-static void view_resource_request (WebKitWebView *view,
1805- WebKitWebFrame *frame,
1806- WebKitWebResource *resource,
1807- WebKitNetworkRequest *request,
1808- WebKitNetworkResponse *response,
1809- gpointer user_data);
1810-static void view_document_loaded (WebKitWebView *view,
1811- WebKitWebFrame *frame,
1812- gpointer user_data);
1813-
1814-static void view_print (GtkAction *action,
1815- YelpView *view);
1816-static void view_history_action (GtkAction *action,
1817- YelpView *view);
1818-static void view_navigation_action (GtkAction *action,
1819- YelpView *view);
1820-
1821-static void view_clear_load (YelpView *view);
1822-static void view_load_page (YelpView *view);
1823-static void view_show_error_page (YelpView *view,
1824- GError *error);
1825-
1826-static void settings_set_fonts (YelpSettings *settings);
1827-static void settings_show_text_cursor (YelpSettings *settings);
1828-
1829-static void uri_resolved (YelpUri *uri,
1830- YelpView *view);
1831-static void document_callback (YelpDocument *document,
1832- YelpDocumentSignal signal,
1833- YelpView *view,
1834- GError *error);
1835-
1836-static const GtkActionEntry entries[] = {
1837- {"YelpViewPrint", GTK_STOCK_PRINT,
1838- N_("_Print..."),
1839- "<Control>P",
1840- NULL,
1841- G_CALLBACK (view_print) },
1842- {"YelpViewGoBack", GTK_STOCK_GO_BACK,
1843- N_("_Back"),
1844- "<Alt>Left",
1845- NULL,
1846- G_CALLBACK (view_history_action) },
1847- {"YelpViewGoForward", GTK_STOCK_GO_FORWARD,
1848- N_("_Forward"),
1849- "<Alt>Right",
1850- NULL,
1851- G_CALLBACK (view_history_action) },
1852- {"YelpViewGoPrevious", NULL,
1853- N_("_Previous Page"),
1854- "<Control>Page_Up",
1855- NULL,
1856- G_CALLBACK (view_navigation_action) },
1857- {"YelpViewGoNext", NULL,
1858- N_("_Next Page"),
1859- "<Control>Page_Down",
1860- NULL,
1861- G_CALLBACK (view_navigation_action) }
1862-};
1863-
1864-static gchar *nautilus_sendto = NULL;
1865-
1866-enum {
1867- PROP_0,
1868- PROP_URI,
1869- PROP_STATE,
1870- PROP_PAGE_ID,
1871- PROP_ROOT_TITLE,
1872- PROP_PAGE_TITLE,
1873- PROP_PAGE_DESC,
1874- PROP_PAGE_ICON
1875-};
1876-
1877-enum {
1878- NEW_VIEW_REQUESTED,
1879- EXTERNAL_URI,
1880- LOADED,
1881- LAST_SIGNAL
1882-};
1883-static gint signals[LAST_SIGNAL] = { 0 };
1884-
1885-G_DEFINE_TYPE (YelpView, yelp_view, WEBKIT_TYPE_WEB_VIEW);
1886-#define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_VIEW, YelpViewPrivate))
1887-
1888-static WebKitWebSettings *websettings;
1889-
1890-typedef struct _YelpActionEntry YelpActionEntry;
1891-struct _YelpActionEntry {
1892- GtkAction *action;
1893- YelpViewActionValidFunc func;
1894- gpointer data;
1895-};
1896-static void
1897-action_entry_free (YelpActionEntry *entry)
1898-{
1899- if (entry == NULL)
1900- return;
1901- g_object_unref (entry->action);
1902- g_free (entry);
1903-}
1904-
1905-typedef struct _YelpBackEntry YelpBackEntry;
1906-struct _YelpBackEntry {
1907- YelpUri *uri;
1908- gchar *title;
1909- gchar *desc;
1910- gdouble hadj;
1911- gdouble vadj;
1912-};
1913-static void
1914-back_entry_free (YelpBackEntry *back)
1915-{
1916- if (back == NULL)
1917- return;
1918- g_object_unref (back->uri);
1919- g_free (back->title);
1920- g_free (back->desc);
1921- g_free (back);
1922-}
1923-
1924-typedef struct _YelpViewPrivate YelpViewPrivate;
1925-struct _YelpViewPrivate {
1926- YelpUri *uri;
1927- YelpUri *resolve_uri;
1928- gulong uri_resolved;
1929- gchar *bogus_uri;
1930- YelpDocument *document;
1931- GCancellable *cancellable;
1932- GtkAdjustment *vadjustment;
1933- GtkAdjustment *hadjustment;
1934- gdouble vadjust;
1935- gdouble hadjust;
1936- gulong vadjuster;
1937- gulong hadjuster;
1938-
1939- gchar *popup_link_uri;
1940- gchar *popup_link_text;
1941- gchar *popup_image_uri;
1942- WebKitDOMNode *popup_code_node;
1943- WebKitDOMNode *popup_code_title;
1944- gchar *popup_code_text;
1945-
1946- YelpViewState state;
1947- YelpViewState prevstate;
1948-
1949- gchar *page_id;
1950- gchar *root_title;
1951- gchar *page_title;
1952- gchar *page_desc;
1953- gchar *page_icon;
1954-
1955- GList *back_list;
1956- GList *back_cur;
1957- gboolean back_load;
1958-
1959- GtkActionGroup *action_group;
1960-
1961- GSList *link_actions;
1962-
1963- gint navigation_requested;
1964-};
1965-
1966-#define TARGET_TYPE_URI_LIST "text/uri-list"
1967-enum {
1968- TARGET_URI_LIST
1969-};
1970-
1971-static void
1972-yelp_view_init (YelpView *view)
1973-{
1974- GtkAction *action;
1975- YelpViewPrivate *priv = GET_PRIV (view);
1976-
1977- g_object_set (view, "settings", websettings, NULL);
1978-
1979- priv->cancellable = NULL;
1980-
1981- priv->prevstate = priv->state = YELP_VIEW_STATE_BLANK;
1982-
1983- priv->navigation_requested =
1984- g_signal_connect (view, "navigation-policy-decision-requested",
1985- G_CALLBACK (view_navigation_requested), NULL);
1986- g_signal_connect (view, "resource-request-starting",
1987- G_CALLBACK (view_resource_request), NULL);
1988- g_signal_connect (view, "document-load-finished",
1989- G_CALLBACK (view_document_loaded), NULL);
1990- g_signal_connect (view, "notify::hadjustment",
1991- G_CALLBACK (view_set_hadjustment), NULL);
1992- g_signal_connect (view, "notify::vadjustment",
1993- G_CALLBACK (view_set_vadjustment), NULL);
1994- g_signal_connect (view, "populate-popup",
1995- G_CALLBACK (view_populate_popup), NULL);
1996- g_signal_connect (view, "script-alert",
1997- G_CALLBACK (view_script_alert), NULL);
1998-
1999- priv->action_group = gtk_action_group_new ("YelpView");
2000- gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE);
2001- gtk_action_group_add_actions (priv->action_group,
2002- entries, G_N_ELEMENTS (entries),
2003- view);
2004- action = gtk_action_group_get_action (priv->action_group, "YelpViewGoBack");
2005- gtk_action_set_sensitive (action, FALSE);
2006- action = gtk_action_group_get_action (priv->action_group, "YelpViewGoForward");
2007- gtk_action_set_sensitive (action, FALSE);
2008-}
2009-
2010-static void
2011-yelp_view_dispose (GObject *object)
2012-{
2013- YelpViewPrivate *priv = GET_PRIV (object);
2014-
2015- view_clear_load (YELP_VIEW (object));
2016-
2017- if (priv->vadjuster > 0) {
2018- g_source_remove (priv->vadjuster);
2019- priv->vadjuster = 0;
2020- }
2021-
2022- if (priv->hadjuster > 0) {
2023- g_source_remove (priv->hadjuster);
2024- priv->hadjuster = 0;
2025- }
2026-
2027- if (priv->action_group) {
2028- g_object_unref (priv->action_group);
2029- priv->action_group = NULL;
2030- }
2031-
2032- if (priv->document) {
2033- g_object_unref (priv->document);
2034- priv->document = NULL;
2035- }
2036-
2037- while (priv->link_actions) {
2038- action_entry_free (priv->link_actions->data);
2039- priv->link_actions = g_slist_delete_link (priv->link_actions, priv->link_actions);
2040- }
2041-
2042- priv->back_cur = NULL;
2043- while (priv->back_list) {
2044- back_entry_free ((YelpBackEntry *) priv->back_list->data);
2045- priv->back_list = g_list_delete_link (priv->back_list, priv->back_list);
2046- }
2047-
2048- G_OBJECT_CLASS (yelp_view_parent_class)->dispose (object);
2049-}
2050-
2051-static void
2052-yelp_view_finalize (GObject *object)
2053-{
2054- YelpViewPrivate *priv = GET_PRIV (object);
2055-
2056- g_free (priv->popup_link_uri);
2057- g_free (priv->popup_link_text);
2058- g_free (priv->popup_image_uri);
2059- g_free (priv->popup_code_text);
2060-
2061- g_free (priv->page_id);
2062- g_free (priv->root_title);
2063- g_free (priv->page_title);
2064- g_free (priv->page_desc);
2065- g_free (priv->page_icon);
2066-
2067- g_free (priv->bogus_uri);
2068-
2069- G_OBJECT_CLASS (yelp_view_parent_class)->finalize (object);
2070-}
2071-
2072-static void
2073-yelp_view_class_init (YelpViewClass *klass)
2074-{
2075- GObjectClass *object_class = G_OBJECT_CLASS (klass);
2076- YelpSettings *settings = yelp_settings_get_default ();
2077-
2078- nautilus_sendto = g_find_program_in_path ("nautilus-sendto");
2079-
2080- websettings = webkit_web_settings_new ();
2081- g_object_set (websettings, "enable-universal-access-from-file-uris", TRUE, NULL);
2082- g_signal_connect (settings,
2083- "fonts-changed",
2084- G_CALLBACK (settings_set_fonts),
2085- NULL);
2086- settings_set_fonts (settings);
2087- g_signal_connect (settings,
2088- "notify::show-text-cursor",
2089- G_CALLBACK (settings_show_text_cursor),
2090- NULL);
2091- settings_show_text_cursor (settings);
2092-
2093- klass->external_uri = view_external_uri;
2094-
2095- object_class->dispose = yelp_view_dispose;
2096- object_class->finalize = yelp_view_finalize;
2097- object_class->get_property = yelp_view_get_property;
2098- object_class->set_property = yelp_view_set_property;
2099-
2100- signals[NEW_VIEW_REQUESTED] =
2101- g_signal_new ("new-view-requested",
2102- G_TYPE_FROM_CLASS (klass),
2103- G_SIGNAL_RUN_LAST,
2104- 0, NULL, NULL,
2105- g_cclosure_marshal_VOID__OBJECT,
2106- G_TYPE_NONE, 1, YELP_TYPE_URI);
2107-
2108- signals[EXTERNAL_URI] =
2109- g_signal_new ("external-uri",
2110- G_TYPE_FROM_CLASS (klass),
2111- G_SIGNAL_RUN_LAST,
2112- G_STRUCT_OFFSET (YelpViewClass, external_uri),
2113- g_signal_accumulator_true_handled, NULL,
2114- yelp_marshal_BOOLEAN__OBJECT,
2115- G_TYPE_BOOLEAN, 1, YELP_TYPE_URI);
2116-
2117- signals[LOADED] =
2118- g_signal_new ("loaded",
2119- G_TYPE_FROM_CLASS (klass),
2120- G_SIGNAL_RUN_LAST,
2121- 0, NULL, NULL,
2122- g_cclosure_marshal_VOID__VOID,
2123- G_TYPE_NONE, 0);
2124-
2125- g_type_class_add_private (klass, sizeof (YelpViewPrivate));
2126-
2127- g_object_class_install_property (object_class,
2128- PROP_URI,
2129- g_param_spec_object ("yelp-uri",
2130- _("Yelp URI"),
2131- _("A YelpUri with the current location"),
2132- YELP_TYPE_URI,
2133- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
2134- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2135-
2136- g_object_class_install_property (object_class,
2137- PROP_STATE,
2138- g_param_spec_enum ("state",
2139- N_("Loading State"),
2140- N_("The loading state of the view"),
2141- YELP_TYPE_VIEW_STATE,
2142- YELP_VIEW_STATE_BLANK,
2143- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
2144- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2145-
2146- g_object_class_install_property (object_class,
2147- PROP_PAGE_ID,
2148- g_param_spec_string ("page-id",
2149- N_("Page ID"),
2150- N_("The ID of the root page of the page being viewed"),
2151- NULL,
2152- G_PARAM_READABLE |
2153- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2154-
2155- g_object_class_install_property (object_class,
2156- PROP_ROOT_TITLE,
2157- g_param_spec_string ("root-title",
2158- N_("Root Title"),
2159- N_("The title of the root page of the page being viewed"),
2160- NULL,
2161- G_PARAM_READABLE |
2162- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2163-
2164- g_object_class_install_property (object_class,
2165- PROP_PAGE_TITLE,
2166- g_param_spec_string ("page-title",
2167- N_("Page Title"),
2168- N_("The title of the page being viewed"),
2169- NULL,
2170- G_PARAM_READABLE |
2171- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2172-
2173- g_object_class_install_property (object_class,
2174- PROP_PAGE_DESC,
2175- g_param_spec_string ("page-desc",
2176- N_("Page Description"),
2177- N_("The description of the page being viewed"),
2178- NULL,
2179- G_PARAM_READABLE |
2180- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2181-
2182- g_object_class_install_property (object_class,
2183- PROP_PAGE_ICON,
2184- g_param_spec_string ("page-icon",
2185- N_("Page Icon"),
2186- N_("The icon of the page being viewed"),
2187- NULL,
2188- G_PARAM_READABLE |
2189- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2190-}
2191-
2192-static void
2193-yelp_view_get_property (GObject *object,
2194- guint prop_id,
2195- GValue *value,
2196- GParamSpec *pspec)
2197-{
2198- YelpViewPrivate *priv = GET_PRIV (object);
2199-
2200- switch (prop_id)
2201- {
2202- case PROP_URI:
2203- g_value_set_object (value, priv->uri);
2204- break;
2205- case PROP_PAGE_ID:
2206- g_value_set_string (value, priv->page_id);
2207- break;
2208- case PROP_ROOT_TITLE:
2209- g_value_set_string (value, priv->root_title);
2210- break;
2211- case PROP_PAGE_TITLE:
2212- g_value_set_string (value, priv->page_title);
2213- break;
2214- case PROP_PAGE_DESC:
2215- g_value_set_string (value, priv->page_desc);
2216- break;
2217- case PROP_PAGE_ICON:
2218- if (priv->page_icon)
2219- g_value_set_string (value, priv->page_icon);
2220- else
2221- g_value_set_string (value, "yelp-page-symbolic");
2222- break;
2223- case PROP_STATE:
2224- g_value_set_enum (value, priv->state);
2225- break;
2226- default:
2227- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2228- break;
2229- }
2230-}
2231-
2232-static void
2233-yelp_view_set_property (GObject *object,
2234- guint prop_id,
2235- const GValue *value,
2236- GParamSpec *pspec)
2237-{
2238- YelpUri *uri;
2239- YelpViewPrivate *priv = GET_PRIV (object);
2240-
2241- switch (prop_id)
2242- {
2243- case PROP_URI:
2244- uri = g_value_get_object (value);
2245- yelp_view_load_uri (YELP_VIEW (object), uri);
2246- g_object_unref (uri);
2247- break;
2248- case PROP_STATE:
2249- priv->prevstate = priv->state;
2250- priv->state = g_value_get_enum (value);
2251- break;
2252- default:
2253- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2254- break;
2255- }
2256-}
2257-
2258-/******************************************************************************/
2259-
2260-GtkWidget *
2261-yelp_view_new (void)
2262-{
2263- return (GtkWidget *) g_object_new (YELP_TYPE_VIEW, NULL);
2264-}
2265-
2266-void
2267-yelp_view_load (YelpView *view,
2268- const gchar *uri)
2269-{
2270- YelpUri *yuri = yelp_uri_new (uri);
2271- yelp_view_load_uri (view, yuri);
2272- g_object_unref (yuri);
2273-}
2274-
2275-void
2276-yelp_view_load_uri (YelpView *view,
2277- YelpUri *uri)
2278-{
2279- YelpViewPrivate *priv = GET_PRIV (view);
2280-
2281- g_object_set (view, "state", YELP_VIEW_STATE_LOADING, NULL);
2282-
2283- gtk_action_set_sensitive (gtk_action_group_get_action (priv->action_group,
2284- "YelpViewGoPrevious"),
2285- FALSE);
2286- gtk_action_set_sensitive (gtk_action_group_get_action (priv->action_group,
2287- "YelpViewGoNext"),
2288- FALSE);
2289-
2290- if (!yelp_uri_is_resolved (uri)) {
2291- if (priv->resolve_uri != NULL) {
2292- if (priv->uri_resolved != 0) {
2293- g_signal_handler_disconnect (priv->resolve_uri, priv->uri_resolved);
2294- priv->uri_resolved = 0;
2295- }
2296- g_object_unref (priv->resolve_uri);
2297- }
2298- priv->resolve_uri = g_object_ref (uri);
2299- priv->uri_resolved = g_signal_connect (uri, "resolved",
2300- G_CALLBACK (uri_resolved),
2301- view);
2302- yelp_uri_resolve (uri);
2303- }
2304- else {
2305- uri_resolved (uri, view);
2306- }
2307-}
2308-
2309-void
2310-yelp_view_load_document (YelpView *view,
2311- YelpUri *uri,
2312- YelpDocument *document)
2313-{
2314- GParamSpec *spec;
2315- YelpViewPrivate *priv = GET_PRIV (view);
2316-
2317- g_return_if_fail (yelp_uri_is_resolved (uri));
2318-
2319- g_object_set (view, "state", YELP_VIEW_STATE_LOADING, NULL);
2320-
2321- g_object_ref (uri);
2322- view_clear_load (view);
2323- priv->uri = uri;
2324- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
2325- "yelp-uri");
2326- g_signal_emit_by_name (view, "notify::yelp-uri", spec);
2327- g_object_ref (document);
2328- if (priv->document)
2329- g_object_unref (document);
2330- priv->document = document;
2331-
2332- view_load_page (view);
2333-}
2334-
2335-YelpDocument *
2336-yelp_view_get_document (YelpView *view)
2337-{
2338- YelpViewPrivate *priv = GET_PRIV (view);
2339- return priv->document;
2340-}
2341-
2342-GtkActionGroup *
2343-yelp_view_get_action_group (YelpView *view)
2344-{
2345- YelpViewPrivate *priv = GET_PRIV (view);
2346- return priv->action_group;
2347-}
2348-
2349-/******************************************************************************/
2350-
2351-void
2352-yelp_view_add_link_action (YelpView *view,
2353- GtkAction *action,
2354- YelpViewActionValidFunc func,
2355- gpointer data)
2356-{
2357- YelpActionEntry *entry;
2358- YelpViewPrivate *priv = GET_PRIV (view);
2359-
2360- entry = g_new0 (YelpActionEntry, 1);
2361- entry->action = g_object_ref (action);
2362- entry->func = func;
2363- entry->data = data;
2364-
2365- priv->link_actions = g_slist_append (priv->link_actions, entry);
2366-}
2367-
2368-YelpUri *
2369-yelp_view_get_active_link_uri (YelpView *view)
2370-{
2371- YelpViewPrivate *priv = GET_PRIV (view);
2372- YelpUri *uri;
2373-
2374- if (g_str_has_prefix (priv->popup_link_uri, BOGUS_URI))
2375- uri = yelp_uri_new_relative (priv->uri, priv->popup_link_uri + BOGUS_URI_LEN);
2376- else
2377- uri = yelp_uri_new_relative (priv->uri, priv->popup_link_uri);
2378-
2379- return uri;
2380-}
2381-
2382-gchar *
2383-yelp_view_get_active_link_text (YelpView *view)
2384-{
2385- YelpViewPrivate *priv = GET_PRIV (view);
2386- return g_strdup (priv->popup_link_text);
2387-}
2388-
2389-/******************************************************************************/
2390-
2391-static gboolean
2392-view_external_uri (YelpView *view,
2393- YelpUri *uri)
2394-{
2395- gchar *struri = yelp_uri_get_canonical_uri (uri);
2396- g_app_info_launch_default_for_uri (struri, NULL, NULL);
2397- g_free (struri);
2398- return TRUE;
2399-}
2400-
2401-typedef struct _YelpInstallInfo YelpInstallInfo;
2402-struct _YelpInstallInfo {
2403- YelpView *view;
2404- gchar *uri;
2405-};
2406-
2407-static void
2408-yelp_install_info_free (YelpInstallInfo *info)
2409-{
2410- g_object_unref (info->view);
2411- if (info->uri)
2412- g_free (info->uri);
2413- g_free (info);
2414-}
2415-
2416-static void
2417-view_install_installed (GDBusConnection *connection,
2418- GAsyncResult *res,
2419- YelpInstallInfo *info)
2420-{
2421- GError *error = NULL;
2422- g_dbus_connection_call_finish (connection, res, &error);
2423- if (error) {
2424- const gchar *err = NULL;
2425- if (error->domain == G_DBUS_ERROR) {
2426- if (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN)
2427- err = _("You do not have PackageKit. Package install links require PackageKit.");
2428- else
2429- err = error->message;
2430- }
2431- if (err != NULL) {
2432- GtkWidget *dialog = gtk_message_dialog_new (NULL, 0,
2433- GTK_MESSAGE_ERROR,
2434- GTK_BUTTONS_CLOSE,
2435- "%s", err);
2436- gtk_dialog_run ((GtkDialog *) dialog);
2437- gtk_widget_destroy (dialog);
2438- }
2439- g_error_free (error);
2440- }
2441- else if (info->uri) {
2442- gchar *struri, *docuri;
2443- YelpViewPrivate *priv = GET_PRIV (info->view);
2444- docuri = yelp_uri_get_document_uri (priv->uri);
2445- if (g_str_equal (docuri, info->uri)) {
2446- struri = yelp_uri_get_canonical_uri (priv->uri);
2447- yelp_view_load (info->view, struri);
2448- g_free (struri);
2449- }
2450- g_free (docuri);
2451- }
2452-
2453- yelp_install_info_free (info);
2454-}
2455-
2456-static void
2457-view_install_uri (YelpView *view,
2458- const gchar *uri)
2459-{
2460- GDBusConnection *connection;
2461- GError *error;
2462- gboolean help = FALSE, ghelp = FALSE;
2463- GVariantBuilder *strv;
2464- YelpInstallInfo *info;
2465- guint32 xid = 0;
2466- YelpViewPrivate *priv = GET_PRIV (view);
2467- GtkWidget *gtkwin;
2468- GdkWindow *gdkwin;
2469- /* do not free */
2470- gchar *pkg, *confirm_search;
2471-
2472- if (g_str_has_prefix (uri, "install-help:")) {
2473- help = TRUE;
2474- pkg = (gchar *) uri + 13;
2475- }
2476- else if (g_str_has_prefix (uri, "install-ghelp:")) {
2477- ghelp = TRUE;
2478- pkg = (gchar *) uri + 14;
2479- }
2480- else if (g_str_has_prefix (uri, "install:")) {
2481- pkg = (gchar *) uri + 8;
2482- }
2483-
2484- connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
2485- if (connection == NULL) {
2486- g_warning ("Unable to connect to dbus: %s", error->message);
2487- g_error_free (error);
2488- return;
2489- }
2490-
2491- info = g_new0 (YelpInstallInfo, 1);
2492- info->view = g_object_ref (view);
2493-
2494- gtkwin = gtk_widget_get_toplevel (GTK_WIDGET (view));
2495- if (gtkwin != NULL && gtk_widget_is_toplevel (gtkwin)) {
2496- gdkwin = gtk_widget_get_window (gtkwin);
2497- if (gdkwin != NULL)
2498- xid = gdk_x11_window_get_xid (gdkwin);
2499- }
2500-
2501- if (priv->state == YELP_VIEW_STATE_ERROR)
2502- confirm_search = "hide-confirm-search";
2503- else
2504- confirm_search = "";
2505-
2506- if (help || ghelp) {
2507- const gchar * const *datadirs = g_get_system_data_dirs ();
2508- gint datadirs_i;
2509- gchar *docbook, *fname;
2510- docbook = g_strconcat (pkg, ".xml", NULL);
2511- strv = g_variant_builder_new (G_VARIANT_TYPE ("as"));
2512- for (datadirs_i = 0; datadirs[datadirs_i] != NULL; datadirs_i++) {
2513- if (ghelp) {
2514- fname = g_build_filename (datadirs[datadirs_i], "gnome", "help",
2515- pkg, "C", "index.page", NULL);
2516- g_variant_builder_add (strv, "s", fname);
2517- g_free (fname);
2518- fname = g_build_filename (datadirs[datadirs_i], "gnome", "help",
2519- pkg, "C", docbook, NULL);
2520- g_variant_builder_add (strv, "s", fname);
2521- g_free (fname);
2522- }
2523- else {
2524- fname = g_build_filename (datadirs[datadirs_i], "help", "C",
2525- pkg, "index.page", NULL);
2526- g_variant_builder_add (strv, "s", fname);
2527- g_free (fname);
2528- fname = g_build_filename (datadirs[datadirs_i], "help", "C",
2529- pkg, "index.docbook", NULL);
2530- g_variant_builder_add (strv, "s", fname);
2531- g_free (fname);
2532- }
2533- }
2534- g_free (docbook);
2535- info->uri = g_strconcat (ghelp ? "ghelp:" : "help:", pkg, NULL);
2536- g_dbus_connection_call (connection,
2537- "org.freedesktop.PackageKit",
2538- "/org/freedesktop/PackageKit",
2539- "org.freedesktop.PackageKit.Modify",
2540- "InstallProvideFiles",
2541- g_variant_new ("(uass)", xid, strv, confirm_search),
2542- NULL,
2543- G_DBUS_CALL_FLAGS_NONE,
2544- G_MAXINT, NULL,
2545- (GAsyncReadyCallback) view_install_installed,
2546- info);
2547- g_variant_builder_unref (strv);
2548- }
2549- else {
2550- gchar **pkgs;
2551- gint i;
2552- strv = g_variant_builder_new (G_VARIANT_TYPE ("as"));
2553- pkgs = g_strsplit (pkg, ",", 0);
2554- for (i = 0; pkgs[i]; i++)
2555- g_variant_builder_add (strv, "s", pkgs[i]);
2556- g_strfreev (pkgs);
2557- g_dbus_connection_call (connection,
2558- "org.freedesktop.PackageKit",
2559- "/org/freedesktop/PackageKit",
2560- "org.freedesktop.PackageKit.Modify",
2561- "InstallPackageNames",
2562- g_variant_new ("(uass)", xid, strv, confirm_search),
2563- NULL,
2564- G_DBUS_CALL_FLAGS_NONE,
2565- G_MAXINT, NULL,
2566- (GAsyncReadyCallback) view_install_installed,
2567- info);
2568- g_variant_builder_unref (strv);
2569- }
2570-
2571- g_object_unref (connection);
2572-}
2573-
2574-static void
2575-view_scrolled (GtkAdjustment *adjustment,
2576- YelpView *view)
2577-{
2578- YelpViewPrivate *priv = GET_PRIV (view);
2579- if (priv->back_cur == NULL || priv->back_cur->data == NULL)
2580- return;
2581- if (adjustment == priv->vadjustment)
2582- ((YelpBackEntry *) priv->back_cur->data)->vadj = gtk_adjustment_get_value (adjustment);
2583- else if (adjustment = priv->hadjustment)
2584- ((YelpBackEntry *) priv->back_cur->data)->hadj = gtk_adjustment_get_value (adjustment);
2585-}
2586-
2587-static void
2588-view_set_hadjustment (YelpView *view,
2589- GParamSpec *pspec,
2590- gpointer data)
2591-{
2592- YelpViewPrivate *priv = GET_PRIV (view);
2593- priv->hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (view));
2594- if (priv->hadjuster > 0)
2595- g_source_remove (priv->hadjuster);
2596- priv->hadjuster = 0;
2597- if (priv->hadjustment)
2598- priv->hadjuster = g_signal_connect (priv->hadjustment, "value-changed",
2599- G_CALLBACK (view_scrolled), view);
2600-}
2601-
2602-static void
2603-view_set_vadjustment (YelpView *view,
2604- GParamSpec *pspec,
2605- gpointer data)
2606-{
2607- YelpViewPrivate *priv = GET_PRIV (view);
2608- priv->vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (view));
2609- if (priv->vadjuster > 0)
2610- g_source_remove (priv->vadjuster);
2611- priv->vadjuster = 0;
2612- if (priv->vadjustment)
2613- priv->vadjuster = g_signal_connect (priv->vadjustment, "value-changed",
2614- G_CALLBACK (view_scrolled), view);
2615-}
2616-
2617-static void
2618-popup_open_link (GtkMenuItem *item,
2619- YelpView *view)
2620-{
2621- YelpViewPrivate *priv = GET_PRIV (view);
2622- YelpUri *uri;
2623-
2624- if (g_str_has_prefix (priv->popup_link_uri, BOGUS_URI))
2625- uri = yelp_uri_new_relative (priv->uri, priv->popup_link_uri + BOGUS_URI_LEN);
2626- else
2627- uri = yelp_uri_new_relative (priv->uri, priv->popup_link_uri);
2628-
2629- yelp_view_load_uri (view, uri);
2630- g_object_unref (uri);
2631-
2632- g_free (priv->popup_link_uri);
2633- priv->popup_link_uri = NULL;
2634-
2635- g_free (priv->popup_link_text);
2636- priv->popup_link_text = NULL;
2637-}
2638-
2639-static void
2640-popup_open_link_new (GtkMenuItem *item,
2641- YelpView *view)
2642-{
2643- YelpViewPrivate *priv = GET_PRIV (view);
2644- YelpUri *uri;
2645-
2646- if (g_str_has_prefix (priv->popup_link_uri, BOGUS_URI))
2647- uri = yelp_uri_new_relative (priv->uri, priv->popup_link_uri + BOGUS_URI_LEN);
2648- else
2649- uri = yelp_uri_new_relative (priv->uri, priv->popup_link_uri);
2650-
2651- g_free (priv->popup_link_uri);
2652- priv->popup_link_uri = NULL;
2653-
2654- g_free (priv->popup_link_text);
2655- priv->popup_link_text = NULL;
2656-
2657- g_signal_emit (view, signals[NEW_VIEW_REQUESTED], 0, uri);
2658- g_object_unref (uri);
2659-}
2660-
2661-static void
2662-popup_copy_link (GtkMenuItem *item,
2663- YelpView *view)
2664-{
2665- YelpViewPrivate *priv = GET_PRIV (view);
2666- gtk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (view), GDK_SELECTION_CLIPBOARD),
2667- priv->popup_link_uri,
2668- -1);
2669-}
2670-
2671-typedef struct _YelpSaveData YelpSaveData;
2672-struct _YelpSaveData {
2673- GFile *orig;
2674- GFile *dest;
2675- YelpView *view;
2676- GtkWindow *window;
2677-};
2678-
2679-static void
2680-file_copied (GFile *file,
2681- GAsyncResult *res,
2682- YelpSaveData *data)
2683-{
2684- GError *error = NULL;
2685- if (!g_file_copy_finish (file, res, &error)) {
2686- GtkWidget *dialog = gtk_message_dialog_new (gtk_widget_get_visible (GTK_WIDGET (data->window)) ? data->window : NULL,
2687- GTK_DIALOG_DESTROY_WITH_PARENT,
2688- GTK_MESSAGE_ERROR,
2689- GTK_BUTTONS_OK,
2690- "%s", error->message);
2691- gtk_dialog_run (GTK_DIALOG (dialog));
2692- gtk_widget_destroy (dialog);
2693- }
2694- g_object_unref (data->orig);
2695- g_object_unref (data->dest);
2696- g_object_unref (data->view);
2697- g_object_unref (data->window);
2698-}
2699-
2700-static void
2701-popup_save_image (GtkMenuItem *item,
2702- YelpView *view)
2703-{
2704- YelpSaveData *data;
2705- GtkWidget *dialog, *window;
2706- gchar *basename;
2707- gint res;
2708- YelpViewPrivate *priv = GET_PRIV (view);
2709-
2710- for (window = gtk_widget_get_parent (GTK_WIDGET (view));
2711- window && !GTK_IS_WINDOW (window);
2712- window = gtk_widget_get_parent (window));
2713-
2714- data = g_new0 (YelpSaveData, 1);
2715- data->orig = g_file_new_for_uri (priv->popup_image_uri);
2716- data->view = g_object_ref (view);
2717- data->window = g_object_ref (window);
2718- g_free (priv->popup_image_uri);
2719- priv->popup_image_uri = NULL;
2720-
2721- dialog = gtk_file_chooser_dialog_new (_("Save Image"),
2722- GTK_WINDOW (window),
2723- GTK_FILE_CHOOSER_ACTION_SAVE,
2724- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2725- GTK_STOCK_SAVE, GTK_RESPONSE_OK,
2726- NULL);
2727- gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
2728- basename = g_file_get_basename (data->orig);
2729- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
2730- g_free (basename);
2731- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
2732- g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
2733-
2734- res = gtk_dialog_run (GTK_DIALOG (dialog));
2735-
2736- if (res == GTK_RESPONSE_OK) {
2737- data->dest = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
2738- g_file_copy_async (data->orig, data->dest,
2739- G_FILE_COPY_OVERWRITE,
2740- G_PRIORITY_DEFAULT,
2741- NULL, NULL, NULL,
2742- (GAsyncReadyCallback) file_copied,
2743- data);
2744- }
2745- else {
2746- g_object_unref (data->orig);
2747- g_object_unref (data->view);
2748- g_object_unref (data->window);
2749- g_free (data);
2750- }
2751-
2752- gtk_widget_destroy (dialog);
2753-}
2754-
2755-static void
2756-popup_send_image (GtkMenuItem *item,
2757- YelpView *view)
2758-{
2759- gchar *command;
2760- GAppInfo *app;
2761- GAppLaunchContext *context;
2762- GError *error = NULL;
2763- YelpViewPrivate *priv = GET_PRIV (view);
2764-
2765- command = g_strdup_printf ("%s %s", nautilus_sendto, priv->popup_image_uri);
2766- context = (GAppLaunchContext *) gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (item)));
2767-
2768- app = g_app_info_create_from_commandline (command, NULL, 0, &error);
2769- if (app) {
2770- g_app_info_launch (app, NULL, context, &error);
2771- g_object_unref (app);
2772- }
2773-
2774- if (error) {
2775- g_debug ("Could not launch nautilus-sendto: %s", error->message);
2776- g_error_free (error);
2777- }
2778-
2779- g_object_unref (context);
2780- g_free (command);
2781- g_free (priv->popup_image_uri);
2782- priv->popup_image_uri = NULL;
2783-}
2784-
2785-static void
2786-popup_copy_code (GtkMenuItem *item,
2787- YelpView *view)
2788-{
2789- YelpViewPrivate *priv = GET_PRIV (view);
2790- GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2791- gchar *content = webkit_dom_node_get_text_content (priv->popup_code_node);
2792- gtk_clipboard_set_text (clipboard, content, -1);
2793- g_free (content);
2794-}
2795-
2796-static void
2797-popup_save_code (GtkMenuItem *item,
2798- YelpView *view)
2799-{
2800- YelpViewPrivate *priv = GET_PRIV (view);
2801- GtkWidget *dialog, *window;
2802- gint res;
2803-
2804- g_free (priv->popup_code_text);
2805- priv->popup_code_text = webkit_dom_node_get_text_content (priv->popup_code_node);
2806- if (!g_str_has_suffix (priv->popup_code_text, "\n")) {
2807- gchar *tmp = g_strconcat (priv->popup_code_text, "\n", NULL);
2808- g_free (priv->popup_code_text);
2809- priv->popup_code_text = tmp;
2810- }
2811-
2812- for (window = gtk_widget_get_parent (GTK_WIDGET (view));
2813- window && !GTK_IS_WINDOW (window);
2814- window = gtk_widget_get_parent (window));
2815-
2816- dialog = gtk_file_chooser_dialog_new (_("Save Code"),
2817- GTK_WINDOW (window),
2818- GTK_FILE_CHOOSER_ACTION_SAVE,
2819- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2820- GTK_STOCK_SAVE, GTK_RESPONSE_OK,
2821- NULL);
2822- gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
2823- if (priv->popup_code_title) {
2824- gchar *filename = webkit_dom_node_get_text_content (priv->popup_code_title);
2825- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename);
2826- g_free (filename);
2827- }
2828- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
2829- g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2830-
2831- res = gtk_dialog_run (GTK_DIALOG (dialog));
2832-
2833- if (res == GTK_RESPONSE_OK) {
2834- GError *error = NULL;
2835- GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
2836- GFileOutputStream *stream = g_file_replace (file, NULL, FALSE,
2837- G_FILE_CREATE_NONE,
2838- NULL,
2839- &error);
2840- if (stream == NULL) {
2841- GtkWidget *dialog = gtk_message_dialog_new (gtk_widget_get_visible (window) ? GTK_WINDOW (window) : NULL,
2842- GTK_DIALOG_DESTROY_WITH_PARENT,
2843- GTK_MESSAGE_ERROR,
2844- GTK_BUTTONS_OK,
2845- "%s", error->message);
2846- gtk_dialog_run (GTK_DIALOG (dialog));
2847- gtk_widget_destroy (dialog);
2848- g_error_free (error);
2849- }
2850- else {
2851- /* FIXME: we should do this async */
2852- GDataOutputStream *datastream = g_data_output_stream_new (G_OUTPUT_STREAM (stream));
2853- if (!g_data_output_stream_put_string (datastream, priv->popup_code_text, NULL, &error)) {
2854- GtkWidget *dialog = gtk_message_dialog_new (gtk_widget_get_visible (window) ? GTK_WINDOW (window) : NULL,
2855- GTK_DIALOG_DESTROY_WITH_PARENT,
2856- GTK_MESSAGE_ERROR,
2857- GTK_BUTTONS_OK,
2858- "%s", error->message);
2859- gtk_dialog_run (GTK_DIALOG (dialog));
2860- gtk_widget_destroy (dialog);
2861- g_error_free (error);
2862- }
2863- g_object_unref (datastream);
2864- }
2865- g_object_unref (file);
2866- }
2867-
2868- priv->popup_code_node = NULL;
2869- priv->popup_code_title = NULL;
2870- g_free (priv->popup_code_text);
2871- priv->popup_code_text = NULL;
2872-
2873- gtk_widget_destroy (dialog);
2874-}
2875-
2876-static void
2877-view_populate_popup (YelpView *view,
2878- GtkMenu *menu,
2879- gpointer data)
2880-{
2881- WebKitHitTestResult *result;
2882- WebKitHitTestResultContext context;
2883- GdkEvent *event;
2884- YelpViewPrivate *priv = GET_PRIV (view);
2885- GList *children;
2886- GtkWidget *item;
2887- WebKitDOMNode *node, *cur, *link_node = NULL, *code_node = NULL, *code_title_node = NULL;
2888-
2889- children = gtk_container_get_children (GTK_CONTAINER (menu));
2890- while (children) {
2891- gtk_container_remove (GTK_CONTAINER (menu),
2892- GTK_WIDGET (children->data));
2893- children = children->next;
2894- }
2895- g_list_free (children);
2896-
2897- event = gtk_get_current_event ();
2898-
2899- result = webkit_web_view_get_hit_test_result (WEBKIT_WEB_VIEW (view), (GdkEventButton *) event);
2900- g_object_get (result,
2901- "context", &context,
2902- "inner-node", &node,
2903- NULL);
2904- for (cur = node; cur != NULL; cur = webkit_dom_node_get_parent_node (cur)) {
2905- if (WEBKIT_DOM_IS_ELEMENT (cur) &&
2906- webkit_dom_element_webkit_matches_selector ((WebKitDOMElement *) cur,
2907- "a", NULL))
2908- link_node = cur;
2909-
2910- if (WEBKIT_DOM_IS_ELEMENT (cur) &&
2911- webkit_dom_element_webkit_matches_selector ((WebKitDOMElement *) cur,
2912- "div.code", NULL)) {
2913- WebKitDOMNode *title;
2914- code_node = (WebKitDOMNode *)
2915- webkit_dom_element_query_selector ((WebKitDOMElement *) cur,
2916- "pre.contents", NULL);
2917- title = webkit_dom_node_get_parent_node (cur);
2918- if (title != NULL && WEBKIT_DOM_IS_ELEMENT (title) &&
2919- webkit_dom_element_webkit_matches_selector ((WebKitDOMElement *) title,
2920- "div.contents", NULL)) {
2921- title = webkit_dom_node_get_previous_sibling (title);
2922- if (title != NULL && WEBKIT_DOM_IS_ELEMENT (title) &&
2923- webkit_dom_element_webkit_matches_selector ((WebKitDOMElement *) title,
2924- "div.title", NULL)) {
2925- code_title_node = title;
2926- }
2927- }
2928- }
2929- }
2930-
2931- if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) {
2932- gchar *uri;
2933- g_object_get (result, "link-uri", &uri, NULL);
2934- g_free (priv->popup_link_uri);
2935- priv->popup_link_uri = uri;
2936-
2937- g_free (priv->popup_link_text);
2938- priv->popup_link_text = NULL;
2939- if (link_node != NULL) {
2940- WebKitDOMNode *child;
2941- gchar *tmp;
2942- gint i, tmpi;
2943- gboolean ws;
2944-
2945- child = (WebKitDOMNode *)
2946- webkit_dom_element_query_selector (WEBKIT_DOM_ELEMENT (link_node),
2947- "span.title", NULL);
2948- if (child != NULL)
2949- priv->popup_link_text = webkit_dom_node_get_text_content (child);
2950-
2951- if (priv->popup_link_text == NULL)
2952- priv->popup_link_text = webkit_dom_node_get_text_content (link_node);
2953-
2954- tmp = g_new0 (gchar, strlen(priv->popup_link_text) + 1);
2955- ws = FALSE;
2956- for (i = 0, tmpi = 0; priv->popup_link_text[i] != '\0'; i++) {
2957- if (priv->popup_link_text[i] == ' ' || priv->popup_link_text[i] == '\n') {
2958- if (!ws) {
2959- tmp[tmpi] = ' ';
2960- tmpi++;
2961- ws = TRUE;
2962- }
2963- }
2964- else {
2965- tmp[tmpi] = priv->popup_link_text[i];
2966- tmpi++;
2967- ws = FALSE;
2968- }
2969- }
2970- tmp[tmpi] = '\0';
2971- g_free (priv->popup_link_text);
2972- priv->popup_link_text = tmp;
2973- }
2974- else {
2975- priv->popup_link_text = g_strdup (uri);
2976- }
2977-
2978- if (g_str_has_prefix (priv->popup_link_uri, "mailto:")) {
2979- gchar *label = g_strdup_printf (_("Send email to %s"),
2980- priv->popup_link_uri + 7);
2981- /* Not using a mnemonic because underscores are common in email
2982- * addresses, and we'd have to escape them. There doesn't seem
2983- * to be a quick GTK+ function for this. In practice, there will
2984- * probably only be one menu item for mailto link popups anyway,
2985- * so the mnemonic's not that big of a deal.
2986- */
2987- item = gtk_menu_item_new_with_label (label);
2988- g_signal_connect (item, "activate",
2989- G_CALLBACK (popup_open_link), view);
2990- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2991- g_free (label);
2992- }
2993- else if (g_str_has_prefix (priv->popup_link_uri, "install:")) {
2994- item = gtk_menu_item_new_with_mnemonic (_("_Install Packages"));
2995- g_signal_connect (item, "activate",
2996- G_CALLBACK (popup_open_link), view);
2997- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2998- }
2999- else {
3000- GSList *cur;
3001-
3002- item = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
3003- g_signal_connect (item, "activate",
3004- G_CALLBACK (popup_open_link), view);
3005- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3006-
3007- if (g_str_has_prefix (priv->popup_link_uri, "http://") ||
3008- g_str_has_prefix (priv->popup_link_uri, "https://")) {
3009- item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Location"));
3010- g_signal_connect (item, "activate",
3011- G_CALLBACK (popup_copy_link), view);
3012- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3013- }
3014- else {
3015- item = gtk_menu_item_new_with_mnemonic (_("Open Link in New _Window"));
3016- g_signal_connect (item, "activate",
3017- G_CALLBACK (popup_open_link_new), view);
3018- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3019- }
3020-
3021- for (cur = priv->link_actions; cur != NULL; cur = cur->next) {
3022- gboolean add;
3023- YelpActionEntry *entry = (YelpActionEntry *) cur->data;
3024- if (entry->func == NULL)
3025- add = TRUE;
3026- else
3027- add = (* entry->func) (view, entry->action,
3028- priv->popup_link_uri,
3029- entry->data);
3030- if (add) {
3031- item = gtk_action_create_menu_item (entry->action);
3032- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3033- }
3034- }
3035- }
3036- }
3037- else {
3038- item = gtk_action_create_menu_item (gtk_action_group_get_action (priv->action_group,
3039- "YelpViewGoBack"));
3040- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3041- item = gtk_action_create_menu_item (gtk_action_group_get_action (priv->action_group,
3042- "YelpViewGoForward"));
3043- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3044- }
3045-
3046- if ((context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE) ||
3047- (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA)) {
3048- /* This doesn't currently work for video with automatic controls,
3049- * because WebKit puts the hit test on the div with the controls.
3050- */
3051- gboolean image = context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE;
3052- gchar *uri;
3053- g_object_get (result, image ? "image-uri" : "media-uri", &uri, NULL);
3054- g_free (priv->popup_image_uri);
3055- if (g_str_has_prefix (uri, BOGUS_URI)) {
3056- priv->popup_image_uri = yelp_uri_locate_file_uri (priv->uri, uri + BOGUS_URI_LEN);
3057- g_free (uri);
3058- }
3059- else {
3060- priv->popup_image_uri = uri;
3061- }
3062-
3063- item = gtk_separator_menu_item_new ();
3064- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3065-
3066- if (image)
3067- item = gtk_menu_item_new_with_mnemonic (_("_Save Image As..."));
3068- else
3069- item = gtk_menu_item_new_with_mnemonic (_("_Save Video As..."));
3070- g_signal_connect (item, "activate",
3071- G_CALLBACK (popup_save_image), view);
3072- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3073-
3074- if (nautilus_sendto) {
3075- if (image)
3076- item = gtk_menu_item_new_with_mnemonic (_("S_end Image To..."));
3077- else
3078- item = gtk_menu_item_new_with_mnemonic (_("S_end Video To..."));
3079- g_signal_connect (item, "activate",
3080- G_CALLBACK (popup_send_image), view);
3081- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3082- }
3083- }
3084-
3085- if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION) {
3086- item = gtk_separator_menu_item_new ();
3087- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3088-
3089- item = gtk_menu_item_new_with_mnemonic (_("_Copy Text"));
3090- g_signal_connect_swapped (item, "activate",
3091- G_CALLBACK (webkit_web_view_copy_clipboard), view);
3092- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3093- }
3094-
3095- if (code_node != NULL) {
3096- item = gtk_separator_menu_item_new ();
3097- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3098-
3099- priv->popup_code_node = code_node;
3100- priv->popup_code_title = code_title_node;
3101-
3102- item = gtk_menu_item_new_with_mnemonic (_("C_opy Code Block"));
3103- g_signal_connect (item, "activate",
3104- G_CALLBACK (popup_copy_code), view);
3105- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3106-
3107- item = gtk_menu_item_new_with_mnemonic (_("Save Code _Block As..."));
3108- g_signal_connect (item, "activate",
3109- G_CALLBACK (popup_save_code), view);
3110- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3111- }
3112-
3113- g_object_unref (result);
3114- gdk_event_free (event);
3115- gtk_widget_show_all (GTK_WIDGET (menu));
3116-}
3117-
3118-static void
3119-view_script_alert (YelpView *view,
3120- WebKitWebFrame *frame,
3121- gchar *message,
3122- gpointer data)
3123-{
3124- printf ("\n\n===ALERT===\n%s\n\n", message);
3125-}
3126-
3127-static gboolean
3128-view_navigation_requested (WebKitWebView *view,
3129- WebKitWebFrame *frame,
3130- WebKitNetworkRequest *request,
3131- WebKitWebNavigationAction *action,
3132- WebKitWebPolicyDecision *decision,
3133- gpointer user_data)
3134-{
3135- const gchar *requri = webkit_network_request_get_uri (request);
3136- YelpViewPrivate *priv = GET_PRIV (view);
3137- YelpUri *uri;
3138-
3139- if (priv->bogus_uri &&
3140- g_str_has_prefix (requri, priv->bogus_uri) &&
3141- requri[strlen(priv->bogus_uri)] == '#') {
3142- gchar *tmp = g_strconcat("xref:", requri + strlen(priv->bogus_uri), NULL);
3143- uri = yelp_uri_new_relative (priv->uri, tmp);
3144- g_free (tmp);
3145- }
3146- else if (g_str_has_prefix (requri, BOGUS_URI)) {
3147- uri = yelp_uri_new_relative (priv->uri, requri + BOGUS_URI_LEN);
3148- }
3149- else
3150- uri = yelp_uri_new_relative (priv->uri, requri);
3151-
3152- webkit_web_policy_decision_ignore (decision);
3153-
3154- yelp_view_load_uri ((YelpView *) view, uri);
3155- g_object_unref (uri);
3156-
3157- return TRUE;
3158-}
3159-
3160-static void
3161-view_resource_request (WebKitWebView *view,
3162- WebKitWebFrame *frame,
3163- WebKitWebResource *resource,
3164- WebKitNetworkRequest *request,
3165- WebKitNetworkResponse *response,
3166- gpointer user_data)
3167-{
3168- YelpViewPrivate *priv = GET_PRIV (view);
3169- const gchar *requri = webkit_network_request_get_uri (request);
3170- gchar last;
3171- gchar *newpath;
3172-
3173- if (!g_str_has_prefix (requri, BOGUS_URI))
3174- return;
3175-
3176- /* We get this signal for the page itself. Ignore. */
3177- if (g_str_equal (requri, priv->bogus_uri))
3178- return;
3179-
3180- newpath = yelp_uri_locate_file_uri (priv->uri, requri + BOGUS_URI_LEN);
3181- if (newpath != NULL) {
3182- webkit_network_request_set_uri (request, newpath);
3183- g_free (newpath);
3184- }
3185- else {
3186- webkit_network_request_set_uri (request, "about:blank");
3187- }
3188-}
3189-
3190-static void
3191-view_document_loaded (WebKitWebView *view,
3192- WebKitWebFrame *frame,
3193- gpointer user_data)
3194-{
3195- YelpViewPrivate *priv = GET_PRIV (view);
3196- gchar *search_terms;
3197-
3198- search_terms = yelp_uri_get_query (priv->uri, "terms");
3199-
3200- if (search_terms) {
3201- WebKitDOMDocument *doc;
3202- WebKitDOMElement *body, *link;
3203- doc = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
3204- body = webkit_dom_document_query_selector (doc, "div.body", NULL);
3205- if (body) {
3206- gchar *tmp, *uri, *txt;
3207- link = webkit_dom_document_create_element (doc, "a", NULL);
3208- webkit_dom_element_set_attribute (link, "class", "fullsearch", NULL);
3209- tmp = g_uri_escape_string (search_terms, NULL, FALSE);
3210- uri = g_strconcat ("xref:search=", tmp, NULL);
3211- webkit_dom_element_set_attribute (link, "href", uri, NULL);
3212- g_free (tmp);
3213- g_free (uri);
3214- txt = g_strdup_printf (_("See all search results for “%s”"),
3215- search_terms);
3216- webkit_dom_node_set_text_content (WEBKIT_DOM_NODE (link), txt, NULL);
3217- g_free (txt);
3218- webkit_dom_node_insert_before (WEBKIT_DOM_NODE (body),
3219- WEBKIT_DOM_NODE (link),
3220- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
3221- NULL);
3222- }
3223- g_free (search_terms);
3224- }
3225-}
3226-
3227-static void
3228-view_print (GtkAction *action, YelpView *view)
3229-{
3230- webkit_web_frame_print (webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view)));
3231-}
3232-
3233-static void
3234-view_history_action (GtkAction *action,
3235- YelpView *view)
3236-{
3237- GList *newcur;
3238- YelpViewPrivate *priv = GET_PRIV (view);
3239-
3240- if (priv->back_cur == NULL)
3241- return;
3242-
3243- if (g_str_equal (gtk_action_get_name (action), "YelpViewGoBack"))
3244- newcur = priv->back_cur->next;
3245- else
3246- newcur = priv->back_cur->prev;
3247-
3248- if (newcur == NULL)
3249- return;
3250-
3251- priv->back_cur = newcur;
3252-
3253- if (priv->back_cur->data == NULL)
3254- return;
3255-
3256- priv->back_load = TRUE;
3257- yelp_view_load_uri (view, ((YelpBackEntry *) priv->back_cur->data)->uri);
3258- priv->vadjust = ((YelpBackEntry *) priv->back_cur->data)->vadj;
3259- priv->hadjust = ((YelpBackEntry *) priv->back_cur->data)->hadj;
3260-}
3261-
3262-static void
3263-view_navigation_action (GtkAction *action,
3264- YelpView *view)
3265-{
3266- YelpViewPrivate *priv = GET_PRIV (view);
3267- gchar *page_id, *new_id, *xref;
3268- YelpUri *new_uri;
3269-
3270- page_id = yelp_uri_get_page_id (priv->uri);
3271-
3272- if (g_str_equal (gtk_action_get_name (action), "YelpViewGoPrevious"))
3273- new_id = yelp_document_get_prev_id (priv->document, page_id);
3274- else
3275- new_id = yelp_document_get_next_id (priv->document, page_id);
3276-
3277- /* Just in case we screwed up somewhere */
3278- if (new_id == NULL) {
3279- gtk_action_set_sensitive (action, FALSE);
3280- return;
3281- }
3282-
3283- xref = g_strconcat ("xref:", new_id, NULL);
3284- new_uri = yelp_uri_new_relative (priv->uri, xref);
3285- yelp_view_load_uri (view, new_uri);
3286-
3287- g_free (xref);
3288- g_free (new_id);
3289- g_object_unref (new_uri);
3290-}
3291-
3292-static void
3293-view_clear_load (YelpView *view)
3294-{
3295- YelpViewPrivate *priv = GET_PRIV (view);
3296-
3297- if (priv->resolve_uri != NULL) {
3298- if (priv->uri_resolved != 0) {
3299- g_signal_handler_disconnect (priv->resolve_uri, priv->uri_resolved);
3300- priv->uri_resolved = 0;
3301- }
3302- g_object_unref (priv->resolve_uri);
3303- }
3304- priv->resolve_uri = NULL;
3305-
3306- if (priv->uri) {
3307- g_object_unref (priv->uri);
3308- priv->uri = NULL;
3309- }
3310-
3311- if (priv->cancellable) {
3312- g_cancellable_cancel (priv->cancellable);
3313- priv->cancellable = NULL;
3314- }
3315-}
3316-
3317-static void
3318-view_load_page (YelpView *view)
3319-{
3320- YelpViewPrivate *priv = GET_PRIV (view);
3321- gchar *page_id;
3322-
3323- debug_print (DB_FUNCTION, "entering\n");
3324-
3325- g_return_if_fail (priv->cancellable == NULL);
3326-
3327- if (priv->document == NULL) {
3328- GError *error;
3329- gchar *docuri;
3330- /* FIXME: and if priv->uri is NULL? */
3331- docuri = yelp_uri_get_document_uri (priv->uri);
3332- /* FIXME: CANT_READ isn't right */
3333- if (docuri) {
3334- error = g_error_new (YELP_ERROR, YELP_ERROR_CANT_READ,
3335- _("Could not load a document for ‘%s’"),
3336- docuri);
3337- g_free (docuri);
3338- }
3339- else {
3340- error = g_error_new (YELP_ERROR, YELP_ERROR_CANT_READ,
3341- _("Could not load a document"));
3342- }
3343- view_show_error_page (view, error);
3344- g_error_free (error);
3345- return;
3346- }
3347-
3348- page_id = yelp_uri_get_page_id (priv->uri);
3349- priv->cancellable = g_cancellable_new ();
3350- yelp_document_request_page (priv->document,
3351- page_id,
3352- priv->cancellable,
3353- (YelpDocumentCallback) document_callback,
3354- view);
3355- g_free (page_id);
3356-}
3357-
3358-static void
3359-view_show_error_page (YelpView *view,
3360- GError *error)
3361-{
3362- YelpViewPrivate *priv = GET_PRIV (view);
3363- static const gchar *errorpage =
3364- "<html><head>"
3365- "<style type='text/css'>"
3366- "body {"
3367- " margin: 1em;"
3368- " color: %s;"
3369- " background-color: %s;"
3370- " }\n"
3371- "p { margin: 1em 0 0 0; }\n"
3372- "div.note {"
3373- " padding: 6px;"
3374- " border-color: %s;"
3375- " border-top: solid 1px;"
3376- " border-bottom: solid 1px;"
3377- " background-color: %s;"
3378- " }\n"
3379- "div.note div.inner {"
3380- " margin: 0; padding: 0;"
3381- " background-image: url(%s);"
3382- " background-position: %s top;"
3383- " background-repeat: no-repeat;"
3384- " min-height: %ipx;"
3385- " }\n"
3386- "div.note div.contents {"
3387- " margin-%s: %ipx;"
3388- " }\n"
3389- "div.note div.title {"
3390- " margin-%s: %ipx;"
3391- " margin-bottom: 0.2em;"
3392- " font-weight: bold;"
3393- " color: %s;"
3394- " }\n"
3395- "a { color: %s; text-decoration: none; }\n"
3396- "</style>"
3397- "</head><body>"
3398- "<div class='note'><div class='inner'>"
3399- "%s<div class='contents'>%s%s</div>"
3400- "</div></div>"
3401- "</body></html>";
3402- YelpSettings *settings = yelp_settings_get_default ();
3403- gchar *page, *title = NULL, *link = NULL, *title_m, *content_beg, *content_end;
3404- gchar *textcolor, *bgcolor, *noteborder, *notebg, *titlecolor, *noteicon, *linkcolor;
3405- gint iconsize;
3406- GParamSpec *spec;
3407- gboolean doc404 = FALSE;
3408- const gchar *left = (gtk_widget_get_direction((GtkWidget *) view) == GTK_TEXT_DIR_RTL) ? "right" : "left";
3409-
3410- if (priv->uri && yelp_uri_get_document_type (priv->uri) == YELP_URI_DOCUMENT_TYPE_NOT_FOUND)
3411- doc404 = TRUE;
3412- if (error->domain == YELP_ERROR)
3413- switch (error->code) {
3414- case YELP_ERROR_NOT_FOUND:
3415- if (doc404)
3416- title = _("Document Not Found");
3417- else
3418- title = _("Page Not Found");
3419- break;
3420- case YELP_ERROR_CANT_READ:
3421- title = _("Cannot Read");
3422- break;
3423- default:
3424- break;
3425- }
3426- if (title == NULL)
3427- title = _("Unknown Error");
3428- title_m = g_markup_printf_escaped ("<div class='title'>%s</div>", title);
3429-
3430- content_beg = g_markup_printf_escaped ("<p>%s</p>", error->message);
3431- content_end = NULL;
3432- if (doc404) {
3433- gchar *struri = yelp_uri_get_document_uri (priv->uri);
3434- /* do not free */
3435- gchar *pkg = NULL, *scheme = NULL;
3436- if (g_str_has_prefix (struri, "help:")) {
3437- scheme = "help";
3438- pkg = struri + 5;
3439- }
3440- else if (g_str_has_prefix (struri, "ghelp:")) {
3441- scheme = "ghelp";
3442- pkg = struri + 6;
3443- }
3444- g_free (struri);
3445- }
3446-
3447- textcolor = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_TEXT);
3448- bgcolor = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_BASE);
3449- noteborder = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_RED_BORDER);
3450- notebg = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_YELLOW_BASE);
3451- titlecolor = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_TEXT_LIGHT);
3452- linkcolor = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_LINK);
3453- noteicon = yelp_settings_get_icon (settings, YELP_SETTINGS_ICON_WARNING);
3454- iconsize = yelp_settings_get_icon_size (settings) + 6;
3455-
3456- page = g_strdup_printf (errorpage,
3457- textcolor, bgcolor, noteborder, notebg, noteicon,
3458- left, iconsize, left, iconsize, left, iconsize,
3459- titlecolor, linkcolor, title_m, content_beg,
3460- (content_end != NULL) ? content_end : "");
3461-
3462- g_object_set (view, "state", YELP_VIEW_STATE_ERROR, NULL);
3463-
3464- if (doc404) {
3465- g_free (priv->root_title);
3466- priv->root_title = g_strdup (title);
3467- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3468- "root-title");
3469- g_signal_emit_by_name (view, "notify::root-title", spec);
3470- g_free (priv->page_id);
3471- priv->page_id = g_strdup ("index");
3472- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3473- "page-id");
3474- g_signal_emit_by_name (view, "notify::page-id", spec);
3475- }
3476-
3477- g_free (priv->page_title);
3478- priv->page_title = g_strdup (title);
3479- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3480- "page-title");
3481- g_signal_emit_by_name (view, "notify::page-title", spec);
3482-
3483- g_free (priv->page_desc);
3484- priv->page_desc = NULL;
3485- if (priv->uri)
3486- priv->page_desc = yelp_uri_get_canonical_uri (priv->uri);
3487- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3488- "page-desc");
3489- g_signal_emit_by_name (view, "notify::page-desc", spec);
3490-
3491- g_free (priv->page_icon);
3492- priv->page_icon = g_strdup ("dialog-warning");
3493- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3494- "page-icon");
3495- g_signal_emit_by_name (view, "notify::page-icon", spec);
3496-
3497- g_signal_emit (view, signals[LOADED], 0);
3498- g_signal_handler_block (view, priv->navigation_requested);
3499- webkit_web_view_load_string (WEBKIT_WEB_VIEW (view),
3500- page,
3501- "text/html",
3502- "UTF-8",
3503- "file:///error/");
3504- g_signal_handler_unblock (view, priv->navigation_requested);
3505- g_free (title_m);
3506- g_free (content_beg);
3507- if (content_end != NULL)
3508- g_free (content_end);
3509- g_free (page);
3510-}
3511-
3512-
3513-static void
3514-settings_set_fonts (YelpSettings *settings)
3515-{
3516- gchar *family;
3517- gint size;
3518-
3519- g_object_set (websettings,
3520- "default-encoding", "utf-8",
3521- "enable-private-browsing", TRUE,
3522- NULL);
3523-
3524- family = yelp_settings_get_font_family (settings,
3525- YELP_SETTINGS_FONT_VARIABLE);
3526- size = yelp_settings_get_font_size (settings,
3527- YELP_SETTINGS_FONT_VARIABLE);
3528- g_object_set (websettings,
3529- "default-font-family", family,
3530- "sans-serif-font-family", family,
3531- "default-font-size", size,
3532- NULL);
3533- g_free (family);
3534-
3535- family = yelp_settings_get_font_family (settings,
3536- YELP_SETTINGS_FONT_FIXED);
3537- size = yelp_settings_get_font_size (settings,
3538- YELP_SETTINGS_FONT_FIXED);
3539- g_object_set (websettings,
3540- "monospace-font-family", family,
3541- "default-monospace-font-size", size,
3542- NULL);
3543- g_free (family);
3544-}
3545-
3546-static void
3547-settings_show_text_cursor (YelpSettings *settings)
3548-{
3549- g_object_set (websettings,
3550- "enable-caret-browsing",
3551- yelp_settings_get_show_text_cursor (settings),
3552- NULL);
3553-}
3554-
3555-/******************************************************************************/
3556-
3557-static void
3558-uri_resolved (YelpUri *uri,
3559- YelpView *view)
3560-{
3561- YelpViewPrivate *priv = GET_PRIV (view);
3562- YelpDocument *document;
3563- YelpBackEntry *back;
3564- GtkAction *action;
3565- GSList *proxies, *cur;
3566- GError *error = NULL;
3567- gchar *struri;
3568- GParamSpec *spec;
3569-
3570- if (yelp_uri_get_document_type (uri) != YELP_URI_DOCUMENT_TYPE_EXTERNAL) {
3571- g_object_ref (uri);
3572- view_clear_load (view);
3573- priv->uri = uri;
3574- }
3575-
3576- switch (yelp_uri_get_document_type (uri)) {
3577- case YELP_URI_DOCUMENT_TYPE_EXTERNAL:
3578- g_object_set (view, "state", priv->prevstate, NULL);
3579- struri = yelp_uri_get_canonical_uri (uri);
3580- if (g_str_has_prefix (struri, "install:") ||
3581- g_str_has_prefix (struri, "install-ghelp:") ||
3582- g_str_has_prefix (struri, "install-help:")) {
3583- view_install_uri (view, struri);
3584- }
3585- else {
3586- gboolean result;
3587- g_signal_emit (view, signals[EXTERNAL_URI], 0, uri, &result);
3588- }
3589- g_free (struri);
3590- return;
3591- case YELP_URI_DOCUMENT_TYPE_NOT_FOUND:
3592- struri = yelp_uri_get_canonical_uri (uri);
3593- if (struri != NULL) {
3594- error = g_error_new (YELP_ERROR, YELP_ERROR_NOT_FOUND,
3595- _("The URI ‘%s’ does not point to a valid page."),
3596- struri);
3597- g_free (struri);
3598- }
3599- else {
3600- error = g_error_new (YELP_ERROR, YELP_ERROR_NOT_FOUND,
3601- _("The URI does not point to a valid page."));
3602- }
3603- break;
3604- case YELP_URI_DOCUMENT_TYPE_ERROR:
3605- struri = yelp_uri_get_canonical_uri (uri);
3606- error = g_error_new (YELP_ERROR, YELP_ERROR_PROCESSING,
3607- _("The URI ‘%s’ could not be parsed."),
3608- struri);
3609- g_free (struri);
3610- break;
3611- default:
3612- break;
3613- }
3614-
3615- if (error == NULL) {
3616- document = yelp_document_get_for_uri (uri);
3617- if (priv->document)
3618- g_object_unref (priv->document);
3619- priv->document = document;
3620- }
3621- else {
3622- if (priv->document != NULL) {
3623- g_object_unref (priv->document);
3624- priv->document = NULL;
3625- }
3626- }
3627-
3628- if (!priv->back_load) {
3629- back = g_new0 (YelpBackEntry, 1);
3630- back->uri = g_object_ref (uri);
3631- while (priv->back_list != priv->back_cur) {
3632- back_entry_free ((YelpBackEntry *) priv->back_list->data);
3633- priv->back_list = g_list_delete_link (priv->back_list, priv->back_list);
3634- }
3635- priv->back_list = g_list_prepend (priv->back_list, back);
3636- priv->back_cur = priv->back_list;
3637- }
3638- priv->back_load = FALSE;
3639-
3640- action = gtk_action_group_get_action (priv->action_group, "YelpViewGoBack");
3641- gtk_action_set_sensitive (action, FALSE);
3642- proxies = gtk_action_get_proxies (action);
3643- if (priv->back_cur->next && priv->back_cur->next->data) {
3644- gchar *tooltip = "";
3645- back = priv->back_cur->next->data;
3646-
3647- gtk_action_set_sensitive (action, TRUE);
3648- if (back->title && back->desc) {
3649- gchar *color;
3650- color = yelp_settings_get_color (yelp_settings_get_default (),
3651- YELP_SETTINGS_COLOR_TEXT_LIGHT);
3652- tooltip = g_markup_printf_escaped ("<span size='larger'>%s</span>\n<span color='%s'>%s</span>",
3653- back->title, color, back->desc);
3654- g_free (color);
3655- }
3656- else if (back->title)
3657- tooltip = g_markup_printf_escaped ("<span size='larger'>%s</span>",
3658- back->title);
3659- /* Can't seem to use markup on GtkAction tooltip */
3660- for (cur = proxies; cur != NULL; cur = cur->next)
3661- gtk_widget_set_tooltip_markup (GTK_WIDGET (cur->data), tooltip);
3662- }
3663- else {
3664- for (cur = proxies; cur != NULL; cur = cur->next)
3665- gtk_widget_set_tooltip_text (GTK_WIDGET (cur->data), "");
3666- }
3667-
3668- action = gtk_action_group_get_action (priv->action_group, "YelpViewGoForward");
3669- gtk_action_set_sensitive (action, FALSE);
3670- proxies = gtk_action_get_proxies (action);
3671- if (priv->back_cur->prev && priv->back_cur->prev->data) {
3672- gchar *tooltip = "";
3673- back = priv->back_cur->prev->data;
3674-
3675- gtk_action_set_sensitive (action, TRUE);
3676- if (back->title && back->desc) {
3677- gchar *color;
3678- color = yelp_settings_get_color (yelp_settings_get_default (),
3679- YELP_SETTINGS_COLOR_TEXT_LIGHT);
3680- tooltip = g_markup_printf_escaped ("<span size='larger'>%s</span>\n<span color='%s'>%s</span>",
3681- back->title, color, back->desc);
3682- g_free (color);
3683- }
3684- else if (back->title)
3685- tooltip = g_markup_printf_escaped ("<span size='larger'>%s</span>",
3686- back->title);
3687- /* Can't seem to use markup on GtkAction tooltip */
3688- for (cur = proxies; cur != NULL; cur = cur->next)
3689- gtk_widget_set_tooltip_markup (GTK_WIDGET (cur->data), tooltip);
3690- }
3691- else {
3692- for (cur = proxies; cur != NULL; cur = cur->next)
3693- gtk_widget_set_tooltip_text (GTK_WIDGET (cur->data), "");
3694- }
3695-
3696- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3697- "yelp-uri");
3698- g_signal_emit_by_name (view, "notify::yelp-uri", spec);
3699-
3700- g_free (priv->page_id);
3701- priv->page_id = NULL;
3702- if (priv->uri != NULL)
3703- priv->page_id = yelp_uri_get_page_id (priv->uri);
3704- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3705- "page-id");
3706- g_signal_emit_by_name (view, "notify::page-id", spec);
3707-
3708- g_free (priv->root_title);
3709- g_free (priv->page_title);
3710- g_free (priv->page_desc);
3711- g_free (priv->page_icon);
3712- priv->root_title = NULL;
3713- priv->page_title = NULL;
3714- priv->page_desc = NULL;
3715- priv->page_icon = NULL;
3716-
3717- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3718- "root-title");
3719- g_signal_emit_by_name (view, "notify::root-title", spec);
3720-
3721- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3722- "page-title");
3723- g_signal_emit_by_name (view, "notify::page-title", spec);
3724-
3725- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3726- "page-desc");
3727- g_signal_emit_by_name (view, "notify::page-desc", spec);
3728-
3729- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3730- "page-icon");
3731- g_signal_emit_by_name (view, "notify::page-icon", spec);
3732-
3733- if (error == NULL)
3734- view_load_page (view);
3735- else {
3736- view_show_error_page (view, error);
3737- g_error_free (error);
3738- }
3739-}
3740-
3741-static void
3742-document_callback (YelpDocument *document,
3743- YelpDocumentSignal signal,
3744- YelpView *view,
3745- GError *error)
3746-{
3747- YelpViewPrivate *priv = GET_PRIV (view);
3748-
3749- debug_print (DB_FUNCTION, "entering\n");
3750-
3751- if (signal == YELP_DOCUMENT_SIGNAL_INFO) {
3752- gchar *prev_id, *next_id, *real_id;
3753- GtkAction *action;
3754- YelpBackEntry *back = NULL;
3755- GParamSpec *spec;
3756-
3757- real_id = yelp_document_get_page_id (document, priv->page_id);
3758- if (priv->page_id && real_id && g_str_equal (real_id, priv->page_id)) {
3759- g_free (real_id);
3760- }
3761- else {
3762- GParamSpec *spec;
3763- g_free (priv->page_id);
3764- priv->page_id = real_id;
3765- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3766- "page-id");
3767- g_signal_emit_by_name (view, "notify::page-id", spec);
3768- }
3769-
3770- g_free (priv->root_title);
3771- g_free (priv->page_title);
3772- g_free (priv->page_desc);
3773- g_free (priv->page_icon);
3774-
3775- priv->root_title = yelp_document_get_root_title (document, priv->page_id);
3776- priv->page_title = yelp_document_get_page_title (document, priv->page_id);
3777- priv->page_desc = yelp_document_get_page_desc (document, priv->page_id);
3778- priv->page_icon = yelp_document_get_page_icon (document, priv->page_id);
3779-
3780- if (priv->back_cur)
3781- back = priv->back_cur->data;
3782- if (back) {
3783- g_free (back->title);
3784- back->title = g_strdup (priv->page_title);
3785- g_free (back->desc);
3786- back->desc = g_strdup (priv->page_desc);
3787- }
3788-
3789- prev_id = yelp_document_get_prev_id (document, priv->page_id);
3790- action = gtk_action_group_get_action (priv->action_group, "YelpViewGoPrevious");
3791- gtk_action_set_sensitive (action, prev_id != NULL);
3792- g_free (prev_id);
3793-
3794- next_id = yelp_document_get_next_id (document, priv->page_id);
3795- action = gtk_action_group_get_action (priv->action_group, "YelpViewGoNext");
3796- gtk_action_set_sensitive (action, next_id != NULL);
3797- g_free (next_id);
3798-
3799- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3800- "root-title");
3801- g_signal_emit_by_name (view, "notify::root-title", spec);
3802-
3803- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3804- "page-title");
3805- g_signal_emit_by_name (view, "notify::page-title", spec);
3806-
3807- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3808- "page-desc");
3809- g_signal_emit_by_name (view, "notify::page-desc", spec);
3810-
3811- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3812- "page-icon");
3813- g_signal_emit_by_name (view, "notify::page-icon", spec);
3814- }
3815- else if (signal == YELP_DOCUMENT_SIGNAL_CONTENTS) {
3816- YelpUriDocumentType doctype;
3817- const gchar *contents;
3818- gchar *mime_type, *page_id, *frag_id, *full_uri;
3819- page_id = yelp_uri_get_page_id (priv->uri);
3820- debug_print (DB_ARG, " document.uri.page_id=\"%s\"\n", page_id);
3821- mime_type = yelp_document_get_mime_type (document, page_id);
3822- contents = yelp_document_read_contents (document, page_id);
3823- frag_id = yelp_uri_get_frag_id (priv->uri);
3824- g_free (priv->bogus_uri);
3825- /* We don't have actual page and frag IDs for DocBook. We just map IDs
3826- of block elements. The result is that we get xref:someid#someid.
3827- If someid is really the page ID, we just drop the frag reference.
3828- Otherwise, normal page views scroll past the link trail.
3829- */
3830- if (frag_id != NULL) {
3831- if (YELP_IS_DOCBOOK_DOCUMENT (document)) {
3832- gchar *real_id = yelp_document_get_page_id (document, page_id);
3833- if (g_str_equal (real_id, frag_id)) {
3834- g_free (frag_id);
3835- frag_id = NULL;
3836- }
3837- g_free (real_id);
3838- }
3839- }
3840- /* We have to give WebKit a URI in a scheme it understands, otherwise we
3841- won't get the resource-request-starting signal. So we can't use the
3842- canonical URI, because it might be something like ghelp. We also have
3843- to give it something unique, because WebKit ignores our load_string
3844- call if the URI isn't different. We could try to construct something
3845- based on actual file locations, but in fact it doesn't matter. So
3846- we just make a bogus URI that's easy to process later.
3847- */
3848- doctype = yelp_uri_get_document_type (priv->uri);
3849- full_uri = yelp_uri_get_canonical_uri (priv->uri);
3850- if (g_str_has_prefix (full_uri, "file:/") &&
3851- (doctype == YELP_URI_DOCUMENT_TYPE_TEXT ||
3852- doctype == YELP_URI_DOCUMENT_TYPE_HTML ||
3853- doctype == YELP_URI_DOCUMENT_TYPE_XHTML )) {
3854- priv->bogus_uri = full_uri;
3855- }
3856- else {
3857- g_free (full_uri);
3858- if (frag_id != NULL)
3859- priv->bogus_uri = g_strdup_printf ("%s%p#%s", BOGUS_URI, priv->uri, frag_id);
3860- else
3861- priv->bogus_uri = g_strdup_printf ("%s%p", BOGUS_URI, priv->uri);
3862- }
3863- g_signal_handler_block (view, priv->navigation_requested);
3864- webkit_web_view_load_string (WEBKIT_WEB_VIEW (view),
3865- contents,
3866- mime_type,
3867- "UTF-8",
3868- priv->bogus_uri);
3869- g_signal_handler_unblock (view, priv->navigation_requested);
3870- g_object_set (view, "state", YELP_VIEW_STATE_LOADED, NULL);
3871-
3872- /* If we need to set the GtkAdjustment or trigger the page title
3873- * from what WebKit thinks it is (see comment below), we need to
3874- * let the main loop run through.
3875- */
3876- if (priv->vadjust > 0 || priv->hadjust > 0 || priv->page_title == NULL)
3877- while (g_main_context_pending (NULL)) {
3878- WebKitLoadStatus status;
3879- status = webkit_web_view_get_load_status (WEBKIT_WEB_VIEW (view));
3880- g_main_context_iteration (NULL, FALSE);
3881- /* Sometimes some runaway JavaScript causes there to always
3882- * be pending sources. Break out if the document is loaded.
3883- */
3884- if (status == WEBKIT_LOAD_FINISHED ||
3885- status == WEBKIT_LOAD_FAILED)
3886- break;
3887- }
3888-
3889- /* Setting adjustments only work after the page is loaded. These
3890- * are set by view_history_action, and they're reset to 0 after
3891- * each load here.
3892- */
3893- if (priv->vadjust > 0) {
3894- if (priv->vadjustment)
3895- gtk_adjustment_set_value (priv->vadjustment, priv->vadjust);
3896- priv->vadjust = 0;
3897- }
3898- if (priv->hadjust > 0) {
3899- if (priv->hadjustment)
3900- gtk_adjustment_set_value (priv->hadjustment, priv->hadjust);
3901- priv->hadjust = 0;
3902- }
3903-
3904- /* If the document didn't give us a page title, get it from WebKit.
3905- * We let the main loop run through so that WebKit gets the title
3906- * set so that we can send notify::page-title before loaded. It
3907- * simplifies things if YelpView consumers can assume the title
3908- * is set before loaded is triggered.
3909- */
3910- if (priv->page_title == NULL) {
3911- GParamSpec *spec;
3912- priv->page_title = g_strdup (webkit_web_view_get_title (WEBKIT_WEB_VIEW (view)));
3913- spec = g_object_class_find_property ((GObjectClass *) YELP_VIEW_GET_CLASS (view),
3914- "page-title");
3915- g_signal_emit_by_name (view, "notify::page-title", spec);
3916- }
3917-
3918- g_free (frag_id);
3919- g_free (page_id);
3920- g_free (mime_type);
3921- yelp_document_finish_read (document, contents);
3922- g_signal_emit (view, signals[LOADED], 0);
3923- }
3924- else if (signal == YELP_DOCUMENT_SIGNAL_ERROR) {
3925- view_show_error_page (view, error);
3926- }
3927-}
3928
3929=== removed directory '.pc/git_signal_handler.patch/src'
3930=== removed file '.pc/git_signal_handler.patch/src/yelp-window.c'
3931--- .pc/git_signal_handler.patch/src/yelp-window.c 2014-02-27 13:28:05 +0000
3932+++ .pc/git_signal_handler.patch/src/yelp-window.c 1970-01-01 00:00:00 +0000
3933@@ -1,1402 +0,0 @@
3934-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3935-/*
3936- * Copyright (C) 2010 Shaun McCance <shaunm@gnome.org>
3937- *
3938- * This program is free software; you can redistribute it and/or
3939- * modify it under the terms of the GNU General Public License as
3940- * published by the Free Software Foundation; either version 2 of the
3941- * License, or (at your option) any later version.
3942- *
3943- * This program is distributed in the hope that it will be useful,
3944- * but WITHOUT ANY WARRANTY; without even the implied warranty of
3945- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3946- * General Public License for more details.
3947- *
3948- * You should have received a copy of the GNU General Public
3949- * License along with this program; if not, write to the
3950- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
3951- * Boston, MA 02111-1307, USA.
3952- *
3953- * Author: Shaun McCance <shaunm@gnome.org>
3954- */
3955-
3956-#ifdef HAVE_CONFIG_H
3957-#include <config.h>
3958-#endif
3959-
3960-#include <math.h>
3961-
3962-#include <gdk/gdkkeysyms.h>
3963-#include <glib/gi18n.h>
3964-#include <gtk/gtk.h>
3965-
3966-#include "yelp-location-entry.h"
3967-#include "yelp-settings.h"
3968-#include "yelp-uri.h"
3969-#include "yelp-view.h"
3970-
3971-#include "yelp-application.h"
3972-#include "yelp-window.h"
3973-
3974-static void yelp_window_init (YelpWindow *window);
3975-static void yelp_window_class_init (YelpWindowClass *klass);
3976-static void yelp_window_dispose (GObject *object);
3977-static void yelp_window_finalize (GObject *object);
3978-static void yelp_window_get_property (GObject *object,
3979- guint prop_id,
3980- GValue *value,
3981- GParamSpec *pspec);
3982-static void yelp_window_set_property (GObject *object,
3983- guint prop_id,
3984- const GValue *value,
3985- GParamSpec *pspec);
3986-
3987-static void window_construct (YelpWindow *window);
3988-static void window_new (GtkAction *action,
3989- YelpWindow *window);
3990-static gboolean window_map_event (YelpWindow *window,
3991- GdkEvent *event,
3992- gpointer user_data);
3993-static gboolean window_configure_event (YelpWindow *window,
3994- GdkEventConfigure *event,
3995- gpointer user_data);
3996-static void window_drag_received (YelpWindow *window,
3997- GdkDragContext *context,
3998- gint x,
3999- gint y,
4000- GtkSelectionData *data,
4001- guint info,
4002- guint time,
4003- gpointer userdata);
4004-static gboolean window_resize_signal (YelpWindow *window);
4005-static void window_close (GtkAction *action,
4006- YelpWindow *window);
4007-static void window_go_all (GtkAction *action,
4008- YelpWindow *window);
4009-static void window_add_bookmark (GtkAction *action,
4010- YelpWindow *window);
4011-static void window_remove_bookmark (GtkAction *action,
4012- YelpWindow *window);
4013-static void window_load_bookmark (GtkAction *action,
4014- YelpWindow *window);
4015-static void window_find_in_page (GtkAction *action,
4016- YelpWindow *window);
4017-static void window_start_search (GtkAction *action,
4018- YelpWindow *window);
4019-static void window_open_location (GtkAction *action,
4020- YelpWindow *window);
4021-static void window_read_later (GtkAction *action,
4022- YelpWindow *window);
4023-static gboolean read_later_clicked (GtkLinkButton *button,
4024- YelpWindow *window);
4025-static void app_read_later_changed (YelpApplication *app,
4026- const gchar *doc_uri,
4027- YelpWindow *window);
4028-static void app_bookmarks_changed (YelpApplication *app,
4029- const gchar *doc_uri,
4030- YelpWindow *window);
4031-static void window_set_bookmarks (YelpWindow *window,
4032- const gchar *doc_uri);
4033-static void window_set_bookmark_action (YelpWindow *window);
4034-static gboolean find_entry_focus_out (GtkEntry *entry,
4035- GdkEventFocus *event,
4036- YelpWindow *window);
4037-static gboolean find_entry_key_press (GtkEntry *entry,
4038- GdkEventKey *event,
4039- YelpWindow *window);
4040-static void find_entry_changed (GtkEntry *entry,
4041- YelpWindow *window);
4042-
4043-static gboolean entry_focus_in (GtkEntry *entry,
4044- GdkEventFocus *event,
4045- YelpWindow *window);
4046-static gboolean entry_focus_out (YelpLocationEntry *entry,
4047- GdkEventFocus *event,
4048- YelpWindow *window);
4049-
4050-static void view_new_window (YelpView *view,
4051- YelpUri *uri,
4052- YelpWindow *window);
4053-static void view_loaded (YelpView *view,
4054- YelpWindow *window);
4055-static void view_uri_selected (YelpView *view,
4056- GParamSpec *pspec,
4057- YelpWindow *window);
4058-static void view_root_title (YelpView *view,
4059- GParamSpec *pspec,
4060- YelpWindow *window);
4061-static gboolean view_is_xref_uri (YelpView *view,
4062- GtkAction *action,
4063- const gchar *uri,
4064- YelpWindow *window);
4065-
4066-static void hidden_entry_activate (GtkEntry *entry,
4067- YelpWindow *window);
4068-static void hidden_entry_hide (YelpWindow *window);
4069-static gboolean hidden_key_press (GtkWidget *widget,
4070- GdkEventKey *event,
4071- YelpWindow *window);
4072-
4073-enum {
4074- PROP_0,
4075- PROP_APPLICATION
4076-};
4077-
4078-enum {
4079- RESIZE_EVENT,
4080- LAST_SIGNAL
4081-};
4082-
4083-static guint signals[LAST_SIGNAL] = { 0 };
4084-
4085-G_DEFINE_TYPE (YelpWindow, yelp_window, GTK_TYPE_WINDOW);
4086-#define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_WINDOW, YelpWindowPrivate))
4087-
4088-static const gchar *YELP_UI =
4089- "<ui>"
4090- "<menubar>"
4091- "<menu action='PageMenu'>"
4092- "<menuitem action='NewWindow'/>"
4093- "<menuitem action='Find'/>"
4094- "<separator/>"
4095- "<menuitem action='YelpViewPrint'/>"
4096- "<separator/>"
4097- "<menuitem action='CloseWindow'/>"
4098- "</menu>"
4099- "<menu action='ViewMenu'>"
4100- "<menuitem action='LargerText'/>"
4101- "<menuitem action='SmallerText'/>"
4102- "<separator/>"
4103- "<menuitem action='ShowTextCursor'/>"
4104- "</menu>"
4105- "<menu action='GoMenu'>"
4106- "<menuitem action='YelpViewGoBack'/>"
4107- "<menuitem action='YelpViewGoForward'/>"
4108- "<separator/>"
4109- "<menuitem action='YelpViewGoPrevious'/>"
4110- "<menuitem action='YelpViewGoNext'/>"
4111- "<separator/>"
4112- "<menuitem action='GoAll'/>"
4113- "</menu>"
4114- "<menu action='BookmarksMenu'>"
4115- "<menuitem action='AddBookmark'/>"
4116- "<menuitem action='RemoveBookmark'/>"
4117- "<separator/>"
4118- "<placeholder name='Bookmarks'/>"
4119- "</menu>"
4120- "</menubar>"
4121- "<accelerator action='Find'/>"
4122- "<accelerator action='Search'/>"
4123- "<accelerator action='OpenLocation'/>"
4124- "</ui>";
4125-
4126-typedef struct _YelpWindowPrivate YelpWindowPrivate;
4127-struct _YelpWindowPrivate {
4128- GtkListStore *history;
4129- GtkUIManager *ui_manager;
4130- GtkActionGroup *action_group;
4131- YelpApplication *application;
4132-
4133- gulong bookmarks_changed;
4134- gulong read_later_changed;
4135-
4136- /* no refs on these, owned by containers */
4137- YelpView *view;
4138- GtkWidget *vbox_view;
4139- GtkWidget *vbox_full;
4140- GtkWidget *hbox;
4141- YelpLocationEntry *entry;
4142- GtkWidget *hidden_entry;
4143- GtkWidget *find_entry;
4144- GtkWidget *find_label;
4145- GtkWidget *read_later_vbox;
4146-
4147- /* refs because we dynamically add & remove */
4148- GtkWidget *find_bar;
4149- GtkWidget *align_location;
4150- GtkWidget *align_hidden;
4151- GtkWidget *read_later;
4152-
4153- gchar *doc_uri;
4154-
4155- GtkActionGroup *bookmark_actions;
4156- guint bookmarks_merge_id;
4157-
4158- guint resize_signal;
4159- gint width;
4160- gint height;
4161-
4162- guint entry_color_animate;
4163- gfloat entry_color_step;
4164-
4165- gboolean configured;
4166-};
4167-
4168-static const GtkActionEntry entries[] = {
4169- { "PageMenu", NULL, N_("_Page") },
4170- { "ViewMenu", NULL, N_("_View") },
4171- { "GoMenu", NULL, N_("_Go") },
4172- { "BookmarksMenu", NULL, N_("_Bookmarks") },
4173-
4174- { "NewWindow", NULL,
4175- N_("_New Window"),
4176- "<Control>N",
4177- NULL,
4178- G_CALLBACK (window_new) },
4179- { "CloseWindow", NULL,
4180- N_("_Close"),
4181- "<Control>W",
4182- NULL,
4183- G_CALLBACK (window_close) },
4184- { "GoAll", NULL,
4185- N_("_All Documents"),
4186- NULL, NULL,
4187- G_CALLBACK (window_go_all) },
4188- { "AddBookmark", NULL,
4189- N_("_Add Bookmark"),
4190- "<Control>D",
4191- NULL,
4192- G_CALLBACK (window_add_bookmark) },
4193- { "RemoveBookmark", NULL,
4194- N_("_Remove Bookmark"),
4195- NULL, NULL,
4196- G_CALLBACK (window_remove_bookmark) },
4197- { "Find", NULL,
4198- N_("Find in Page..."),
4199- "<Control>F",
4200- NULL,
4201- G_CALLBACK (window_find_in_page) },
4202- { "Search", NULL,
4203- N_("Search..."),
4204- "<Control>S",
4205- NULL,
4206- G_CALLBACK (window_start_search) },
4207- { "OpenLocation", NULL,
4208- N_("Open Location"),
4209- "<Control>L",
4210- NULL,
4211- G_CALLBACK (window_open_location) }
4212-};
4213-
4214-static void
4215-yelp_window_init (YelpWindow *window)
4216-{
4217- g_signal_connect (window, "configure-event", G_CALLBACK (window_configure_event), NULL);
4218- g_signal_connect (window, "map-event", G_CALLBACK (window_map_event), NULL);
4219-}
4220-
4221-static void
4222-yelp_window_class_init (YelpWindowClass *klass)
4223-{
4224- GObjectClass *object_class = G_OBJECT_CLASS (klass);
4225-
4226- object_class->dispose = yelp_window_dispose;
4227- object_class->finalize = yelp_window_finalize;
4228- object_class->get_property = yelp_window_get_property;
4229- object_class->set_property = yelp_window_set_property;
4230-
4231- g_object_class_install_property (object_class,
4232- PROP_APPLICATION,
4233- g_param_spec_object ("application",
4234- _("Application"),
4235- _("A YelpApplication instance that controls this window"),
4236- YELP_TYPE_APPLICATION,
4237- G_PARAM_CONSTRUCT_ONLY |
4238- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
4239- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
4240-
4241- signals[RESIZE_EVENT] =
4242- g_signal_new ("resized",
4243- G_OBJECT_CLASS_TYPE (klass),
4244- G_SIGNAL_RUN_LAST,
4245- 0, NULL, NULL,
4246- g_cclosure_marshal_VOID__VOID,
4247- G_TYPE_NONE, 0);
4248-
4249- g_type_class_add_private (klass, sizeof (YelpWindowPrivate));
4250-}
4251-
4252-static void
4253-yelp_window_dispose (GObject *object)
4254-{
4255- YelpWindowPrivate *priv = GET_PRIV (object);
4256-
4257- if (priv->history) {
4258- g_object_unref (priv->history);
4259- priv->history = NULL;
4260- }
4261-
4262- if (priv->action_group) {
4263- g_object_unref (priv->action_group);
4264- priv->action_group = NULL;
4265- }
4266-
4267- if (priv->bookmark_actions) {
4268- g_object_unref (priv->bookmark_actions);
4269- priv->bookmark_actions = NULL;
4270- }
4271-
4272- if (priv->read_later_changed) {
4273- g_source_remove (priv->read_later_changed);
4274- priv->read_later_changed = 0;
4275- }
4276-
4277- if (priv->bookmarks_changed) {
4278- g_source_remove (priv->bookmarks_changed);
4279- priv->bookmarks_changed = 0;
4280- }
4281-
4282- if (priv->align_location) {
4283- g_object_unref (priv->align_location);
4284- priv->align_location = NULL;
4285- }
4286-
4287- if (priv->align_hidden) {
4288- g_object_unref (priv->align_hidden);
4289- priv->align_hidden = NULL;
4290- }
4291-
4292- if (priv->find_bar) {
4293- g_object_unref (priv->find_bar);
4294- priv->find_bar = NULL;
4295- }
4296-
4297- if (priv->entry_color_animate != 0) {
4298- g_source_remove (priv->entry_color_animate);
4299- priv->entry_color_animate = 0;
4300- }
4301-
4302- G_OBJECT_CLASS (yelp_window_parent_class)->dispose (object);
4303-}
4304-
4305-static void
4306-yelp_window_finalize (GObject *object)
4307-{
4308- YelpWindowPrivate *priv = GET_PRIV (object);
4309- g_free (priv->doc_uri);
4310- G_OBJECT_CLASS (yelp_window_parent_class)->finalize (object);
4311-}
4312-
4313-static void
4314-yelp_window_get_property (GObject *object,
4315- guint prop_id,
4316- GValue *value,
4317- GParamSpec *pspec)
4318-{
4319- YelpWindowPrivate *priv = GET_PRIV (object);
4320- switch (prop_id) {
4321- case PROP_APPLICATION:
4322- g_value_set_object (value, priv->application);
4323- break;
4324- default:
4325- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4326- break;
4327- }
4328-}
4329-
4330-static void
4331-yelp_window_set_property (GObject *object,
4332- guint prop_id,
4333- const GValue *value,
4334- GParamSpec *pspec)
4335-{
4336- YelpWindowPrivate *priv = GET_PRIV (object);
4337- switch (prop_id) {
4338- case PROP_APPLICATION:
4339- priv->application = g_value_get_object (value);
4340- window_construct ((YelpWindow *) object);
4341- break;
4342- default:
4343- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4344- break;
4345- }
4346-}
4347-
4348-static void
4349-window_construct (YelpWindow *window)
4350-{
4351- GtkWidget *scroll;
4352- GtkActionGroup *view_actions;
4353- GtkAction *action;
4354- GtkWidget *vbox, *button, *label;
4355- gchar *color, *text;
4356- YelpWindowPrivate *priv = GET_PRIV (window);
4357-
4358- gtk_window_set_icon_name (GTK_WINDOW (window), "help-browser");
4359-
4360- priv->view = (YelpView *) yelp_view_new ();
4361-
4362- action = gtk_action_new ("ReadLinkLater", _("Read Link _Later"), NULL, NULL);
4363- g_signal_connect (action, "activate", G_CALLBACK (window_read_later), window);
4364- yelp_view_add_link_action (priv->view, action,
4365- (YelpViewActionValidFunc) view_is_xref_uri,
4366- window);
4367- priv->read_later_changed =
4368- g_signal_connect (priv->application, "read-later-changed",
4369- G_CALLBACK (app_read_later_changed), window);
4370-
4371- priv->vbox_full = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
4372- gtk_container_add (GTK_CONTAINER (window), priv->vbox_full);
4373-
4374- priv->vbox_view = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4375- gtk_box_pack_start (GTK_BOX (priv->vbox_full), priv->vbox_view, TRUE, TRUE, 0);
4376-
4377- priv->action_group = gtk_action_group_new ("YelpWindowActions");
4378- gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE);
4379- gtk_action_group_add_actions (priv->action_group,
4380- entries, G_N_ELEMENTS (entries),
4381- window);
4382-
4383- priv->bookmark_actions = gtk_action_group_new ("BookmarkActions");
4384- gtk_action_group_set_translate_func (priv->bookmark_actions, NULL, NULL, NULL);
4385-
4386- priv->ui_manager = gtk_ui_manager_new ();
4387- gtk_ui_manager_insert_action_group (priv->ui_manager, priv->action_group, 0);
4388- gtk_ui_manager_insert_action_group (priv->ui_manager, priv->bookmark_actions, 1);
4389- gtk_ui_manager_insert_action_group (priv->ui_manager,
4390- yelp_application_get_action_group (priv->application),
4391- 2);
4392- view_actions = yelp_view_get_action_group (priv->view);
4393- gtk_ui_manager_insert_action_group (priv->ui_manager, view_actions, 3);
4394- gtk_window_add_accel_group (GTK_WINDOW (window),
4395- gtk_ui_manager_get_accel_group (priv->ui_manager));
4396- gtk_ui_manager_add_ui_from_string (priv->ui_manager, YELP_UI, -1, NULL);
4397- gtk_box_pack_start (GTK_BOX (priv->vbox_view),
4398- gtk_ui_manager_get_widget (priv->ui_manager, "/ui/menubar"),
4399- FALSE, FALSE, 0);
4400-
4401- priv->bookmarks_merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
4402- priv->bookmarks_changed =
4403- g_signal_connect (priv->application, "bookmarks-changed",
4404- G_CALLBACK (app_bookmarks_changed), window);
4405-
4406- priv->hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4407- g_object_set (priv->hbox, "border-width", 2, NULL);
4408- gtk_box_pack_start (GTK_BOX (priv->vbox_view), priv->hbox, FALSE, FALSE, 0);
4409-
4410- action = gtk_action_group_get_action (view_actions, "YelpViewGoBack");
4411- button = gtk_action_create_tool_item (action);
4412- gtk_box_pack_start (GTK_BOX (priv->hbox),
4413- button,
4414- FALSE, FALSE, 0);
4415- action = gtk_action_group_get_action (view_actions, "YelpViewGoForward");
4416- button = gtk_action_create_tool_item (action);
4417- gtk_box_pack_start (GTK_BOX (priv->hbox),
4418- button,
4419- FALSE, FALSE, 0);
4420-
4421- priv->entry = (YelpLocationEntry *) yelp_location_entry_new (priv->view,
4422- YELP_BOOKMARKS (priv->application));
4423- g_signal_connect (gtk_bin_get_child (GTK_BIN (priv->entry)), "focus-in-event",
4424- G_CALLBACK (entry_focus_in), window);
4425- g_signal_connect (priv->entry, "focus-out-event",
4426- G_CALLBACK (entry_focus_out), window);
4427-
4428- priv->align_location = g_object_ref_sink (gtk_alignment_new (0.0, 0.5, 1.0, 0.0));
4429- gtk_box_pack_start (GTK_BOX (priv->hbox),
4430- GTK_WIDGET (priv->align_location),
4431- TRUE, TRUE, 0);
4432- gtk_container_add (GTK_CONTAINER (priv->align_location), GTK_WIDGET (priv->entry));
4433-
4434- priv->hidden_entry = gtk_entry_new ();
4435- priv->align_hidden = g_object_ref_sink (gtk_alignment_new (0.0, 0.5, 1.0, 0.0));
4436- gtk_container_add (GTK_CONTAINER (priv->align_hidden), GTK_WIDGET (priv->hidden_entry));
4437-
4438- g_signal_connect (priv->hidden_entry, "activate",
4439- G_CALLBACK (hidden_entry_activate), window);
4440- g_signal_connect_swapped (priv->hidden_entry, "focus-out-event",
4441- G_CALLBACK (hidden_entry_hide), window);
4442- g_signal_connect (priv->hidden_entry, "key-press-event",
4443- G_CALLBACK (hidden_key_press), window);
4444-
4445- scroll = gtk_scrolled_window_new (NULL, NULL);
4446- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
4447- GTK_POLICY_AUTOMATIC,
4448- GTK_POLICY_AUTOMATIC);
4449- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
4450- GTK_SHADOW_IN);
4451- gtk_box_pack_start (GTK_BOX (priv->vbox_view), scroll, TRUE, TRUE, 0);
4452-
4453- priv->find_bar = g_object_ref_sink (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6));
4454- g_object_set (priv->find_bar,
4455- "border-width", 2,
4456- "margin-right", 16,
4457- NULL);
4458-
4459- label = gtk_label_new (_("Find:"));
4460- gtk_box_pack_start (GTK_BOX (priv->find_bar), label, FALSE, FALSE, 6);
4461-
4462- priv->find_entry = gtk_entry_new ();
4463- g_signal_connect (priv->find_entry, "changed",
4464- G_CALLBACK (find_entry_changed), window);
4465- g_signal_connect (priv->find_entry, "key-press-event",
4466- G_CALLBACK (find_entry_key_press), window);
4467- g_signal_connect (priv->find_entry, "focus-out-event",
4468- G_CALLBACK (find_entry_focus_out), window);
4469- g_object_set (priv->find_entry, "width-request", 300, NULL);
4470- gtk_box_pack_start (GTK_BOX (priv->find_bar), priv->find_entry, FALSE, FALSE, 0);
4471-
4472- priv->find_label = gtk_label_new ("");
4473- g_object_set (priv->find_label, "xalign", 0.0, NULL);
4474- gtk_box_pack_start (GTK_BOX (priv->find_bar), priv->find_label, FALSE, FALSE, 0);
4475-
4476- priv->read_later = g_object_ref_sink (gtk_info_bar_new ());
4477- vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4478- color = yelp_settings_get_color (yelp_settings_get_default (),
4479- YELP_SETTINGS_COLOR_TEXT_LIGHT);
4480- text = g_markup_printf_escaped ("<span weight='bold' color='%s'>%s</span>",
4481- color, _("Read Later"));
4482- button = gtk_label_new (text);
4483- g_object_set (button, "use-markup", TRUE, "xalign", 0.0, NULL);
4484- g_free (color);
4485- g_free (text);
4486- gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
4487- gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (priv->read_later))),
4488- vbox,
4489- FALSE, FALSE, 0);
4490- priv->read_later_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4491- gtk_box_pack_start (GTK_BOX (vbox), priv->read_later_vbox, FALSE, FALSE, 0);
4492-
4493- g_signal_connect (priv->view, "new-view-requested", G_CALLBACK (view_new_window), window);
4494- g_signal_connect (priv->view, "loaded", G_CALLBACK (view_loaded), window);
4495- g_signal_connect (priv->view, "notify::yelp-uri", G_CALLBACK (view_uri_selected), window);
4496- g_signal_connect_swapped (priv->view, "notify::page-id",
4497- G_CALLBACK (window_set_bookmark_action), window);
4498- window_set_bookmark_action (window);
4499- g_signal_connect (priv->view, "notify::root-title", G_CALLBACK (view_root_title), window);
4500- gtk_container_add (GTK_CONTAINER (scroll), GTK_WIDGET (priv->view));
4501- gtk_widget_grab_focus (GTK_WIDGET (priv->view));
4502-
4503- gtk_drag_dest_set (GTK_WIDGET (window),
4504- GTK_DEST_DEFAULT_ALL,
4505- NULL, 0,
4506- GDK_ACTION_COPY);
4507- gtk_drag_dest_add_uri_targets (GTK_WIDGET (window));
4508- g_signal_connect (window, "drag-data-received",
4509- G_CALLBACK (window_drag_received), NULL);
4510-}
4511-
4512-/******************************************************************************/
4513-
4514-YelpWindow *
4515-yelp_window_new (YelpApplication *app)
4516-{
4517- YelpWindow *window;
4518-
4519- window = (YelpWindow *) g_object_new (YELP_TYPE_WINDOW, "application", app, NULL);
4520-
4521- return window;
4522-}
4523-
4524-void
4525-yelp_window_load_uri (YelpWindow *window,
4526- YelpUri *uri)
4527-{
4528- YelpWindowPrivate *priv = GET_PRIV (window);
4529-
4530- yelp_view_load_uri (priv->view, uri);
4531-}
4532-
4533-YelpUri *
4534-yelp_window_get_uri (YelpWindow *window)
4535-{
4536- YelpUri *uri;
4537- YelpWindowPrivate *priv = GET_PRIV (window);
4538- g_object_get (G_OBJECT (priv->view), "yelp-uri", &uri, NULL);
4539- return uri;
4540-}
4541-
4542-void
4543-yelp_window_get_geometry (YelpWindow *window,
4544- gint *width,
4545- gint *height)
4546-{
4547- YelpWindowPrivate *priv = GET_PRIV (window);
4548- *width = priv->width;
4549- *height = priv->height;
4550-}
4551-
4552-/******************************************************************************/
4553-
4554-static void
4555-window_new (GtkAction *action, YelpWindow *window)
4556-{
4557- YelpUri *yuri;
4558- gchar *uri = NULL;
4559- YelpWindowPrivate *priv = GET_PRIV (window);
4560-
4561- g_object_get (priv->view, "yelp-uri", &yuri, NULL);
4562- uri = yelp_uri_get_document_uri (yuri);
4563-
4564- yelp_application_new_window (priv->application, uri);
4565-
4566- g_free (uri);
4567- g_object_unref (yuri);
4568-}
4569-
4570-static void
4571-window_drag_received (YelpWindow *window,
4572- GdkDragContext *context,
4573- gint x,
4574- gint y,
4575- GtkSelectionData *data,
4576- guint info,
4577- guint time,
4578- gpointer userdata)
4579-{
4580- gchar **uris = gtk_selection_data_get_uris (data);
4581- if (uris && uris[0]) {
4582- YelpUri *uri = yelp_uri_new (uris[0]);
4583- yelp_window_load_uri (window, uri);
4584- g_object_unref (uri);
4585- g_strfreev (uris);
4586- gtk_drag_finish (context, TRUE, FALSE, time);
4587- }
4588- gtk_drag_finish (context, FALSE, FALSE, time);
4589-}
4590-
4591-static gboolean
4592-window_map_event (YelpWindow *window,
4593- GdkEvent *event,
4594- gpointer user_data)
4595-{
4596- YelpWindowPrivate *priv = GET_PRIV (window);
4597- priv->configured = TRUE;
4598- return FALSE;
4599-}
4600-
4601-static gboolean
4602-window_configure_event (YelpWindow *window,
4603- GdkEventConfigure *event,
4604- gpointer user_data)
4605-{
4606- YelpWindowPrivate *priv = GET_PRIV (window);
4607- gboolean skip = TRUE;
4608- if (priv->width != event->width) {
4609- skip = FALSE;
4610- priv->width = event->width;
4611- }
4612- if (priv->height != event->height) {
4613- skip = FALSE;
4614- priv->height = event->height;
4615- }
4616- /* Skip the configure-event signals that GTK+ sends as it's mapping
4617- * the window, and also skip if the event didn't change the size of
4618- * the window (i.e. it was just a move).
4619- */
4620- if (!priv->configured || skip)
4621- return FALSE;
4622-
4623- if (priv->resize_signal > 0)
4624- g_source_remove (priv->resize_signal);
4625- priv->resize_signal = g_timeout_add (200,
4626- (GSourceFunc) window_resize_signal,
4627- window);
4628- g_object_set (priv->find_entry, "width-request", 2 * priv->width / 3, NULL);
4629- return FALSE;
4630-}
4631-
4632-static gboolean
4633-window_resize_signal (YelpWindow *window)
4634-{
4635- YelpWindowPrivate *priv = GET_PRIV (window);
4636- g_signal_emit (window, signals[RESIZE_EVENT], 0);
4637- priv->resize_signal = 0;
4638- return FALSE;
4639-}
4640-
4641-static void
4642-window_close (GtkAction *action, YelpWindow *window)
4643-{
4644- gboolean ret;
4645- g_signal_emit_by_name (window, "delete-event", NULL, &ret);
4646- gtk_widget_destroy (GTK_WIDGET (window));
4647-}
4648-
4649-static void
4650-window_go_all (GtkAction *action,
4651- YelpWindow *window)
4652-{
4653- YelpWindowPrivate *priv = GET_PRIV (window);
4654- yelp_view_load (priv->view, "help-list:");
4655-}
4656-
4657-static void
4658-window_add_bookmark (GtkAction *action,
4659- YelpWindow *window)
4660-{
4661- YelpUri *uri;
4662- gchar *doc_uri, *page_id, *icon, *title;
4663- YelpWindowPrivate *priv = GET_PRIV (window);
4664-
4665- g_object_get (priv->view,
4666- "yelp-uri", &uri,
4667- "page-id", &page_id,
4668- "page-icon", &icon,
4669- "page-title", &title,
4670- NULL);
4671- doc_uri = yelp_uri_get_document_uri (uri);
4672- yelp_application_add_bookmark (YELP_BOOKMARKS (priv->application),
4673- doc_uri, page_id, icon, title);
4674- g_free (doc_uri);
4675- g_free (page_id);
4676- g_free (icon);
4677- g_free (title);
4678- g_object_unref (uri);
4679-}
4680-
4681-static void
4682-window_remove_bookmark (GtkAction *action,
4683- YelpWindow *window)
4684-{
4685- YelpUri *uri;
4686- gchar *doc_uri, *page_id;
4687- YelpWindowPrivate *priv = GET_PRIV (window);
4688-
4689- g_object_get (priv->view,
4690- "yelp-uri", &uri,
4691- "page-id", &page_id,
4692- NULL);
4693- doc_uri = yelp_uri_get_document_uri (uri);
4694- yelp_application_remove_bookmark (YELP_BOOKMARKS (priv->application),
4695- doc_uri, page_id);
4696- g_free (doc_uri);
4697- g_free (page_id);
4698- g_object_unref (uri);
4699-}
4700-static void
4701-window_load_bookmark (GtkAction *action,
4702- YelpWindow *window)
4703-{
4704- YelpUri *base, *uri;
4705- gchar *xref;
4706- YelpWindowPrivate *priv = GET_PRIV (window);
4707-
4708- /* Bookmark action names are prefixed with 'LoadBookmark-' */
4709- xref = g_strconcat ("xref:", gtk_action_get_name (action) + 13, NULL);
4710- g_object_get (priv->view, "yelp-uri", &base, NULL);
4711- uri = yelp_uri_new_relative (base, xref);
4712-
4713- yelp_view_load_uri (priv->view, uri);
4714-
4715- g_object_unref (base);
4716- g_object_unref (uri);
4717- g_free (xref);
4718-}
4719-
4720-static void
4721-app_bookmarks_changed (YelpApplication *app,
4722- const gchar *doc_uri,
4723- YelpWindow *window)
4724-{
4725- YelpUri *uri;
4726- gchar *this_doc_uri;
4727- YelpWindowPrivate *priv = GET_PRIV (window);
4728-
4729- g_object_get (priv->view, "yelp-uri", &uri, NULL);
4730- this_doc_uri = yelp_uri_get_document_uri (uri);
4731-
4732- if (g_str_equal (this_doc_uri, doc_uri)) {
4733- window_set_bookmarks (window, doc_uri);
4734- }
4735-
4736- g_free (this_doc_uri);
4737- g_object_unref (uri);
4738-}
4739-
4740-typedef struct _YelpMenuEntry YelpMenuEntry;
4741-struct _YelpMenuEntry {
4742- gchar *page_id;
4743- gchar *icon;
4744- gchar *title;
4745-};
4746-
4747-static gint
4748-entry_compare (YelpMenuEntry *a, YelpMenuEntry *b)
4749-{
4750- gint ret = yelp_settings_cmp_icons (a->icon, b->icon);
4751- if (ret != 0)
4752- return ret;
4753-
4754- if (a->title && b->title)
4755- return g_utf8_collate (a->title, b->title);
4756- else if (b->title == NULL)
4757- return -1;
4758- else if (a->title == NULL)
4759- return 1;
4760-
4761- return 0;
4762-}
4763-
4764-static void
4765-window_set_bookmarks (YelpWindow *window,
4766- const gchar *doc_uri)
4767-{
4768- GVariant *value;
4769- GVariantIter *iter;
4770- gchar *page_id, *icon, *title;
4771- YelpWindowPrivate *priv = GET_PRIV (window);
4772- GSList *entries = NULL;
4773-
4774- window_set_bookmark_action (window);
4775-
4776- gtk_ui_manager_remove_ui (priv->ui_manager, priv->bookmarks_merge_id);
4777-
4778- value = yelp_application_get_bookmarks (priv->application, doc_uri);
4779- g_variant_get (value, "a(sss)", &iter);
4780- while (g_variant_iter_loop (iter, "(&s&s&s)", &page_id, &icon, &title)) {
4781- YelpMenuEntry *entry = g_new0 (YelpMenuEntry, 1);
4782- entry->page_id = page_id;
4783- entry->icon = g_strdup (icon);
4784- entry->title = title;
4785- entries = g_slist_insert_sorted (entries, entry, (GCompareFunc) entry_compare);
4786- }
4787- for ( ; entries != NULL; entries = g_slist_delete_link (entries, entries)) {
4788- GSList *cur;
4789- GtkAction *bookmark;
4790- YelpMenuEntry *entry = (YelpMenuEntry *) entries->data;
4791- gchar *action_id = g_strconcat ("LoadBookmark-", entry->page_id, NULL);
4792-
4793- bookmark = gtk_action_group_get_action (priv->bookmark_actions, action_id);
4794- if (bookmark) {
4795- /* The action might have been set by a different document using
4796- * the same page ID. We can just reuse the action, since it's
4797- * just a page ID relative to the current URI, but we need to
4798- * reset the title and icon.
4799- */
4800- g_object_set (bookmark,
4801- "label", entry->title,
4802- "icon-name", entry->icon,
4803- NULL);
4804- } else {
4805- bookmark = gtk_action_new (action_id, entry->title, NULL, NULL);
4806- g_signal_connect (bookmark, "activate",
4807- G_CALLBACK (window_load_bookmark), window);
4808- gtk_action_set_icon_name (bookmark, entry->icon);
4809- gtk_action_group_add_action (priv->bookmark_actions, bookmark);
4810- }
4811- gtk_ui_manager_add_ui (priv->ui_manager,
4812- priv->bookmarks_merge_id,
4813- "ui/menubar/BookmarksMenu/Bookmarks",
4814- action_id, action_id,
4815- GTK_UI_MANAGER_MENUITEM,
4816- FALSE);
4817- gtk_ui_manager_ensure_update (priv->ui_manager);
4818- for (cur = gtk_action_get_proxies (bookmark); cur != NULL; cur = cur->next) {
4819- if (GTK_IS_IMAGE_MENU_ITEM (cur->data))
4820- g_object_set (cur->data, "always-show-image", TRUE, NULL);
4821- }
4822- g_free (action_id);
4823- g_free (entry->icon);
4824- g_free (entry);
4825- }
4826-
4827- g_variant_iter_free (iter);
4828- g_variant_unref (value);
4829-}
4830-
4831-static void
4832-window_set_bookmark_action (YelpWindow *window)
4833-{
4834- YelpUri *uri = NULL;
4835- gchar *doc_uri = NULL, *page_id = NULL;
4836- GtkAction *action_add, *action_del;
4837- gboolean bookmarked;
4838- YelpWindowPrivate *priv = GET_PRIV (window);
4839-
4840- action_add = gtk_action_group_get_action (priv->action_group, "AddBookmark");
4841- action_del = gtk_action_group_get_action (priv->action_group, "RemoveBookmark");
4842-
4843- g_object_get (priv->view,
4844- "yelp-uri", &uri,
4845- "page-id", &page_id,
4846- NULL);
4847- if (page_id == NULL || uri == NULL) {
4848- gtk_action_set_sensitive (action_add, FALSE);
4849- gtk_action_set_sensitive (action_del, FALSE);
4850- goto done;
4851- }
4852- doc_uri = yelp_uri_get_document_uri (uri);
4853- bookmarked = yelp_application_is_bookmarked (YELP_BOOKMARKS (priv->application),
4854- doc_uri, page_id);
4855- gtk_action_set_sensitive (action_add, !bookmarked);
4856- gtk_action_set_sensitive (action_del, bookmarked);
4857-
4858- done:
4859- g_free (page_id);
4860- g_free (doc_uri);
4861- if (uri)
4862- g_object_unref (uri);
4863-}
4864-
4865-static void
4866-window_start_search (GtkAction *action, YelpWindow *window)
4867-{
4868- YelpWindowPrivate *priv = GET_PRIV (window);
4869-
4870- yelp_location_entry_start_search (priv->entry);
4871-}
4872-
4873-static void
4874-window_open_location (GtkAction *action, YelpWindow *window)
4875-{
4876- YelpUri *yuri = NULL;
4877- gchar *uri = NULL;
4878- GdkColor yellow;
4879- gchar *color;
4880- YelpWindowPrivate *priv = GET_PRIV (window);
4881-
4882- gtk_container_remove (GTK_CONTAINER (priv->hbox),
4883- priv->align_location);
4884- gtk_box_pack_start (GTK_BOX (priv->hbox),
4885- priv->align_hidden,
4886- TRUE, TRUE, 0);
4887-
4888- gtk_widget_show_all (priv->align_hidden);
4889- gtk_entry_set_text (GTK_ENTRY (priv->hidden_entry), "");
4890- gtk_widget_grab_focus (priv->hidden_entry);
4891-
4892- color = yelp_settings_get_color (yelp_settings_get_default (),
4893- YELP_SETTINGS_COLOR_YELLOW_BASE);
4894- if (gdk_color_parse (color, &yellow)) {
4895- gtk_widget_modify_base (priv->hidden_entry,
4896- GTK_STATE_NORMAL,
4897- &yellow);
4898- }
4899- g_free (color);
4900-
4901- g_object_get (priv->view, "yelp-uri", &yuri, NULL);
4902- if (yuri) {
4903- uri = yelp_uri_get_canonical_uri (yuri);
4904- g_object_unref (yuri);
4905- }
4906- if (uri) {
4907- gchar *c;
4908- gtk_entry_set_text (GTK_ENTRY (priv->hidden_entry), uri);
4909- c = strchr (uri, ':');
4910- if (c)
4911- gtk_editable_select_region (GTK_EDITABLE (priv->hidden_entry), c - uri + 1, -1);
4912- else
4913- gtk_editable_select_region (GTK_EDITABLE (priv->hidden_entry), 5, -1);
4914- g_free (uri);
4915- }
4916-}
4917-
4918-static void
4919-read_later_resolved (YelpUri *uri,
4920- YelpWindow *window)
4921-{
4922- gchar *fulluri;
4923- const gchar *text = (const gchar *) g_object_get_data ((GObject *) uri, "link-text");
4924- YelpWindowPrivate *priv = GET_PRIV (window);
4925- YelpUri *base;
4926- gchar *doc_uri;
4927-
4928- g_object_get (priv->view, "yelp-uri", &base, NULL);
4929- doc_uri = yelp_uri_get_document_uri (uri);
4930- fulluri = yelp_uri_get_canonical_uri (uri);
4931-
4932- yelp_application_add_read_later (priv->application, doc_uri, fulluri, text);
4933-
4934- g_object_unref (base);
4935- g_free (doc_uri);
4936- g_free (fulluri);
4937-}
4938-
4939-static void
4940-window_read_later (GtkAction *action,
4941- YelpWindow *window)
4942-{
4943- YelpWindowPrivate *priv = GET_PRIV (window);
4944- YelpUri *uri;
4945- gchar *text;
4946-
4947- uri = yelp_view_get_active_link_uri (priv->view);
4948- text = yelp_view_get_active_link_text (priv->view);
4949-
4950- g_object_set_data_full ((GObject *) uri, "link-text", text, g_free);
4951-
4952- if (!yelp_uri_is_resolved (uri)) {
4953- g_signal_connect (uri, "resolved",
4954- G_CALLBACK (read_later_resolved),
4955- window);
4956- yelp_uri_resolve (uri);
4957- }
4958- else {
4959- read_later_resolved (uri, window);
4960- }
4961-}
4962-
4963-static gboolean
4964-read_later_clicked (GtkLinkButton *button,
4965- YelpWindow *window)
4966-{
4967- YelpWindowPrivate *priv = GET_PRIV (window);
4968- YelpUri *base;
4969- gchar *doc_uri;
4970- gchar *fulluri;
4971-
4972- fulluri = g_strdup (gtk_link_button_get_uri (button));
4973-
4974- g_object_get (priv->view, "yelp-uri", &base, NULL);
4975- doc_uri = yelp_uri_get_document_uri (base);
4976-
4977- yelp_application_remove_read_later (priv->application, doc_uri, fulluri);
4978-
4979- g_object_unref (base);
4980- g_free (doc_uri);
4981-
4982- yelp_view_load (priv->view, fulluri);
4983-
4984- g_free (fulluri);
4985- return TRUE;
4986-}
4987-
4988-static void
4989-app_read_later_changed (YelpApplication *app,
4990- const gchar *doc_uri,
4991- YelpWindow *window)
4992-{
4993- GVariant *value;
4994- GVariantIter *viter;
4995- gchar *uri, *title; /* do not free */
4996- GList *children;
4997- gboolean has_children = FALSE;
4998- YelpWindowPrivate *priv = GET_PRIV (window);
4999-
5000- children = gtk_container_get_children (GTK_CONTAINER (priv->read_later_vbox));
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: