~midori/midori/cmake-make-dist

« back to all changes in this revision

Viewing changes to midori/main.c

  • Committer: Christian Dywan
  • Date: 2008-06-01 21:47:27 UTC
  • Revision ID: git-v1:b511f12b9b4b063610161f2229b94a24a86be0fc
Rename folder 'src' to 'midori'

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
 
3
 
 
4
 This library is free software; you can redistribute it and/or
 
5
 modify it under the terms of the GNU Lesser General Public
 
6
 License as published by the Free Software Foundation; either
 
7
 version 2.1 of the License, or (at your option) any later version.
 
8
 
 
9
 See the file COPYING for the full license text.
 
10
*/
 
11
 
 
12
#include "main.h"
 
13
 
 
14
#include "sokoke.h"
 
15
#include "search.h"
 
16
 
 
17
#include "midori-app.h"
 
18
#include "midori-websettings.h"
 
19
#include "midori-trash.h"
 
20
#include "midori-browser.h"
 
21
#include "gjs.h"
 
22
 
 
23
#include <katze/katze.h>
 
24
#include <string.h>
 
25
#include <gtk/gtk.h>
 
26
 
 
27
#include "config.h"
 
28
 
 
29
#ifdef ENABLE_NLS
 
30
    #include <libintl.h>
 
31
#endif
 
32
 
 
33
// -- stock icons
 
34
 
 
35
static void stock_items_init(void)
 
36
{
 
37
    static GtkStockItem items[] =
 
38
    {
 
39
        { STOCK_LOCK_OPEN },
 
40
        { STOCK_LOCK_SECURE },
 
41
        { STOCK_LOCK_BROKEN },
 
42
        { STOCK_SCRIPT },
 
43
        { STOCK_THEME },
 
44
        { STOCK_USER_TRASH },
 
45
 
 
46
        { STOCK_BOOKMARK,       N_("Bookmark"), 0, 0, NULL },
 
47
        { STOCK_BOOKMARK_ADD,   N_("_Add Bookmark"), 0, 0, NULL },
 
48
        { STOCK_FORM_FILL,      N_("_Form Fill"), 0, 0, NULL },
 
49
        { STOCK_HOMEPAGE,       N_("_Homepage"), 0, 0, NULL },
 
50
        { STOCK_TAB_NEW,        N_("New _Tab"), 0, 0, NULL },
 
51
        { STOCK_WINDOW_NEW,     N_("New _Window"), 0, 0, NULL },
 
52
        #if !GTK_CHECK_VERSION(2, 10, 0)
 
53
        { GTK_STOCK_SELECT_ALL, N_("Select _All"), 0, 0, NULL },
 
54
        #endif
 
55
        #if !GTK_CHECK_VERSION(2, 8, 0)
 
56
        { GTK_STOCK_FULLSCREEN, N_("_Fullscreen"), 0, 0, NULL },
 
57
        { GTK_STOCK_LEAVE_FULLSCREEN, N_("_Leave Fullscreen"), 0, 0, NULL },
 
58
        #endif
 
59
    };
 
60
    GtkIconFactory* factory = gtk_icon_factory_new();
 
61
    guint i;
 
62
    for(i = 0; i < (guint)G_N_ELEMENTS(items); i++)
 
63
    {
 
64
        GtkIconSource* iconSource = gtk_icon_source_new();
 
65
        gtk_icon_source_set_icon_name(iconSource, items[i].stock_id);
 
66
        GtkIconSet* iconSet = gtk_icon_set_new();
 
67
        gtk_icon_set_add_source(iconSet, iconSource);
 
68
        gtk_icon_source_free(iconSource);
 
69
        gtk_icon_factory_add(factory, items[i].stock_id, iconSet);
 
70
        gtk_icon_set_unref(iconSet);
 
71
    }
 
72
    gtk_stock_add_static(items, G_N_ELEMENTS(items));
 
73
    gtk_icon_factory_add_default(factory);
 
74
    g_object_unref(factory);
 
75
}
 
76
 
 
77
static void
 
78
locale_init (void)
 
79
{
 
80
#ifdef ENABLE_NLS
 
81
    bindtextdomain (GETTEXT_PACKAGE, MIDORI_LOCALEDIR);
 
82
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
83
    textdomain (GETTEXT_PACKAGE);
 
84
#endif
 
85
}
 
