Updated Korean translation
[yelp.git] / src / yelp-application.c
blob47a69991176fc7cd43999b7e44f0e55ba9987408
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;
69 gboolean fallback_help_list;
72 static void yelp_application_iface_init (YelpBookmarksInterface *iface);
73 static void yelp_application_dispose (GObject *object);
74 static void yelp_application_finalize (GObject *object);
76 static gboolean yelp_application_cmdline (GApplication *app,
77 gchar ***arguments,
78 gint *exit_status);
79 static void yelp_application_startup (GApplication *app);
80 static int yelp_application_command_line (GApplication *app,
81 GApplicationCommandLine *cmdline);
82 static void application_uri_resolved (YelpUri *uri,
83 YelpApplicationLoad *data);
84 static gboolean application_window_deleted (YelpWindow *window,
85 GdkEvent *event,
86 YelpApplication *app);
87 GSettings * application_get_doc_settings (YelpApplication *app,
88 const gchar *doc_uri);
89 static void application_adjust_font (GAction *action,
90 GVariant *parameter,
91 YelpApplication *app);
92 static void application_set_font_sensitivity (YelpApplication *app);
94 static void bookmarks_changed (GSettings *settings,
95 const gchar *key,
96 YelpApplication *app);
97 static gboolean window_resized (YelpWindow *window,
98 YelpApplication *app);
100 G_DEFINE_TYPE_WITH_CODE (YelpApplication, yelp_application, GTK_TYPE_APPLICATION,
101 G_IMPLEMENT_INTERFACE (YELP_TYPE_BOOKMARKS,
102 yelp_application_iface_init))
103 #define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_APPLICATION, YelpApplicationPrivate))
105 typedef struct _YelpApplicationPrivate YelpApplicationPrivate;
106 struct _YelpApplicationPrivate {
107 GSList *windows;
108 GHashTable *windows_by_document;
110 GPropertyAction *show_cursor_action;
111 GSimpleAction *larger_text_action;
112 GSimpleAction *smaller_text_action;
114 GSettingsBackend *backend;
115 GSettings *gsettings;
116 GHashTable *docsettings;
119 static void
120 yelp_application_init (YelpApplication *app)
122 YelpApplicationPrivate *priv = GET_PRIV (app);
123 priv->docsettings = g_hash_table_new_full (g_str_hash, g_str_equal,
124 (GDestroyNotify) g_free,
125 (GDestroyNotify) g_object_unref);
127 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
128 "app.yelp-application-show-cursor",
129 (const gchar*[]) {"F7", NULL});
130 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
131 "app.yelp-application-larger-text",
132 (const gchar*[]) {"<Control>plus", NULL});
133 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
134 "app.yelp-application-smaller-text",
135 (const gchar*[]) {"<Control>minus", NULL});
137 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
138 "win.yelp-window-find", (const gchar*[]) {"<Control>F", NULL});
139 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
140 "win.yelp-window-search", (const gchar*[]) {"<Control>S", NULL});
141 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
142 "win.yelp-window-new", (const gchar*[]) {"<Control>N", NULL});
143 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
144 "win.yelp-window-close", (const gchar*[]) {"<Control>W", NULL});
145 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
146 "win.yelp-window-ctrll", (const gchar*[]) {"<Control>L", NULL});
147 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
148 "win.yelp-view-print", (const gchar*[]) {"<Control>P", NULL});
150 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
151 "win.yelp-view-go-back",
152 (const gchar*[]) {"<Alt>Left", NULL});
153 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
154 "win.yelp-view-go-forward",
155 (const gchar*[]) {"<Alt>Right", NULL});
156 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
157 "win.yelp-view-go-previous",
158 (const gchar*[]) {"<Control>Page_Up", NULL});
159 gtk_application_set_accels_for_action (GTK_APPLICATION (app),
160 "win.yelp-view-go-next",
161 (const gchar*[]) {"<Control>Page_Down", NULL});
164 static void
165 yelp_application_class_init (YelpApplicationClass *klass)
167 GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
168 GObjectClass *object_class = G_OBJECT_CLASS (klass);
170 application_class->local_command_line = yelp_application_cmdline;
171 application_class->startup = yelp_application_startup;
172 application_class->command_line = yelp_application_command_line;
174 object_class->dispose = yelp_application_dispose;
175 object_class->finalize = yelp_application_finalize;
177 g_type_class_add_private (klass, sizeof (YelpApplicationPrivate));
180 static void
181 yelp_application_iface_init (YelpBookmarksInterface *iface)
183 iface->add_bookmark = yelp_application_add_bookmark;
184 iface->remove_bookmark = yelp_application_remove_bookmark;
185 iface->is_bookmarked = yelp_application_is_bookmarked;
188 static void
189 yelp_application_dispose (GObject *object)
191 YelpApplicationPrivate *priv = GET_PRIV (object);
193 if (priv->show_cursor_action) {
194 g_object_unref (priv->show_cursor_action);
195 priv->show_cursor_action = NULL;
198 if (priv->larger_text_action) {
199 g_object_unref (priv->larger_text_action);
200 priv->larger_text_action = NULL;
203 if (priv->smaller_text_action) {
204 g_object_unref (priv->smaller_text_action);
205 priv->smaller_text_action = NULL;
208 if (priv->gsettings) {
209 g_object_unref (priv->gsettings);
210 priv->gsettings = NULL;
213 G_OBJECT_CLASS (yelp_application_parent_class)->dispose (object);
216 static void
217 yelp_application_finalize (GObject *object)
219 YelpApplicationPrivate *priv = GET_PRIV (object);
221 g_hash_table_destroy (priv->windows_by_document);
222 g_hash_table_destroy (priv->docsettings);
224 G_OBJECT_CLASS (yelp_application_parent_class)->finalize (object);
228 static gboolean
229 yelp_application_cmdline (GApplication *app,
230 gchar ***arguments,
231 gint *exit_status)
233 GOptionContext *context;
234 gint argc = g_strv_length (*arguments);
235 gint i;
237 context = g_option_context_new (NULL);
238 g_option_context_add_group (context, gtk_get_option_group (FALSE));
239 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
240 g_option_context_parse (context, &argc, arguments, NULL);
242 for (i = 1; i < argc; i++) {
243 if (!strchr ((*arguments)[i], ':') && !((*arguments)[i][0] == '/')) {
244 GFile *base, *new;
245 gchar *cur, *newuri;
246 cur = g_get_current_dir ();
247 base = g_file_new_for_path (cur);
248 new = g_file_resolve_relative_path (base, (*arguments)[i]);
249 newuri = g_file_get_uri (new);
250 g_free ((*arguments)[i]);
251 (*arguments)[i] = newuri;
252 g_free (cur);
253 g_object_unref (new);
254 g_object_unref (base);
258 return G_APPLICATION_CLASS (yelp_application_parent_class)
259 ->local_command_line (app, arguments, exit_status);
262 static void
263 yelp_application_startup (GApplication *application)
265 YelpApplication *app = YELP_APPLICATION (application);
266 YelpApplicationPrivate *priv = GET_PRIV (app);
267 GMenu *menu, *section;
268 gchar *keyfile;
269 YelpSettings *settings;
271 g_set_application_name (N_("Help"));
273 /* chain up */
274 G_APPLICATION_CLASS (yelp_application_parent_class)->startup (application);
276 settings = yelp_settings_get_default ();
277 if (editor_mode)
278 yelp_settings_set_editor_mode (settings, TRUE);
279 priv->windows_by_document = g_hash_table_new_full (g_str_hash,
280 g_str_equal,
281 g_free,
282 NULL);
283 /* Use a config file for per-document settings, because
284 Ryan asked me to. */
285 keyfile = g_build_filename (g_get_user_config_dir (), "yelp", "yelp.cfg", NULL);
286 priv->backend = g_keyfile_settings_backend_new (keyfile, "/org/gnome/yelp/", "yelp");
287 g_free (keyfile);
289 /* But the main settings are in dconf */
290 priv->gsettings = g_settings_new ("org.gnome.yelp");
292 g_settings_bind (priv->gsettings, "show-cursor",
293 settings, "show-text-cursor",
294 G_SETTINGS_BIND_DEFAULT);
295 priv->show_cursor_action = g_property_action_new ("yelp-application-show-cursor",
296 settings, "show-text-cursor");
297 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->show_cursor_action));
299 g_settings_bind (priv->gsettings, "font-adjustment",
300 settings, "font-adjustment",
301 G_SETTINGS_BIND_DEFAULT);
303 priv->larger_text_action = g_simple_action_new ("yelp-application-larger-text", NULL);
304 g_signal_connect (priv->larger_text_action,
305 "activate",
306 G_CALLBACK (application_adjust_font),
307 app);
308 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->larger_text_action));
310 priv->smaller_text_action = g_simple_action_new ("yelp-application-smaller-text", NULL);
311 g_signal_connect (priv->smaller_text_action,
312 "activate",
313 G_CALLBACK (application_adjust_font),
314 app);
315 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (priv->smaller_text_action));
317 application_set_font_sensitivity (app);
319 menu = g_menu_new ();
320 section = g_menu_new ();
321 g_menu_append (section, _("New Window"), "win.yelp-window-new");
322 g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
323 g_object_unref (section);
324 section = g_menu_new ();
325 g_menu_append (section, _("Larger Text"), "app.yelp-application-larger-text");
326 g_menu_append (section, _("Smaller Text"), "app.yelp-application-smaller-text");
327 g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
328 g_object_unref (section);
329 gtk_application_set_app_menu (GTK_APPLICATION (application), G_MENU_MODEL (menu));
332 /******************************************************************************/
334 static void
335 application_adjust_font (GAction *action,
336 GVariant *parameter,
337 YelpApplication *app)
339 YelpApplicationPrivate *priv = GET_PRIV (app);
340 gint adjustment = g_settings_get_int (priv->gsettings, "font-adjustment");
341 gint adjust = g_str_equal (g_action_get_name (action), "yelp-application-larger-text") ? 1 : -1;
343 adjustment += adjust;
344 g_settings_set_int (priv->gsettings, "font-adjustment", adjustment);
346 application_set_font_sensitivity (app);
349 static void
350 application_set_font_sensitivity (YelpApplication *app)
352 YelpApplicationPrivate *priv = GET_PRIV (app);
353 YelpSettings *settings = yelp_settings_get_default ();
354 GParamSpec *spec = g_object_class_find_property ((GObjectClass *) YELP_SETTINGS_GET_CLASS (settings),
355 "font-adjustment");
356 gint adjustment = g_settings_get_int (priv->gsettings, "font-adjustment");
357 if (!G_PARAM_SPEC_INT (spec)) {
358 g_warning ("Expcected integer param spec for font-adjustment");
359 return;
361 g_simple_action_set_enabled (priv->larger_text_action,
362 adjustment < ((GParamSpecInt *) spec)->maximum);
363 g_simple_action_set_enabled (priv->smaller_text_action,
364 adjustment > ((GParamSpecInt *) spec)->minimum);
367 /******************************************************************************/
369 YelpApplication *
370 yelp_application_new (void)
372 YelpApplication *app;
374 app = g_object_new (YELP_TYPE_APPLICATION,
375 "application-id", "org.gnome.Yelp",
376 "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
377 "inactivity-timeout", 5000,
378 NULL);
380 return app;
383 /* consumes the uri */
384 static void
385 open_uri (YelpApplication *app,
386 YelpUri *uri,
387 gboolean new_window,
388 gboolean fallback_help_list)
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;
395 data->fallback_help_list = fallback_help_list;
397 g_signal_connect (uri, "resolved",
398 G_CALLBACK (application_uri_resolved),
399 data);
401 /* hold the app while resolving the uri so we don't exit while
402 * in the middle of the load
404 g_application_hold (G_APPLICATION (app));
406 yelp_uri_resolve (uri);
410 static int
411 yelp_application_command_line (GApplication *application,
412 GApplicationCommandLine *cmdline)
414 YelpApplication *app = YELP_APPLICATION (application);
415 gchar **argv;
416 int i;
418 argv = g_application_command_line_get_arguments (cmdline, NULL);
420 if (argv[1] == NULL)
421 open_uri (app, yelp_uri_new (DEFAULT_URI), FALSE, TRUE);
423 for (i = 1; argv[i]; i++)
424 open_uri (app, yelp_uri_new (argv[i]), FALSE, FALSE);
426 g_strfreev (argv);
428 return 0;
431 void
432 yelp_application_new_window (YelpApplication *app,
433 const gchar *uri)
435 if (uri)
436 open_uri (app, yelp_uri_new (uri), TRUE, FALSE);
437 else
438 open_uri (app, yelp_uri_new (DEFAULT_URI), TRUE, TRUE);
441 void
442 yelp_application_new_window_uri (YelpApplication *app,
443 YelpUri *uri)
445 open_uri (app, g_object_ref (uri), TRUE, FALSE);
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);
456 GFile *gfile;
458 /* We held the application while resolving the URI, so unhold now. */
459 g_application_release (G_APPLICATION (data->app));
461 /* Get the GFile associated with the URI, or NULL if not available */
462 gfile = yelp_uri_get_file (uri);
463 if (gfile == NULL && data->fallback_help_list) {
464 /* There is no file associated to the default uri, so we'll fallback
465 * to help-list: if we're told to do so. */
466 open_uri (data->app, yelp_uri_new ("help-list:"), data->new, FALSE);
467 g_object_unref (uri);
468 g_free (data);
469 return;
471 g_clear_object (&gfile);
473 doc_uri = yelp_uri_get_document_uri (uri);
475 if (data->new || !doc_uri)
476 window = NULL;
477 else
478 window = g_hash_table_lookup (priv->windows_by_document, doc_uri);
480 if (window == NULL) {
481 gint width, height;
482 GSettings *settings = application_get_doc_settings (data->app, doc_uri);
484 g_settings_get (settings, "geometry", "(ii)", &width, &height);
485 window = yelp_window_new (data->app);
486 gtk_window_set_default_size (GTK_WINDOW (window), width, height);
487 g_signal_connect (window, "resized", G_CALLBACK (window_resized), data->app);
488 priv->windows = g_slist_prepend (priv->windows, window);
490 if (!data->new) {
491 g_hash_table_insert (priv->windows_by_document, doc_uri, window);
492 g_object_set_data (G_OBJECT (window), "doc_uri", doc_uri);
494 else {
495 g_free (doc_uri);
498 g_signal_connect (window, "delete-event",
499 G_CALLBACK (application_window_deleted), data->app);
500 gtk_window_set_application (GTK_WINDOW (window),
501 GTK_APPLICATION (data->app));
503 else {
504 g_free (doc_uri);
507 yelp_window_load_uri (window, uri);
509 gtk_widget_show_all (GTK_WIDGET (window));
511 /* Metacity no longer does anything useful with gtk_window_present */
512 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
514 #ifdef GDK_WINDOWING_X11
515 if (GDK_IS_X11_WINDOW (gdk_window)){
516 if (gdk_window)
517 gdk_x11_window_move_to_current_desktop (gdk_window);
519 /* Ensure we actually present the window when invoked from the command
520 * line. This is somewhat evil, but the minor evil of Yelp stealing
521 * focus (after you requested it) is outweighed for me by the major
522 * evil of no help window appearing when you click Help.
524 if (data->timestamp == 0)
525 data->timestamp = gdk_x11_get_server_time (gtk_widget_get_window (GTK_WIDGET (window)));
527 gtk_window_present_with_time (GTK_WINDOW (window), data->timestamp);
529 else
530 #endif
531 gtk_window_present (GTK_WINDOW (window));
533 g_object_unref (uri);
534 g_free (data);
537 static gboolean
538 application_window_deleted (YelpWindow *window,
539 GdkEvent *event,
540 YelpApplication *app)
542 gchar *doc_uri; /* owned by windows_by_document */
543 YelpApplicationPrivate *priv = GET_PRIV (app);
545 priv->windows = g_slist_remove (priv->windows, window);
546 doc_uri = g_object_get_data (G_OBJECT (window), "doc_uri");
547 if (doc_uri)
548 g_hash_table_remove (priv->windows_by_document, doc_uri);
550 return FALSE;
553 GSettings *
554 application_get_doc_settings (YelpApplication *app, const gchar *doc_uri)
556 YelpApplicationPrivate *priv = GET_PRIV (app);
557 GSettings *settings = g_hash_table_lookup (priv->docsettings, doc_uri);
558 if (settings == NULL) {
559 gchar *tmp, *key, *settings_path;
560 tmp = g_uri_escape_string (doc_uri, "", FALSE);
561 settings_path = g_strconcat ("/org/gnome/yelp/documents/", tmp, "/", NULL);
562 g_free (tmp);
563 if (priv->backend)
564 settings = g_settings_new_with_backend_and_path ("org.gnome.yelp.documents",
565 priv->backend,
566 settings_path);
567 else
568 settings = g_settings_new_with_path ("org.gnome.yelp.documents",
569 settings_path);
570 key = g_strdup (doc_uri);
571 g_hash_table_insert (priv->docsettings, key, settings);
572 g_object_set_data ((GObject *) settings, "doc_uri", key);
573 g_signal_connect (settings, "changed::bookmarks",
574 G_CALLBACK (bookmarks_changed), app);
575 g_free (settings_path);
577 return settings;
580 /******************************************************************************/
582 void
583 yelp_application_add_bookmark (YelpBookmarks *bookmarks,
584 const gchar *doc_uri,
585 const gchar *page_id,
586 const gchar *icon,
587 const gchar *title)
589 GSettings *settings;
590 YelpApplication *app = YELP_APPLICATION (bookmarks);
592 g_return_if_fail (page_id);
593 g_return_if_fail (doc_uri);
595 settings = application_get_doc_settings (app, doc_uri);
597 if (settings) {
598 GVariantBuilder builder;
599 GVariantIter *iter;
600 gchar *this_id, *this_icon, *this_title;
601 gboolean broken = FALSE;
602 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
603 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
604 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
605 if (g_str_equal (page_id, this_id)) {
606 /* Already have this bookmark */
607 broken = TRUE;
608 break;
610 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
612 g_variant_iter_free (iter);
614 if (!broken) {
615 GVariant *value;
616 g_variant_builder_add (&builder, "(sss)", page_id, icon, title);
617 value = g_variant_builder_end (&builder);
618 g_settings_set_value (settings, "bookmarks", value);
623 void
624 yelp_application_remove_bookmark (YelpBookmarks *bookmarks,
625 const gchar *doc_uri,
626 const gchar *page_id)
628 GSettings *settings;
629 YelpApplication *app = YELP_APPLICATION (bookmarks);
631 g_return_if_fail (page_id);
632 g_return_if_fail (doc_uri);
634 settings = application_get_doc_settings (app, doc_uri);
636 if (settings) {
637 GVariantBuilder builder;
638 GVariantIter *iter;
639 gchar *this_id, *this_icon, *this_title;
640 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
641 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
642 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
643 if (!g_str_equal (page_id, this_id))
644 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
646 g_variant_iter_free (iter);
648 g_settings_set_value (settings, "bookmarks", g_variant_builder_end (&builder));
652 gboolean
653 yelp_application_is_bookmarked (YelpBookmarks *bookmarks,
654 const gchar *doc_uri,
655 const gchar *page_id)
657 GVariant *stored_bookmarks;
658 GVariantIter *iter;
659 gboolean ret = FALSE;
660 gchar *this_id = NULL;
661 GSettings *settings;
662 YelpApplication *app = YELP_APPLICATION (bookmarks);
664 g_return_val_if_fail (page_id, FALSE);
665 g_return_val_if_fail (doc_uri, FALSE);
667 settings = application_get_doc_settings (app, doc_uri);
668 if (settings == NULL)
669 return FALSE;
671 stored_bookmarks = g_settings_get_value (settings, "bookmarks");
672 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
673 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, NULL, NULL)) {
674 if (g_str_equal (page_id, this_id)) {
675 ret = TRUE;
676 break;
680 g_variant_iter_free (iter);
681 g_variant_unref (stored_bookmarks);
682 return ret;
685 void
686 yelp_application_update_bookmarks (YelpApplication *app,
687 const gchar *doc_uri,
688 const gchar *page_id,
689 const gchar *icon,
690 const gchar *title)
692 GSettings *settings;
694 g_return_if_fail (page_id);
695 g_return_if_fail (doc_uri);
697 settings = application_get_doc_settings (app, doc_uri);
699 if (settings) {
700 GVariantBuilder builder;
701 GVariantIter *iter;
702 gchar *this_id, *this_icon, *this_title;
703 gboolean updated = FALSE;
704 g_settings_get (settings, "bookmarks", "a(sss)", &iter);
705 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sss)"));
706 while (g_variant_iter_loop (iter, "(&s&s&s)", &this_id, &this_icon, &this_title)) {
707 if (g_str_equal (page_id, this_id)) {
708 if (icon && !g_str_equal (icon, this_icon)) {
709 this_icon = (gchar *) icon;
710 updated = TRUE;
712 if (title && !g_str_equal (title, this_title)) {
713 this_title = (gchar *) title;
714 updated = TRUE;
716 if (!updated)
717 break;
719 g_variant_builder_add (&builder, "(sss)", this_id, this_icon, this_title);
721 g_variant_iter_free (iter);
723 if (updated)
724 g_settings_set_value (settings, "bookmarks",
725 g_variant_builder_end (&builder));
726 else
727 g_variant_builder_clear (&builder);
731 GVariant *
732 yelp_application_get_bookmarks (YelpApplication *app,
733 const gchar *doc_uri)
735 GSettings *settings = application_get_doc_settings (app, doc_uri);
737 return g_settings_get_value (settings, "bookmarks");
740 static void
741 bookmarks_changed (GSettings *settings,
742 const gchar *key,
743 YelpApplication *app)
745 const gchar *doc_uri = g_object_get_data ((GObject *) settings, "doc_uri");
746 if (doc_uri)
747 g_signal_emit_by_name (app, "bookmarks-changed", doc_uri);
750 static gboolean
751 window_resized (YelpWindow *window,
752 YelpApplication *app)
754 YelpApplicationPrivate *priv = GET_PRIV (app);
755 YelpUri *uri;
756 gchar *doc_uri;
757 GSettings *settings;
759 uri = yelp_window_get_uri (window);
760 if (uri == NULL)
761 return FALSE;
762 doc_uri = yelp_uri_get_document_uri (uri);
763 if (doc_uri == NULL) {
764 g_object_unref (uri);
765 return FALSE;
767 settings = g_hash_table_lookup (priv->docsettings, doc_uri);
769 if (settings) {
770 gint width, height;
771 yelp_window_get_geometry (window, &width, &height);
772 g_settings_set (settings, "geometry", "(ii)", width, height);
775 g_free (doc_uri);
776 g_object_unref (uri);
778 return FALSE;