Allow .docbook files as file path, #699995
[yelp.git] / src / yelp-application.c
blob4c5159a16808f4bc8eec5316c11414d3040e83b0
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Copyright (C) 2010 Shaun McCance <shaunm@gnome.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Shaun McCance <shaunm@gnome.org>
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #define G_SETTINGS_ENABLE_BACKEND
27 #include <gio/gio.h>
28 #include <gio/gsettingsbackend.h>
29 #include <glib/gi18n.h>
30 #include <gtk/gtk.h>
31 #ifdef GDK_WINDOWING_X11
32 #include <gdk/gdkx.h>
33 #endif
34 #include <stdlib.h>
36 #include "yelp-bookmarks.h"
37 #include "yelp-settings.h"
38 #include "yelp-view.h"
40 #include "yelp-application.h"
41 #include "yelp-window.h"
43 #define DEFAULT_URI "help:gnome-help"
45 static gboolean editor_mode = FALSE;
47 G_GNUC_NORETURN static gboolean
48 option_version_cb (const gchar *option_name,
49 const gchar *value,
50 gpointer data,
51 GError **error)
53 g_print ("%s %s\n", PACKAGE, VERSION);
55 exit (0);
58 static const GOptionEntry entries[] = {
59 {"editor-mode", 0, 0, G_OPTION_ARG_NONE, &editor_mode, N_("Turn on editor mode"), NULL},
60 { "version", 0, G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, option_version_cb, NULL, NULL },
61 { NULL }
64 typedef struct _YelpApplicationLoad YelpApplicationLoad;
65 struct _YelpApplicationLoad {
66 YelpApplication *app;
67 guint32 timestamp;
68 gboolean new;
71 static void yelp_application_iface_init (YelpBookmarksInterface *iface);
72 static void yelp_application_dispose (GObject *object);
73 static void yelp_application_finalize (GObject *object);
75 static gboolean yelp_application_cmdline (GApplication *app,
76 gchar ***arguments,
77 gint *exit_status);
78 static void yelp_application_startup (GApplication *app);
79 static int yelp_application_command_line (GApplication *app,
80 GApplicationCommandLine *cmdline);
81 static void application_uri_resolved (YelpUri *uri,
82 YelpApplicationLoad *data);
83 static gboolean application_window_deleted (YelpWindow *window,
84 GdkEvent *event,
85 YelpApplication *app);
86 GSettings * application_get_doc_settings (YelpApplication *app,
87 const gchar *doc_uri);
88 static void application_adjust_font (GAction *action,
89 GVariant *parameter,
90 YelpApplication *app);
91 static void application_set_font_sensitivity (YelpApplication *app);
93 static void bookmarks_changed (GSettings *settings,
94 const gchar *key,
95 YelpApplication *app);
96 static gboolean window_resized (YelpWindow *window,
97 YelpApplication *app);
99 G_DEFINE_TYPE_WITH_CODE (YelpApplication, yelp_application, GTK_TYPE_APPLICATION,
100 G_IMPLEMENT_INTERFACE (YELP_TYPE_BOOKMARKS,
101 yelp_application_iface_init))
102 #define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_APPLICATION, YelpApplicationPrivate))
104 typedef struct _YelpApplicationPrivate YelpApplicationPrivate;
105 struct _YelpApplicationPrivate {
106 GSList *windows;
107 GHashTable *windows_by_document;
109 GPropertyAction *show_cursor_action;
110 GSimpleAction *larger_text_action;
111 GSimpleAction *smaller_text_action;
113 GSettingsBackend *backend;
114 GSettings *gsettings;
115 GHashTable *docsettings;
118 static void
119 yelp_application_init (YelpApplication *app)
121 YelpApplicationPrivate *priv = GET_PRIV (app);
122 priv->docsettings = g_hash_table_new_full (g_str_hash, g_str_equal,
123 (GDestroyNotify) g_free,
124 (GDestroyNotify) g_object_unref);
126 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
127 "app.yelp-application-show-cursor",
128 (const gchar*[]) {"F7", NULL});
129 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
130 "app.yelp-application-larger-text",
131 (const gchar*[]) {"<Control>plus", NULL});
132 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
133 "app.yelp-application-smaller-text",
134 (const gchar*[]) {"<Control>minus", NULL});
136 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
137 "win.yelp-window-find", (const gchar*[]) {"<Control>F", NULL});
138 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
139 "win.yelp-window-search", (const gchar*[]) {"<Control>S", NULL});
140 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
141 "win.yelp-window-new", (const gchar*[]) {"<Control>N", NULL});
142 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
143 "win.yelp-window-close", (const gchar*[]) {"<Control>W", NULL});
144 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
145 "win.yelp-window-ctrll", (const gchar*[]) {"<Control>L", NULL});
146 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
147 "win.yelp-view-print", (const gchar*[]) {"<Control>P", NULL});
149 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
150 "win.yelp-view-go-back",
151 (const gchar*[]) {"<Alt>Left", NULL});
152 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
153 "win.yelp-view-go-forward",
154 (const gchar*[]) {"<Alt>Right", NULL});
155 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
156 "win.yelp-view-go-previous",
157 (const gchar*[]) {"<Control>Page_Up", NULL});
158 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
159 "win.yelp-view-go-next",
160 (const gchar*[]) {"<Control>Page_Down", NULL});
163 static void
164 yelp_application_class_init (YelpApplicationClass *klass)
166 GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
167 GObjectClass *object_class = G_OBJECT_CLASS (klass);
169 application_class->local_command_line = yelp_application_cmdline;
170 application_class->startup = yelp_application_startup;
171 application_class->command_line = yelp_application_command_line;
173 object_class->dispose = yelp_application_dispose;
174 object_class->finalize = yelp_application_finalize;
176 g_type_class_add_private (klass, sizeof (YelpApplicationPrivate));
179 static void
180 yelp_application_iface_init (YelpBookmarksInterface *iface)
182 iface->add_bookmark = yelp_application_add_bookmark;
183 iface->remove_bookmark = yelp_application_remove_bookmark;
184 iface->is_bookmarked = yelp_application_is_bookmarked;
187 static void
188 yelp_application_dispose (GObject *object)
190 YelpApplicationPrivate *priv = GET_PRIV (object);
192 if (priv->show_cursor_action) {
193 g_object_unref (priv->show_cursor_action);
194 priv->show_cursor_action = NULL;
197 if (priv->larger_text_action) {
198 g_object_unref (priv->larger_text_action);
199 priv->larger_text_action = NULL;
202 if (priv->smaller_text_action) {
203 g_object_unref (priv->smaller_text_action);
204 priv->smaller_text_action = NULL;
207 if (priv->gsettings) {
208 g_object_unref (priv->gsettings);
209 priv->gsettings = NULL;
212 G_OBJECT_CLASS (yelp_application_parent_class)->dispose (object);
215 static void
216 yelp_application_finalize (GObject *object)
218 YelpApplicationPrivate *priv = GET_PRIV (object);
220 g_hash_table_destroy (priv->windows_by_document);
221 g_hash_table_destroy (priv->docsettings);
223 G_OBJECT_CLASS (yelp_application_parent_class)->finalize (object);
227 static gboolean
228 yelp_application_cmdline (GApplication *app,
229 gchar ***arguments,
230 gint *exit_status)
232 GOptionContext *context;
233 gint argc = g_strv_length (*arguments);
234 gint i;
236 context = g_option_context_new (NULL);
237 g_option_context_add_group (context, gtk_get_option_group (FALSE));
238 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
239 g_option_context_parse (context, &argc, arguments, NULL);
241 for (i = 1; i < argc; i++) {
242 if (!strchr ((*arguments)[i], ':') && !((*arguments)[i][0] == '/')) {
243 GFile *base, *new;
244 gchar *cur, *newuri;
245 cur = g_get_current_dir ();
246 base = g_file_new_for_path (cur);
247 new = g_file_resolve_relative_path (base, (*arguments)[i]);
248 newuri = g_file_get_uri (new);
249 g_free ((*arguments)[i]);
250 (*arguments)[i] = newuri;
251 g_free (cur);
252 g_object_unref (new);
253 g_object_unref (base);
257 return G_APPLICATION_CLASS (yelp_application_parent_class)
258 ->local_command_line (app, arguments, exit_status);
261 static void
262 yelp_application_startup (GApplication *application)
264 YelpApplication *app = YELP_APPLICATION (application);
265 YelpApplicationPrivate *priv = GET_PRIV (app);
266 GMenu *menu, *section;
267 gchar *keyfile;
268 YelpSettings *settings;
270 g_set_application_name (N_("Help"));
272 /* chain up */
273 G_APPLICATION_CLASS (yelp_application_parent_class)->startup (application);
275 settings = yelp_settings_get_default ();
276 if (editor_mode)
277 yelp_settings_set_editor_mode (settings, TRUE);
278 priv->windows_by_document = g_hash_table_new_full (g_str_hash,
279 g_str_equal,
280 g_free,
281 NULL);
282 /* Use a config file for per-document settings, because
283 Ryan asked me to. */
284 keyfile = g_build_filename (g_get_user_config_dir (), "yelp", "yelp.cfg", NULL);
285 priv->backend = g_keyfile_settings_backend_new (keyfile, "/org/gnome/yelp/", "yelp");
286 g_free (keyfile);
288 /* But the main settings are in dconf */
289 priv->gsettings = g_settings_new ("org.gnome.yelp");
291 g_settings_bind (priv->gsettings, "show-cursor",
292 settings, "show-text-cursor",
293 G_SETTINGS_BIND_DEFAULT);
294 priv->show_cursor_action = g_property_action_new ("yelp-application-show-cursor",
295 settings, "show-text-cursor");
296 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->show_cursor_action));
298 g_settings_bind (priv->gsettings, "font-adjustment",
299 settings, "font-adjustment",
300 G_SETTINGS_BIND_DEFAULT);
302 priv->larger_text_action = g_simple_action_new ("yelp-application-larger-text", NULL);
303 g_signal_connect (priv->larger_text_action,
304 "activate",
305 G_CALLBACK (application_adjust_font),
306 app);
307 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->larger_text_action));
309 priv->smaller_text_action = g_simple_action_new ("yelp-application-smaller-text", NULL);
310 g_signal_connect (priv->smaller_text_action,
311 "activate",
312 G_CALLBACK (application_adjust_font),
313 app);
314 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->smaller_text_action));
316 application_set_font_sensitivity (app);
318 menu = g_menu_new ();
319 section = g_menu_new ();
320 g_menu_append (section, _("New Window"), "win.yelp-window-new");
321 g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
322 g_object_unref (section);
323 section = g_menu_new ();
324 g_menu_append (section, _("Larger Text"), "app.yelp-application-larger-text");
325 g_menu_append (section, _("Smaller Text"), "app.yelp-application-smaller-text");
326 g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
327 g_object_unref (section);
328 gtk_application_set_app_menu (GTK_APPLICATION (application), G_MENU_MODEL (menu));
331 /******************************************************************************/
333 static void
334 application_adjust_font (GAction *action,
335 GVariant *parameter,
336 YelpApplication *app)
338 YelpApplicationPrivate *priv = GET_PRIV (app);
339 gint adjustment = g_settings_get_int (priv->gsettings, "font-adjustment");
340 gint adjust = g_str_equal (g_action_get_name (action), "yelp-application-larger-text") ? 1 : -1;
342 adjustment += adjust;
343 g_settings_set_int (priv->gsettings, "font-adjustment", adjustment);
345 application_set_font_sensitivity (app);
348 static void
349 application_set_font_sensitivity (YelpApplication *app)
351 YelpApplicationPrivate *priv = GET_PRIV (app);
352 YelpSettings *settings = yelp_settings_get_default ();
353 GParamSpec *spec = g_object_class_find_property ((GObjectClass *) YELP_SETTINGS_GET_CLASS (settings),
354 "font-adjustment");
355 gint adjustment = g_settings_get_int (priv->gsettings, "font-adjustment");
356 if (!G_PARAM_SPEC_INT (spec)) {
357 g_warning ("Expcected integer param spec for font-adjustment");
358 return;
360 g_simple_action_set_enabled (priv->larger_text_action,
361 adjustment < ((GParamSpecInt *) spec)->maximum);
362 g_simple_action_set_enabled (priv->smaller_text_action,
363 adjustment > ((GParamSpecInt *) spec)->minimum);
366 /******************************************************************************/
368 YelpApplication *
369 yelp_application_new (void)
371 YelpApplication *app;
373 app = g_object_new (YELP_TYPE_APPLICATION,
374 "application-id", "org.gnome.Yelp",
375 "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
376 "inactivity-timeout", 5000,
377 NULL);
379 return app;
382 /* consumes the uri */
383 static void
384 open_uri (YelpApplication *app,
385 YelpUri *uri,
386 gboolean new_window)
388 YelpApplicationLoad *data;
389 data = g_new (YelpApplicationLoad, 1);
390 data->app = app;
391 data->timestamp = gtk_get_current_event_time ();
392 data->new = new_window;
394 g_signal_connect (uri, "resolved",
395 G_CALLBACK (application_uri_resolved),
396 data);
398 /* hold the app while resolving the uri so we don't exit while
399 * in the middle of the load
401 g_application_hold (G_APPLICATION (app));
403 yelp_uri_resolve (uri);
407 static int
408 yelp_application_command_line (GApplication *application,
409 GApplicationCommandLine *cmdline)
411 YelpApplication *app = YELP_APPLICATION (application);
412 gchar **argv;
413 int i;
415 argv = g_application_command_line_get_arguments (cmdline, NULL);
417 if (argv[1] == NULL)
418 open_uri (app, yelp_uri_new (DEFAULT_URI), FALSE);
420 for (i = 1; argv[i]; i++)
421 open_uri (app, yelp_uri_new (argv[i]), FALSE);
423 g_strfreev (argv);
425 return 0;
428 void
429 yelp_application_new_window (YelpApplication *app,
430 const gchar *uri)
432 YelpUri *yuri;
434 yuri = yelp_uri_new (uri ? uri : DEFAULT_URI);
436 yelp_application_new_window_uri (app, yuri);
439 void
440 yelp_application_new_window_uri (YelpApplication *app,
441 YelpUri *uri)
443 open_uri (app, g_object_ref (uri), TRUE);
446 static void
447 application_uri_resolved (YelpUri *uri,
448 YelpApplicationLoad *data)
450 YelpWindow *window;
451 gchar *doc_uri;
452 GdkWindow *gdk_window;
453 YelpApplicationPrivate *priv = GET_PRIV (data->app);
455 /* We held the application while resolving the URI, so unhold now. */
456 g_application_release (G_APPLICATION (data->app));
458 doc_uri = yelp_uri_get_document_uri (uri);
460 if (data->new || !doc_uri)
461 window = NULL;
462 else
463 window = g_hash_table_lookup (priv->windows_by_document, doc_uri);
465 if (window == NULL) {
466 gint width, height;
467 GSettings *settings = application_get_doc_settings (data->app, doc_uri);
469 g_settings_get (settings, "geometry", "(ii)", &width, &height);
470 window = yelp_window_new (data->app);
471 gtk_window_set_default_size (GTK_WINDOW (window), width, height);
472 g_signal_connect (window, "resized", G_CALLBACK (window_resized), data->app);
473 priv->windows = g_slist_prepend (priv->windows, window);
475 if (!data->new) {
476 g_hash_table_insert (priv->windows_by_document, doc_uri, window);
477 g_object_set_data (G_OBJECT (window), "doc_uri", doc_uri);
479 else {
480 g_free (doc_uri);
483 g_signal_connect (window, "delete-event",
484 G_CALLBACK (application_window_deleted), data->app);
485 gtk_window_set_application (GTK_WINDOW (window),
486 GTK_APPLICATION (data->app));
488 else {
489 g_free (doc_uri);
492 yelp_window_load_uri (window, uri);
494 gtk_widget_show_all (GTK_WIDGET (window));
496 /* Metacity no longer does anything useful with gtk_window_present */
497 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
499 #ifdef GDK_WINDOWING_X11
500 if (GDK_IS_X11_WINDOW (gdk_window)){
501 if (gdk_window)
502 gdk_x11_window_move_to_current_desktop (gdk_window);
504 /* Ensure we actually present the window when invoked from the command
505 * line. This is somewhat evil, but the minor evil of Yelp stealing
506 * focus (after you requested it) is outweighed for me by the major
507 * evil of no help window appearing when you click Help.
509 if (data->timestamp == 0)
510 data->timestamp = gdk_x11_get_server_time (gtk_widget_get_window (GTK_WIDGET (window)));
512 gtk_window_present_with_time (GTK_WINDOW (window), data->timestamp);
514 else
515 #endif
516 gtk_window_present (GTK_WINDOW (window));
518 g_object_unref (uri);
519 g_free (data);
522 static gboolean
523 application_window_deleted (YelpWindow *window,
524 GdkEvent *event,
525 YelpApplication *app)
527 gchar *doc_uri; /* owned by windows_by_document */
528 YelpApplicationPrivate *priv = GET_PRIV (app);
530 priv->windows = g_slist_remove (priv->windows, window);
531 doc_uri = g_object_get_data (G_OBJECT (window), "doc_uri");
532 if (doc_uri)
533 g_hash_table_remove (priv->windows_by_document, doc_uri);
535 return FALSE;
538 GSettings *
539 application_get_doc_settings (YelpApplication *app, const gchar *doc_uri)
541 YelpApplicationPrivate *priv = GET_PRIV (app);
542 GSettings *settings = g_hash_table_lookup (priv->docsettings, doc_uri);
543 if (settings == NULL) {
544 gchar *tmp, *key, *settings_path;
545 tmp = g_uri_escape_string (doc_uri, "", FALSE);
546 settings_path = g_strconcat ("/org/gnome/yelp/documents/", tmp, "/", NULL);
547 g_free (tmp);
548 if (priv->backend)
549 settings = g_settings_new_with_backend_and_path ("org.gnome.yelp.documents",
550 priv->backend,
551 settings_path);
552 else
553 settings = g_settings_new_with_path ("org.gnome.yelp.documents",
554 settings_path);
555 key = g_strdup (doc_uri);
556 g_hash_table_insert (priv->docsettings, key, settings);
557 g_object_set_data ((GObject *) settings, "doc_uri", key);
558 g_signal_connect (settings, "changed::bookmarks",
559 G_CALLBACK (bookmarks_changed), app);
560 g_free (settings_path);
562 return settings;
565 /******************************************************************************/
567 void
568 yelp_application_add_bookmark (YelpBookmarks *bookmarks,
569 const gchar *doc_uri,
570 const gchar *page_id,
571 const gchar *icon,
572 const gchar *title)
574 GSettings *settings;
575 YelpApplication *app = YELP_APPLICATION (bookmarks);
577 g_return_if_fail (page_id);
578 g_return_if_fail (doc_uri);
580 settings = application_get_doc_settings (app, doc_uri);
582 if (settings) {
583 GVariantBuilder builder;
584 GVariantIter *iter;
585 gchar *this_id, *this_icon, *this_title;
586 gboolean broken = FALSE;
587 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
588 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
589 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
590 if (g_str_equal (page_id, this_id)) {
591 /* Already have this bookmark */
592 broken = TRUE;
593 break;
595 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
597 g_variant_iter_free (iter);
599 if (!broken) {
600 GVariant *value;
601 g_variant_builder_add (&builder, "(sss)", page_id, icon, title);
602 value = g_variant_builder_end (&builder);
603 g_settings_set_value (settings, "bookmarks", value);
608 void
609 yelp_application_remove_bookmark (YelpBookmarks *bookmarks,
610 const gchar *doc_uri,
611 const gchar *page_id)
613 GSettings *settings;
614 YelpApplication *app = YELP_APPLICATION (bookmarks);
616 g_return_if_fail (page_id);
617 g_return_if_fail (doc_uri);
619 settings = application_get_doc_settings (app, doc_uri);
621 if (settings) {
622 GVariantBuilder builder;
623 GVariantIter *iter;
624 gchar *this_id, *this_icon, *this_title;
625 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
626 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
627 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
628 if (!g_str_equal (page_id, this_id))
629 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
631 g_variant_iter_free (iter);
633 g_settings_set_value (settings, "bookmarks", g_variant_builder_end (&builder));
637 gboolean
638 yelp_application_is_bookmarked (YelpBookmarks *bookmarks,
639 const gchar *doc_uri,
640 const gchar *page_id)
642 GVariant *stored_bookmarks;
643 GVariantIter *iter;
644 gboolean ret = FALSE;
645 gchar *this_id = NULL;
646 GSettings *settings;
647 YelpApplication *app = YELP_APPLICATION (bookmarks);
649 g_return_val_if_fail (page_id, FALSE);
650 g_return_val_if_fail (doc_uri, FALSE);
652 settings = application_get_doc_settings (app, doc_uri);
653 if (settings == NULL)
654 return FALSE;
656 stored_bookmarks = g_settings_get_value (settings, "bookmarks");
657 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
658 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, NULL, NULL)) {
659 if (g_str_equal (page_id, this_id)) {
660 ret = TRUE;
661 break;
665 g_variant_iter_free (iter);
666 g_variant_unref (stored_bookmarks);
667 return ret;
670 void
671 yelp_application_update_bookmarks (YelpApplication *app,
672 const gchar *doc_uri,
673 const gchar *page_id,
674 const gchar *icon,
675 const gchar *title)
677 GSettings *settings;
679 g_return_if_fail (page_id);
680 g_return_if_fail (doc_uri);
682 settings = application_get_doc_settings (app, doc_uri);
684 if (settings) {
685 GVariantBuilder builder;
686 GVariantIter *iter;
687 gchar *this_id, *this_icon, *this_title;
688 gboolean updated = FALSE;
689 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
690 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
691 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
692 if (g_str_equal (page_id, this_id)) {
693 if (icon && !g_str_equal (icon, this_icon)) {
694 this_icon = (gchar *) icon;
695 updated = TRUE;
697 if (title && !g_str_equal (title, this_title)) {
698 this_title = (gchar *) title;
699 updated = TRUE;
701 if (!updated)
702 break;
704 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
706 g_variant_iter_free (iter);
708 if (updated)
709 g_settings_set_value (settings, "bookmarks",
710 g_variant_builder_end (&builder));
711 else
712 g_variant_builder_clear (&builder);
716 GVariant *
717 yelp_application_get_bookmarks (YelpApplication *app,
718 const gchar *doc_uri)
720 GSettings *settings = application_get_doc_settings (app, doc_uri);
722 return g_settings_get_value (settings, "bookmarks");
725 static void
726 bookmarks_changed (GSettings *settings,
727 const gchar *key,
728 YelpApplication *app)
730 const gchar *doc_uri = g_object_get_data ((GObject *) settings, "doc_uri");
731 if (doc_uri)
732 g_signal_emit_by_name (app, "bookmarks-changed", doc_uri);
735 static gboolean
736 window_resized (YelpWindow *window,
737 YelpApplication *app)
739 YelpApplicationPrivate *priv = GET_PRIV (app);
740 YelpUri *uri;
741 gchar *doc_uri;
742 GSettings *settings;
744 uri = yelp_window_get_uri (window);
745 if (uri == NULL)
746 return FALSE;
747 doc_uri = yelp_uri_get_document_uri (uri);
748 if (doc_uri == NULL) {
749 g_object_unref (uri);
750 return FALSE;
752 settings = g_hash_table_lookup (priv->docsettings, doc_uri);
754 if (settings) {
755 gint width, height;
756 yelp_window_get_geometry (window, &width, &height);
757 g_settings_set (settings, "geometry", "(ii)", width, height);
760 g_free (doc_uri);
761 g_object_unref (uri);
763 return FALSE;