86
 
 
87
static MidoriWebSettings*
 
88
settings_new_from_file (const gchar* filename)
 
89
{
 
90
    MidoriWebSettings* settings = midori_web_settings_new ();
 
91
    GKeyFile* key_file = g_key_file_new ();
 
92
    GError* error = NULL;
 
93
    if (!g_key_file_load_from_file (key_file, filename,
 
94
                                   G_KEY_FILE_KEEP_COMMENTS, &error))
 
95
    {
 
96
        if (error->code != G_FILE_ERROR_NOENT)
 
97
            printf (_("The configuration couldn't be loaded. %s\n"),
 
98
                    error->message);
 
99
        g_error_free (error);
 
100
    }
 
101
    GObjectClass* class = G_OBJECT_GET_CLASS (settings);
 
102
    guint i, n_properties;
 
103
    GParamSpec** pspecs = g_object_class_list_properties (class, &n_properties);
 
104
    for (i = 0; i < n_properties; i++)
 
105
    {
 
106
        GParamSpec* pspec = pspecs[i];
 
107
        if (!(pspec->flags & G_PARAM_WRITABLE))
 
108
            continue;
 
109
        GType type = G_PARAM_SPEC_TYPE (pspec);
 
110
        const gchar* property = g_param_spec_get_name (pspec);
 
111
        if (type == G_TYPE_PARAM_STRING)
 
112
        {
 
113
            gchar* string = sokoke_key_file_get_string_default (key_file,
 
114
                "settings", property,
 
115
                G_PARAM_SPEC_STRING (pspec)->default_value, NULL);
 
116
            g_object_set (settings, property, string, NULL);
 
117
            g_free (string);
 
118
        }
 
119
        else if (type == G_TYPE_PARAM_INT)
 
120
        {
 
121
            gint integer = sokoke_key_file_get_integer_default (key_file,
 
122
                "settings", property,
 
123
                G_PARAM_SPEC_INT (pspec)->default_value, NULL);
 
124
            g_object_set (settings, property, integer, NULL);
 
125
        }
 
126
        else if (type == G_TYPE_PARAM_FLOAT)
 
127
        {
 
128
            gdouble number = sokoke_key_file_get_double_default (key_file,
 
129
                "settings", property,
 
130
                G_PARAM_SPEC_FLOAT (pspec)->default_value, NULL);
 
131
            g_object_set (settings, property, number, NULL);
 
132
        }
 
133
        else if (type == G_TYPE_PARAM_BOOLEAN)
 
134
        {
 
135
            gboolean boolean = sokoke_key_file_get_boolean_default (key_file,
 
136
                "settings", property,
 
137
                G_PARAM_SPEC_BOOLEAN (pspec)->default_value, NULL);
 
138
            g_object_set (settings, property, boolean, NULL);
 
139
        }
 
140
        else if (type == G_TYPE_PARAM_ENUM)
 
141
        {
 
142
            GEnumClass* enum_class = G_ENUM_CLASS (
 
143
                g_type_class_ref (pspec->value_type));
 
144
            GEnumValue* enum_value = g_enum_get_value (enum_class,
 
145
                G_PARAM_SPEC_ENUM (pspec)->default_value);
 
146
            gchar* string = sokoke_key_file_get_string_default (key_file,
 
147
                "settings", property,
 
148
                enum_value->value_name, NULL);
 
149
            enum_value = g_enum_get_value_by_name (enum_class, string);
 
150
            if (enum_value)
 
151
                 g_object_set (settings, property, enum_value->value, NULL);
 
152
             else
 
153
                 g_warning (_("Value '%s' is invalid for %s"),
 
154
                            string, property);
 
155
 
 
156
            g_free (string);
 
157
            g_type_class_unref (enum_class);
 
158
        }
 
159
        else
 
160
            g_warning (_("Unhandled settings value '%s'"), property);
 
161
    }
 
162
    return settings;
 
163
}
 
164
 
 
165
static gboolean
 
166
settings_save_to_file (MidoriWebSettings* settings,
 
167
                       const gchar*       filename,
 
168
                       GError**           error)
 
