yelp-window: Drop gtk bug workaround because mclasen fixed the bug
[yelp.git] / src / yelp-application.c
blobedcc3a1a667da04dd760db02ff3f45fd244508a1
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_init (YelpApplication *app);
72 static void yelp_application_class_init (YelpApplicationClass *klass);
73 static void yelp_application_iface_init (YelpBookmarksInterface *iface);
74 static void yelp_application_dispose (GObject *object);
75 static void yelp_application_finalize (GObject *object);
77 static gboolean yelp_application_cmdline (GApplication *app,
78 gchar ***arguments,
79 gint *exit_status);
80 static void yelp_application_startup (GApplication *app);
81 static int yelp_application_command_line (GApplication *app,
82 GApplicationCommandLine *cmdline);
83 static void application_uri_resolved (YelpUri *uri,
84 YelpApplicationLoad *data);
85 static gboolean application_window_deleted (YelpWindow *window,
86 GdkEvent *event,
87 YelpApplication *app);
88 GSettings * application_get_doc_settings (YelpApplication *app,
89 const gchar *doc_uri);
90 static void application_adjust_font (GAction *action,
91 GVariant *parameter,
92 YelpApplication *app);
93 static void application_set_font_sensitivity (YelpApplication *app);
95 static void bookmarks_changed (GSettings *settings,
96 const gchar *key,
97 YelpApplication *app);
98 static gboolean window_resized (YelpWindow *window,
99 YelpApplication *app);
101 G_DEFINE_TYPE_WITH_CODE (YelpApplication, yelp_application, GTK_TYPE_APPLICATION,
102 G_IMPLEMENT_INTERFACE (YELP_TYPE_BOOKMARKS,
103 yelp_application_iface_init))
104 #define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_APPLICATION, YelpApplicationPrivate))
106 typedef struct _YelpApplicationPrivate YelpApplicationPrivate;
107 struct _YelpApplicationPrivate {
108 GSList *windows;
109 GHashTable *windows_by_document;
111 GPropertyAction *show_cursor_action;
112 GSimpleAction *larger_text_action;
113 GSimpleAction *smaller_text_action;
115 GSettingsBackend *backend;
116 GSettings *gsettings;
117 GHashTable *docsettings;
120 static void
121 yelp_application_init (YelpApplication *app)
123 YelpApplicationPrivate *priv = GET_PRIV (app);
124 priv->docsettings = g_hash_table_new_full (g_str_hash, g_str_equal,
125 (GDestroyNotify) g_free,
126 (GDestroyNotify) g_object_unref);
128 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
129 "app.yelp-application-show-cursor",
130 (const gchar*[]) {"F7", NULL});
131 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
132 "app.yelp-application-larger-text",
133 (const gchar*[]) {"<Control>plus", NULL});
134 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
135 "app.yelp-application-smaller-text",
136 (const gchar*[]) {"<Control>minus", NULL});
138 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
139 "win.yelp-window-find", (const gchar*[]) {"<Control>F", NULL});
140 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
141 "win.yelp-window-search", (const gchar*[]) {"<Control>S", NULL});
142 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
143 "win.yelp-window-new", (const gchar*[]) {"<Control>N", NULL});
144 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
145 "win.yelp-window-close", (const gchar*[]) {"<Control>W", NULL});
146 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
147 "win.yelp-window-ctrll", (const gchar*[]) {"<Control>L", NULL});
148 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
149 "win.yelp-view-print", (const gchar*[]) {"<Control>P", NULL});
151 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
152 "win.yelp-view-go-back",
153 (const gchar*[]) {"<Alt>Left", NULL});
154 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
155 "win.yelp-view-go-forward",
156 (const gchar*[]) {"<Alt>Right", NULL});
157 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
158 "win.yelp-view-go-previous",
159 (const gchar*[]) {"<Control>Page_Up", NULL});
160 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
161 "win.yelp-view-go-next",
162 (const gchar*[]) {"<Control>Page_Down", NULL});
165 static void
166 yelp_application_class_init (YelpApplicationClass *klass)
168 GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
169 GObjectClass *object_class = G_OBJECT_CLASS (klass);
171 application_class->local_command_line = yelp_application_cmdline;
172 application_class->startup = yelp_application_startup;
173 application_class->command_line = yelp_application_command_line;
175 object_class->dispose = yelp_application_dispose;
176 object_class->finalize = yelp_application_finalize;
178 g_type_class_add_private (klass, sizeof (YelpApplicationPrivate));
181 static void
182 yelp_application_iface_init (YelpBookmarksInterface *iface)
184 iface->add_bookmark = yelp_application_add_bookmark;
185 iface->remove_bookmark = yelp_application_remove_bookmark;
186 iface->is_bookmarked = yelp_application_is_bookmarked;
189 static void
190 yelp_application_dispose (GObject *object)
192 YelpApplicationPrivate *priv = GET_PRIV (object);
194 if (priv->show_cursor_action) {
195 g_object_unref (priv->show_cursor_action);
196 priv->show_cursor_action = NULL;
199 if (priv->larger_text_action) {
200 g_object_unref (priv->larger_text_action);
201 priv->larger_text_action = NULL;
204 if (priv->smaller_text_action) {
205 g_object_unref (priv->smaller_text_action);
206 priv->smaller_text_action = NULL;
209 if (priv->gsettings) {
210 g_object_unref (priv->gsettings);
211 priv->gsettings = NULL;
214 G_OBJECT_CLASS (yelp_application_parent_class)->dispose (object);
217 static void
218 yelp_application_finalize (GObject *object)
220 YelpApplicationPrivate *priv = GET_PRIV (object);
222 g_hash_table_destroy (priv->windows_by_document);
223 g_hash_table_destroy (priv->docsettings);
225 G_OBJECT_CLASS (yelp_application_parent_class)->finalize (object);
229 static gboolean
230 yelp_application_cmdline (GApplication *app,
231 gchar ***arguments,
232 gint *exit_status)
234 GOptionContext *context;
235 gint argc = g_strv_length (*arguments);
236 gint i;
238 context = g_option_context_new (NULL);
239 g_option_context_add_group (context, gtk_get_option_group (TRUE));
240 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
241 g_option_context_parse (context, &argc, arguments, NULL);
243 for (i = 1; i < argc; i++) {
244 if (!strchr ((*arguments)[i], ':') && !((*arguments)[i][0] == '/')) {
245 GFile *base, *new;
246 gchar *cur, *newuri;
247 cur = g_get_current_dir ();
248 base = g_file_new_for_path (cur);
249 new = g_file_resolve_relative_path (base, (*arguments)[i]);
250 newuri = g_file_get_uri (new);
251 g_free ((*arguments)[i]);
252 (*arguments)[i] = newuri;
253 g_free (cur);
254 g_object_unref (new);
255 g_object_unref (base);
259 return G_APPLICATION_CLASS (yelp_application_parent_class)
260 ->local_command_line (app, arguments, exit_status);
263 static void
264 yelp_application_startup (GApplication *application)
266 YelpApplication *app = YELP_APPLICATION (application);
267 YelpApplicationPrivate *priv = GET_PRIV (app);
268 GMenu *menu, *section;
269 gchar *keyfile;
270 YelpSettings *settings;
272 g_set_application_name (N_("Help"));
274 /* chain up */
275 G_APPLICATION_CLASS (yelp_application_parent_class)->startup (application);
277 settings = yelp_settings_get_default ();
278 if (editor_mode)
279 yelp_settings_set_editor_mode (settings, TRUE);
280 priv->windows_by_document = g_hash_table_new_full (g_str_hash,
281 g_str_equal,
282 g_free,
283 NULL);
284 /* Use a config file for per-document settings, because
285 Ryan asked me to. */
286 keyfile = g_build_filename (g_get_user_config_dir (), "yelp", "yelp.cfg", NULL);
287 priv->backend = g_keyfile_settings_backend_new (keyfile, "/org/gnome/yelp/", "yelp");
288 g_free (keyfile);
290 /* But the main settings are in dconf */
291 priv->gsettings = g_settings_new ("org.gnome.yelp");
293 g_settings_bind (priv->gsettings, "show-cursor",
294 settings, "show-text-cursor",
295 G_SETTINGS_BIND_DEFAULT);
296 priv->show_cursor_action = g_property_action_new ("yelp-application-show-cursor",
297 settings, "show-text-cursor");
298 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->show_cursor_action));
300 g_settings_bind (priv->gsettings, "font-adjustment",
301 settings, "font-adjustment",
302 G_SETTINGS_BIND_DEFAULT);
304 priv->larger_text_action = g_simple_action_new ("yelp-application-larger-text", NULL);
305 g_signal_connect (priv->larger_text_action,
306 "activate",
307 G_CALLBACK (application_adjust_font),
308 app);
309 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->larger_text_action));
311 priv->smaller_text_action = g_simple_action_new ("yelp-application-smaller-text", NULL);
312 g_signal_connect (priv->smaller_text_action,
313 "activate",
314 G_CALLBACK (application_adjust_font),
315 app);
316 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->smaller_text_action));
318 application_set_font_sensitivity (app);
320 menu = g_menu_new ();
321 section = g_menu_new ();
322 g_menu_append (section, _("New Window"), "win.yelp-window-new");
323 g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
324 g_object_unref (section);
325 section = g_menu_new ();
326 g_menu_append (section, _("Larger Text"), "app.yelp-application-larger-text");
327 g_menu_append (section, _("Smaller Text"), "app.yelp-application-smaller-text");
328 g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
329 g_object_unref (section);
330 gtk_application_set_app_menu (GTK_APPLICATION (application), G_MENU_MODEL (menu));
333 /******************************************************************************/
335 static void
336 application_adjust_font (GAction *action,
337 GVariant *parameter,
338 YelpApplication *app)
340 YelpApplicationPrivate *priv = GET_PRIV (app);
341 gint adjustment = g_settings_get_int (priv->gsettings, "font-adjustment");
342 gint adjust = g_str_equal (g_action_get_name (action), "yelp-application-larger-text") ? 1 : -1;
344 adjustment += adjust;
345 g_settings_set_int (priv->gsettings, "font-adjustment", adjustment);
347 application_set_font_sensitivity (app);
350 static void
351 application_set_font_sensitivity (YelpApplication *app)
353 YelpApplicationPrivate *priv = GET_PRIV (app);
354 YelpSettings *settings = yelp_settings_get_default ();
355 GParamSpec *spec = g_object_class_find_property ((GObjectClass *) YELP_SETTINGS_GET_CLASS (settings),
356 "font-adjustment");
357 gint adjustment = g_settings_get_int (priv->gsettings, "font-adjustment");
358 if (!G_PARAM_SPEC_INT (spec)) {
359 g_warning ("Expcected integer param spec for font-adjustment");
360 return;
362 g_simple_action_set_enabled (priv->larger_text_action,
363 adjustment < ((GParamSpecInt *) spec)->maximum);
364 g_simple_action_set_enabled (priv->smaller_text_action,
365 adjustment > ((GParamSpecInt *) spec)->minimum);
368 /******************************************************************************/
370 YelpApplication *
371 yelp_application_new (void)
373 YelpApplication *app;
375 app = g_object_new (YELP_TYPE_APPLICATION,
376 "application-id", "org.gnome.Yelp",
377 "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
378 "inactivity-timeout", 5000,
379 NULL);
381 return app;
384 /* consumes the uri */
385 static void
386 open_uri (YelpApplication *app,
387 YelpUri *uri,
388 gboolean new_window)
390 YelpApplicationLoad *data;
391 data = g_new (YelpApplicationLoad, 1);
392 data->app = app;
393 data->timestamp = gtk_get_current_event_time ();
394 data->new = new_window;
396 g_signal_connect (uri, "resolved",
397 G_CALLBACK (application_uri_resolved),
398 data);
400 /* hold the app while resolving the uri so we don't exit while
401 * in the middle of the load
403 g_application_hold (G_APPLICATION (app));
405 yelp_uri_resolve (uri);
409 static int
410 yelp_application_command_line (GApplication *application,
411 GApplicationCommandLine *cmdline)
413 YelpApplication *app = YELP_APPLICATION (application);
414 gchar **argv;
415 int i;
417 argv = g_application_command_line_get_arguments (cmdline, NULL);
419 if (argv[1] == NULL)
420 open_uri (app, yelp_uri_new (DEFAULT_URI), FALSE);
422 for (i = 1; argv[i]; i++)
423 open_uri (app, yelp_uri_new (argv[i]), FALSE);
425 g_strfreev (argv);
427 return 0;
430 void
431 yelp_application_new_window (YelpApplication *app,
432 const gchar *uri)
434 YelpUri *yuri;
436 yuri = yelp_uri_new (uri ? uri : DEFAULT_URI);
438 yelp_application_new_window_uri (app, yuri);
441 void
442 yelp_application_new_window_uri (YelpApplication *app,
443 YelpUri *uri)
445 open_uri (app, g_object_ref (uri), TRUE);
448 static void
449 application_uri_resolved (YelpUri *uri,
450 YelpApplicationLoad *data)
452 YelpWindow *window;
453 gchar *doc_uri;
454 GdkWindow *gdk_window;
455 YelpApplicationPrivate *priv = GET_PRIV (data->app);
457 /* We held the application while resolving the URI, so unhold now. */
458 g_application_release (G_APPLICATION (data->app));
460 doc_uri = yelp_uri_get_document_uri (uri);
462 if (data->new || !doc_uri)
463 window = NULL;
464 else
465 window = g_hash_table_lookup (priv->windows_by_document, doc_uri);
467 if (window == NULL) {
468 gint width, height;
469 GSettings *settings = application_get_doc_settings (data->app, doc_uri);
471 g_settings_get (settings, "geometry", "(ii)", &width, &height);
472 window = yelp_window_new (data->app);
473 gtk_window_set_default_size (GTK_WINDOW (window), width, height);
474 g_signal_connect (window, "resized", G_CALLBACK (window_resized), data->app);
475 priv->windows = g_slist_prepend (priv->windows, window);
477 if (!data->new) {
478 g_hash_table_insert (priv->windows_by_document, doc_uri, window);
479 g_object_set_data (G_OBJECT (window), "doc_uri", doc_uri);
481 else {
482 g_free (doc_uri);
485 g_signal_connect (window, "delete-event",
486 G_CALLBACK (application_window_deleted), data->app);
487 gtk_window_set_application (GTK_WINDOW (window),
488 GTK_APPLICATION (data->app));
490 else {
491 g_free (doc_uri);
494 yelp_window_load_uri (window, uri);
496 gtk_widget_show_all (GTK_WIDGET (window));
498 /* Metacity no longer does anything useful with gtk_window_present */
499 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
501 #ifdef GDK_WINDOWING_X11
502 if (GDK_IS_X11_WINDOW (gdk_window)){
503 if (gdk_window)
504 gdk_x11_window_move_to_current_desktop (gdk_window);
506 /* Ensure we actually present the window when invoked from the command
507 * line. This is somewhat evil, but the minor evil of Yelp stealing
508 * focus (after you requested it) is outweighed for me by the major
509 * evil of no help window appearing when you click Help.
511 if (data->timestamp == 0)
512 data->timestamp = gdk_x11_get_server_time (gtk_widget_get_window (GTK_WIDGET (window)));
514 gtk_window_present_with_time (GTK_WINDOW (window), data->timestamp);
516 else
517 #endif
518 gtk_window_present (GTK_WINDOW (window));
520 g_object_unref (uri);
521 g_free (data);
524 static gboolean
525 application_window_deleted (YelpWindow *window,
526 GdkEvent *event,
527 YelpApplication *app)
529 gchar *doc_uri; /* owned by windows_by_document */
530 YelpApplicationPrivate *priv = GET_PRIV (app);
532 priv->windows = g_slist_remove (priv->windows, window);
533 doc_uri = g_object_get_data (G_OBJECT (window), "doc_uri");
534 if (doc_uri)
535 g_hash_table_remove (priv->windows_by_document, doc_uri);
537 return FALSE;
540 GSettings *
541 application_get_doc_settings (YelpApplication *app, const gchar *doc_uri)
543 YelpApplicationPrivate *priv = GET_PRIV (app);
544 GSettings *settings = g_hash_table_lookup (priv->docsettings, doc_uri);
545 if (settings == NULL) {
546 gchar *tmp, *key, *settings_path;
547 tmp = g_uri_escape_string (doc_uri, "", FALSE);
548 settings_path = g_strconcat ("/org/gnome/yelp/documents/", tmp, "/", NULL);
549 g_free (tmp);
550 if (priv->backend)
551 settings = g_settings_new_with_backend_and_path ("org.gnome.yelp.documents",
552 priv->backend,
553 settings_path);
554 else
555 settings = g_settings_new_with_path ("org.gnome.yelp.documents",
556 settings_path);
557 key = g_strdup (doc_uri);
558 g_hash_table_insert (priv->docsettings, key, settings);
559 g_object_set_data ((GObject *) settings, "doc_uri", key);
560 g_signal_connect (settings, "changed::bookmarks",
561 G_CALLBACK (bookmarks_changed), app);
562 g_free (settings_path);
564 return settings;
567 /******************************************************************************/
569 void
570 yelp_application_add_bookmark (YelpBookmarks *bookmarks,
571 const gchar *doc_uri,
572 const gchar *page_id,
573 const gchar *icon,
574 const gchar *title)
576 GSettings *settings;
577 YelpApplication *app = YELP_APPLICATION (bookmarks);
579 g_return_if_fail (page_id);
580 g_return_if_fail (doc_uri);
582 settings = application_get_doc_settings (app, doc_uri);
584 if (settings) {
585 GVariantBuilder builder;
586 GVariantIter *iter;
587 gchar *this_id, *this_icon, *this_title;
588 gboolean broken = FALSE;
589 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
590 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
591 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
592 if (g_str_equal (page_id, this_id)) {
593 /* Already have this bookmark */
594 broken = TRUE;
595 break;
597 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
599 g_variant_iter_free (iter);
601 if (!broken) {
602 GVariant *value;
603 g_variant_builder_add (&builder, "(sss)", page_id, icon, title);
604 value = g_variant_builder_end (&builder);
605 g_settings_set_value (settings, "bookmarks", value);
610 void
611 yelp_application_remove_bookmark (YelpBookmarks *bookmarks,
612 const gchar *doc_uri,
613 const gchar *page_id)
615 GSettings *settings;
616 YelpApplication *app = YELP_APPLICATION (bookmarks);
618 g_return_if_fail (page_id);
619 g_return_if_fail (doc_uri);
621 settings = application_get_doc_settings (app, doc_uri);
623 if (settings) {
624 GVariantBuilder builder;
625 GVariantIter *iter;
626 gchar *this_id, *this_icon, *this_title;
627 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
628 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
629 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
630 if (!g_str_equal (page_id, this_id))
631 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
633 g_variant_iter_free (iter);
635 g_settings_set_value (settings, "bookmarks", g_variant_builder_end (&builder));
639 gboolean
640 yelp_application_is_bookmarked (YelpBookmarks *bookmarks,
641 const gchar *doc_uri,
642 const gchar *page_id)
644 GVariant *stored_bookmarks;
645 GVariantIter *iter;
646 gboolean ret = FALSE;
647 gchar *this_id = NULL;
648 GSettings *settings;
649 YelpApplication *app = YELP_APPLICATION (bookmarks);
651 g_return_val_if_fail (page_id, FALSE);
652 g_return_val_if_fail (doc_uri, FALSE);
654 settings = application_get_doc_settings (app, doc_uri);
655 if (settings == NULL)
656 return FALSE;
658 stored_bookmarks = g_settings_get_value (settings, "bookmarks");
659 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
660 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, NULL, NULL)) {
661 if (g_str_equal (page_id, this_id)) {
662 ret = TRUE;
663 break;
667 g_variant_iter_free (iter);
668 g_variant_unref (stored_bookmarks);
669 return ret;
672 void
673 yelp_application_update_bookmarks (YelpApplication *app,
674 const gchar *doc_uri,
675 const gchar *page_id,
676 const gchar *icon,
677 const gchar *title)
679 GSettings *settings;
681 g_return_if_fail (page_id);
682 g_return_if_fail (doc_uri);
684 settings = application_get_doc_settings (app, doc_uri);
686 if (settings) {
687 GVariantBuilder builder;
688 GVariantIter *iter;
689 gchar *this_id, *this_icon, *this_title;
690 gboolean updated = FALSE;
691 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
692 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
693 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
694 if (g_str_equal (page_id, this_id)) {
695 if (icon && !g_str_equal (icon, this_icon)) {
696 this_icon = (gchar *) icon;
697 updated = TRUE;
699 if (title && !g_str_equal (title, this_title)) {
700 this_title = (gchar *) title;
701 updated = TRUE;
703 if (!updated)
704 break;
706 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
708 g_variant_iter_free (iter);
710 if (updated)
711 g_settings_set_value (settings, "bookmarks",
712 g_variant_builder_end (&builder));
713 else
714 g_variant_builder_clear (&builder);
718 GVariant *
719 yelp_application_get_bookmarks (YelpApplication *app,
720 const gchar *doc_uri)
722 GSettings *settings = application_get_doc_settings (app, doc_uri);
724 return g_settings_get_value (settings, "bookmarks");
727 static void
728 bookmarks_changed (GSettings *settings,
729 const gchar *key,
730 YelpApplication *app)
732 const gchar *doc_uri = g_object_get_data ((GObject *) settings, "doc_uri");
733 if (doc_uri)
734 g_signal_emit_by_name (app, "bookmarks-changed", doc_uri);
737 static gboolean
738 window_resized (YelpWindow *window,
739 YelpApplication *app)
741 YelpApplicationPrivate *priv = GET_PRIV (app);
742 YelpUri *uri;
743 gchar *doc_uri;
744 GSettings *settings;
746 uri = yelp_window_get_uri (window);
747 if (uri == NULL)
748 return FALSE;
749 doc_uri = yelp_uri_get_document_uri (uri);
750 if (doc_uri == NULL) {
751 g_object_unref (uri);
752 return FALSE;
754 settings = g_hash_table_lookup (priv->docsettings, doc_uri);
756 if (settings) {
757 gint width, height;
758 yelp_window_get_geometry (window, &width, &height);
759 g_settings_set (settings, "geometry", "(ii)", width, height);
762 g_free (doc_uri);
763 g_object_unref (uri);
765 return FALSE;