169
{
 
170
    GKeyFile* key_file = g_key_file_new ();
 
171
    GObjectClass* class = G_OBJECT_GET_CLASS (settings);
 
172
    guint i, n_properties;
 
173
    GParamSpec** pspecs = g_object_class_list_properties (class, &n_properties);
 
174
    for (i = 0; i < n_properties; i++)
 
175
    {
 
176
        GParamSpec* pspec = pspecs[i];
 
177
        GType type = G_PARAM_SPEC_TYPE (pspec);
 
178
        const gchar* property = g_param_spec_get_name (pspec);
 
179
        if (!(pspec->flags & G_PARAM_WRITABLE))
 
180
        {
 
181
            gchar* comment = g_strdup_printf ("# %s", property);
 
182
            g_key_file_set_string (key_file, "settings", comment, "");
 
183
            g_free (comment);
 
184
            continue;
 
185
        }
 
186
        if (type == G_TYPE_PARAM_STRING)
 
187
        {
 
188
            const gchar* string;
 
189
            g_object_get (settings, property, &string, NULL);
 
190
            g_key_file_set_string (key_file, "settings", property,
 
191
                                   string ? string : "");
 
192
        }
 
193
        else if (type == G_TYPE_PARAM_INT)
 
194
        {
 
195
            gint integer;
 
196
            g_object_get (settings, property, &integer, NULL);
 
197
            g_key_file_set_integer (key_file, "settings", property, integer);
 
198
        }
 
199
        else if (type == G_TYPE_PARAM_FLOAT)
 
200
        {
 
201
            gdouble number;
 
202
            g_object_get (settings, property, &number, NULL);
 
203
            g_key_file_set_double (key_file, "settings", property, number);
 
204
        }
 
205
        else if (type == G_TYPE_PARAM_BOOLEAN)
 
206
        {
 
207
            gboolean boolean;
 
208
            g_object_get (settings, property, &boolean, NULL);
 
209
            g_key_file_set_boolean (key_file, "settings", property, boolean);
 
210
        }
 
211
        else if (type == G_TYPE_PARAM_ENUM)
 
212
        {
 
213
            GEnumClass* enum_class = G_ENUM_CLASS (
 
214
                g_type_class_ref (pspec->value_type));
 
215
            gint integer;
 
216
            g_object_get (settings, property, &integer, NULL);
 
217
            GEnumValue* enum_value = g_enum_get_value (enum_class, integer);
 
218
            g_key_file_set_string (key_file, "settings", property,
 
219
                                   enum_value->value_name);
 
220
        }
 
221
        else
 
222
            g_warning (_("Unhandled settings property '%s'"), property);
 
223
    }
 
224
    gboolean saved = sokoke_key_file_save_to_file (key_file, filename, error);
 
225
    g_key_file_free (key_file);
 
226
    return saved;
 
227
}
 
228
 
 
229
int
 
230
main (int argc, char** argv)
 
231
{
 
232
    MidoriStartup load_on_startup;
 
233
    gchar* homepage;
 
234
 
 
235
    locale_init ();
 
236
    g_set_application_name (_("midori"));
 
237
 
 
238
    // Parse cli options
 
239
    gboolean version = FALSE;
 
240
    GOptionEntry entries[] =
 
241
    {
 
242
     { "version", 'v', 0, G_OPTION_ARG_NONE, &version,
 
243
       N_("Display program version"), NULL },
 
244
     { NULL }
 
245
    };
 
246
 
 
247
    GError* error = NULL;
 
248
    if (!gtk_init_with_args (&argc, &argv, _("[URL]"), entries,
 
249
                             GETTEXT_PACKAGE, &error))
 
250
    {
 
251
        g_error_free (error);
 
252
        return 1;
 
253
    }
 
254
 
 
255
    if (version)
 
256
    {
 
257
        g_print (
 
258
          "%s %s - Copyright (c) 2007-2008 Christian Dywan\n\n"
 
259
          "GTK+2:  \t\t%s\n"
 
260
          "WebKit: \t\t%s\n"
 
261
          "Libsexy:\t\t%s\n"
 
262
          "libXML2:\t\t%s\n"
 
263
          "\n"
 
264
          "%s:\t\t%s\n"
 
265
          "\n"
 
266
          "%s\n"
 
267
          "\t%s\n"
 
268
          "%s\n"
 
269
          "\thttp://software.twotoasts.de\n",
 
270
          _("midori"), PACKAGE_VERSION,
 
271
          GTK_VER, WEBKIT_VER, LIBSEXY_VER, LIBXML_VER,
 
272
          _("Debugging"), SOKOKE_DEBUG_,
 
273
          _("Please report comments, suggestions and bugs to:"),
 
274
          PACKAGE_BUGREPORT,
 
275
          _("Check for new versions at:")
 
276
        );
 
277
        return 0;
 
278
    }
 
279
 
 
280
    // Standalone gjs support
 
281
    if (argc > 1 && argv[1] && g_str_has_suffix (argv[1], ".js"))
 
282
    {
 
283
        JSGlobalContextRef js_context = gjs_global_context_new ();
 
284
        gchar* exception = NULL;
 
285
        gjs_script_from_file (js_context, argv[1], &exception);
 
286
        JSGlobalContextRelease (js_context);
 
287
        if (!exception)
 
288
            return 0;
 
289
        printf ("%s - Exception: %s\n", argv[1], exception);
 
290
        return 1;
 
291
    }
 
292
 
 
293
    // Load configuration files
 
294
    GString* error_messages = g_string_new (NULL);
 
295
    gchar* config_path = g_build_filename (g_get_user_config_dir (),
 
296
                                           PACKAGE_NAME, NULL);
 
297
    g_mkdir_with_parents (config_path, 0755);
 
298
    gchar* config_file = g_build_filename (config_path, "config", NULL);
 
299
    error = NULL;
 
300
    MidoriWebSettings* settings = settings_new_from_file (config_file);
 
301
    katze_assign (config_file, g_build_filename (config_path, "accels", NULL));
 
302
    gtk_accel_map_load (config_file);
 
303
    katze_assign (config_file, g_build_filename (config_path, "search", NULL));
 
304
    error = NULL;
 
305
    searchEngines = search_engines_new ();
 
306
    if (!search_engines_from_file (&searchEngines, config_file, &error))
 
307
    {
 
308
        // FIXME: We may have a "file empty" error, how do we recognize that?
 
309
        /*if (error->code != G_FILE_ERROR_NOENT)
 
310
            g_string_append_printf (error_messages,
 
311
                _("The search engines couldn't be loaded. %s\n"),
 
312
                error->message);*/
 
313
        g_error_free (error);
 
314
    }
 
315
    katze_assign (config_file, g_build_filename (config_path, "bookmarks.xbel",
 
316
                                                 NULL));
 
317
    bookmarks = katze_xbel_folder_new();
 
318
    error = NULL;
 
319
    if (!katze_xbel_folder_from_file (bookmarks, config_file, &error))
 
320
    {
 
321
        if (error->code != G_FILE_ERROR_NOENT)
 
322
            g_string_append_printf (error_messages,
 
323
                _("The bookmarks couldn't be loaded. %s\n"), error->message);
 
324
        g_error_free (error);
 
325
    }
 
326
    g_free (config_file);
 
327
    KatzeXbelItem* _session = katze_xbel_folder_new ();
 
328
    g_object_get (settings, "load-on-startup", &load_on_startup, NULL);
 
329
    if (load_on_startup == MIDORI_STARTUP_LAST_OPEN_PAGES)
 
330
    {
 
331
        config_file = g_build_filename (config_path, "session.xbel", NULL);
 
332
        error = NULL;
 
333
        if (!katze_xbel_folder_from_file (_session, config_file, &error))
 
334
        {
 
335
            if (error->code != G_FILE_ERROR_NOENT)
 
336
                g_string_append_printf (error_messages,
 
337
                    _("The session couldn't be loaded. %s\n"), error->message);
 
338
            g_error_free (error);
 
339
        }
 
340
        g_free (config_file);
 
341
    }
 
342
    config_file = g_build_filename (config_path, "tabtrash.xbel", NULL);
 
343
    KatzeXbelItem* xbel_trash = katze_xbel_folder_new ();
 
344
    error = NULL;
 
345
    if (!katze_xbel_folder_from_file (xbel_trash, config_file, &error))
 
346
    {
 
347
        if (error->code != G_FILE_ERROR_NOENT)
 
348
            g_string_append_printf(error_messages,
 
349
                _("The trash couldn't be loaded. %s\n"), error->message);
 
350
        g_error_free (error);
 
351
    }
 
352
    g_free (config_file);
 
353
 
 
354
    // In case of errors
 
355
    if (error_messages->len)
 
356
    {
 
357
        GtkWidget* dialog = gtk_message_dialog_new(NULL
 
358
         , 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_NONE
 
359
         , _("The following errors occured:"));
 
360
        gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
 
361
        gtk_window_set_title(GTK_WINDOW(dialog), g_get_application_name());
 
362
        // FIXME: Use custom program icon
 
363
        gtk_window_set_icon_name(GTK_WINDOW(dialog), "web-browser");
 
364
        gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog)
 
365
         , "%s", error_messages->str);
 
366
        gtk_dialog_add_buttons(GTK_DIALOG(dialog)
 
367
         , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL
 
368
         , "_Ignore", GTK_RESPONSE_ACCEPT
 
369
         , NULL);
 
370
        if(gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT)
 
371
        {
 
372
            search_engines_free(searchEngines);
 
373
            katze_xbel_item_unref(bookmarks);
 
374
            katze_xbel_item_unref(_session);
 
375
            katze_xbel_item_unref(xbel_trash);
 
376
            g_string_free(error_messages, TRUE);
 
377
            return 0;
 
378
        }
 
379
        gtk_widget_destroy(dialog);
 
380
        /* FIXME: Since we will overwrite files that could not be loaded
 
381
                  , would we want to make backups? */
 
382
    }
 
383
    g_string_free (error_messages, TRUE);
 
384
 
 
385
    // TODO: Handle any number of separate uris from argv
 
386
    // Open as many tabs as we have uris, seperated by pipes
 
387
    gchar* uri = argc > 1 ? strtok (g_strdup(argv[1]), "|") : NULL;
 
388
    while (uri != NULL)
 
389
    {
 
390
        KatzeXbelItem* item = katze_xbel_bookmark_new ();
 
391
        gchar* uri_ready = sokoke_magic_uri (uri, NULL);
 
392
        katze_xbel_bookmark_set_href (item, uri_ready);
 
393
        g_free (uri_ready);
 
394
        katze_xbel_folder_append_item (_session, item);
 
395
        uri = strtok (NULL, "|");
 
396
    }
 
397
    g_free (uri);
 
398
 
 
399
    if (katze_xbel_folder_is_empty (_session))
 
400
    {
 
401
        KatzeXbelItem* item = katze_xbel_bookmark_new ();
 
402
        if (load_on_startup == MIDORI_STARTUP_BLANK_PAGE)
 
403
            katze_xbel_bookmark_set_href (item, "");
 
404
        else
 
405
        {
 
406
            g_object_get (settings, "homepage", &homepage, NULL);
 
407
            katze_xbel_bookmark_set_href (item, homepage);
 
408
            g_free (homepage);
 
409
        }
 
410
        katze_xbel_folder_prepend_item (_session, item);
 
411
    }
 
412
    g_free (config_path);
 
413
 
 
414
    stock_items_init ();
 
415
 
 
416
    MidoriApp* app = midori_app_new ();
 
417
    g_object_set (app, "settings", settings, NULL);
 
418
 
 
419
    MidoriTrash* trash = midori_app_get_trash (app);
 
420
    guint n = katze_xbel_folder_get_n_items (xbel_trash);
 
421
    guint i;
 
422
    for (i = 0; i < n; i++)
 
423
    {
 
424
        KatzeXbelItem* item = katze_xbel_folder_get_nth_item (xbel_trash, i);
 
425
        midori_trash_prepend_xbel_item (trash, item);
 
426
    }
 
427
 
 
428
    MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER,
 
429
                                           "settings", settings,
 
430
                                           "trash", trash,
 
431
                                           NULL);
 
432
    g_signal_emit_by_name (app, "add-browser", browser);
 
433
 
 
434
    gtk_widget_show (GTK_WIDGET (browser));
 
435
 
 
436
    KatzeXbelItem* session = katze_xbel_folder_new ();
 
437
    n = katze_xbel_folder_get_n_items (_session);
 
438
    for (i = 0; i < n; i++)
 
439
    {
 
440
        KatzeXbelItem* item = katze_xbel_folder_get_nth_item (_session, i);
 
441
        midori_browser_add_xbel_item (browser, item);
 
442
    }
 
443
    // FIXME: Switch to the last active page
 
444
    KatzeXbelItem* item = katze_xbel_folder_get_nth_item (_session, 0);
 
445
    if (!strcmp (katze_xbel_bookmark_get_href (item), ""))
 
446
        midori_browser_activate_action (browser, "Location");
 
447
    katze_xbel_item_unref (_session);
 
448
 
 
449
    // Load extensions
 
450
    JSGlobalContextRef js_context = gjs_global_context_new ();
 
451
    // FIXME: We want to honor system installed addons as well
 
452
    gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME,
 
453
                                          "extensions", NULL);
 
454
    GDir* addon_dir = g_dir_open (addon_path, 0, NULL);
 
455
    if (addon_dir)
 
456
    {
 
457
        const gchar* filename;
 
458
        while ((filename = g_dir_read_name (addon_dir)))
 
459
        {
 
460
            gchar* fullname = g_build_filename (addon_path, filename, NULL);
 
461
            gchar* exception = NULL;
 
462
            gjs_script_from_file (js_context, fullname, &exception);
 
463
            if (exception)
 
464
            // FIXME: Do we want to print this somewhere else?
 
465
            // FIXME Convert the filename to UTF8
 
466
                printf ("%s - Exception: %s\n", filename, exception);
 
467
            g_free (fullname);
 
468
        }
 
469
        g_dir_close (addon_dir);
 
470
    }
 
471
 
 
472
    gtk_main ();
 
473
 
 
474
    JSGlobalContextRelease (js_context);
 
475
 
 
476
    // Save configuration files
 
477
    config_path = g_build_filename (g_get_user_config_dir(), PACKAGE_NAME,
 
478
                                    NULL);
 
479
    g_mkdir_with_parents (config_path, 0755);
 
480
    config_file = g_build_filename (config_path, "search", NULL);
 
481
    error = NULL;
 
482
    if (!search_engines_to_file (searchEngines, config_file, &error))
 
483
    {
 
484
        g_warning (_("The search engines couldn't be saved. %s"), error->message);
 
485
        g_error_free (error);
 
486
    }
 
487
    search_engines_free(searchEngines);
 
488
    g_free (config_file);
 
489
    config_file = g_build_filename (config_path, "bookmarks.xbel", NULL);
 
490
    error = NULL;
 
491
    if (!katze_xbel_folder_to_file (bookmarks, config_file, &error))
 
492
    {
 
493
        g_warning (_("The bookmarks couldn't be saved. %s"), error->message);
 
494
        g_error_free (error);
 
495
    }
 
496
    katze_xbel_item_unref(bookmarks);
 
497
    g_free (config_file);
 
498
    config_file = g_build_filename (config_path, "tabtrash.xbel", NULL);
 
499
    error = NULL;
 
500
    if (!katze_xbel_folder_to_file (xbel_trash, config_file, &error))
 
501
    {
 
502
        g_warning (_("The trash couldn't be saved. %s"), error->message);
 
503
        g_error_free (error);
 
504
    }
 
505
    katze_xbel_item_unref (xbel_trash);
 
506
    g_object_get (settings, "load-on-startup", &load_on_startup, NULL);
 
507
    if(load_on_startup == MIDORI_STARTUP_LAST_OPEN_PAGES)
 
508
    {
 
509
        katze_assign (config_file, g_build_filename (config_path,
 
510
                                                     "session.xbel", NULL));
 
511
        error = NULL;
 
512
        if (!katze_xbel_folder_to_file (session, config_file, &error))
 
513
        {
 
514
            g_warning (_("The session couldn't be saved. %s"), error->message);
 
515
            g_error_free (error);
 
516
        }
 
517
    }
 
518
    katze_xbel_item_unref (session);
 
519
    katze_assign (config_file, g_build_filename (config_path, "config", NULL));
 
520
    error = NULL;
 
521
    if (!settings_save_to_file (settings, config_file, &error))
 
522
    {
 
523
        g_warning (_("The configuration couldn't be saved. %s"), error->message);
 
524
        g_error_free (error);
 
525
    }
 
526
    katze_assign (config_file, g_build_filename (config_path, "accels", NULL));
 
527
    gtk_accel_map_save (config_file);
 
528
    g_free (config_file);
 
529
    g_free (config_path);
 
530
    return 0;
 
531
}