cdde1293ab
Switch configuration logic from a custom structure to fully rely on MidoriWebSettings. This includes revamping the preferences dialog. The old logic is not yet replaced completely, this will follow soon, thus several settings will have no effect right now.
521 lines
18 KiB
C
521 lines
18 KiB
C
/*
|
|
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
See the file COPYING for the full license text.
|
|
*/
|
|
|
|
#include "main.h"
|
|
|
|
#include "global.h"
|
|
#include "helpers.h"
|
|
#include "sokoke.h"
|
|
#include "search.h"
|
|
|
|
#include "midori-websettings.h"
|
|
#include "midori-trash.h"
|
|
#include "midori-browser.h"
|
|
#include <katze/katze.h>
|
|
|
|
#include <string.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef ENABLE_NLS
|
|
# include <libintl.h>
|
|
# if HAVE_LOCALE_H
|
|
# include <locale.h>
|
|
# endif
|
|
#endif
|
|
|
|
// -- stock icons
|
|
|
|
static void stock_items_init(void)
|
|
{
|
|
static GtkStockItem items[] =
|
|
{
|
|
{ STOCK_LOCK_OPEN },
|
|
{ STOCK_LOCK_SECURE },
|
|
{ STOCK_LOCK_BROKEN },
|
|
{ STOCK_SCRIPT },
|
|
{ STOCK_THEME },
|
|
{ STOCK_USER_TRASH },
|
|
|
|
{ STOCK_BOOKMARK, N_("Bookmark"), 0, 0, NULL },
|
|
{ STOCK_BOOKMARK_NEW, N_("New Bookmark"), 0, 0, NULL },
|
|
{ STOCK_FORM_FILL, N_("_Form Fill"), 0, 0, NULL },
|
|
{ STOCK_HOMEPAGE, N_("Homepage"), 0, 0, NULL },
|
|
{ STOCK_TAB_NEW, N_("New _Tab"), 0, 0, NULL },
|
|
{ STOCK_WINDOW_NEW, N_("New _Window"), 0, 0, NULL },
|
|
#if !GTK_CHECK_VERSION(2, 10, 0)
|
|
{ GTK_STOCK_SELECT_ALL, N_("Select _All", 0, 0, NULL },
|
|
#endif
|
|
#if !GTK_CHECK_VERSION(2, 8, 0)
|
|
{ GTK_STOCK_FULLSCREEN, N_("_Fullscreen"), 0, 0, NULL },
|
|
{ GTK_STOCK_FULLSCREEN, N_("_Leave Fullscreen"), 0, 0, NULL },
|
|
#endif
|
|
};
|
|
GtkIconFactory* factory = gtk_icon_factory_new();
|
|
guint i;
|
|
for(i = 0; i < (guint)G_N_ELEMENTS(items); i++)
|
|
{
|
|
GtkIconSource* iconSource = gtk_icon_source_new();
|
|
gtk_icon_source_set_icon_name(iconSource, items[i].stock_id);
|
|
GtkIconSet* iconSet = gtk_icon_set_new();
|
|
gtk_icon_set_add_source(iconSet, iconSource);
|
|
gtk_icon_source_free(iconSource);
|
|
gtk_icon_factory_add(factory, items[i].stock_id, iconSet);
|
|
gtk_icon_set_unref(iconSet);
|
|
}
|
|
gtk_stock_add_static(items, G_N_ELEMENTS(items));
|
|
gtk_icon_factory_add_default(factory);
|
|
g_object_unref(factory);
|
|
}
|
|
|
|
static gboolean
|
|
midori_browser_delete_event_cb (MidoriBrowser* browser,
|
|
GdkEvent* event,
|
|
GList* browsers)
|
|
{
|
|
browsers = g_list_remove (browsers, browser);
|
|
if (g_list_nth (browsers, 0))
|
|
return FALSE;
|
|
gtk_main_quit ();
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
midori_browser_quit_cb (MidoriBrowser* browser,
|
|
GdkEvent* event,
|
|
GList* browsers)
|
|
{
|
|
gtk_main_quit ();
|
|
}
|
|
|
|
static void
|
|
midori_browser_new_window_cb (MidoriBrowser* browser,
|
|
const gchar* uri,
|
|
GList* browsers)
|
|
{
|
|
MidoriBrowser* new_browser = g_object_new (MIDORI_TYPE_BROWSER,
|
|
// "settings", settings,
|
|
// "trash", trash,
|
|
NULL);
|
|
// gtk_window_add_accel_group (GTK_WINDOW (browser), accel_group);
|
|
g_object_connect (new_browser,
|
|
"signal::new-window", midori_browser_new_window_cb, browsers,
|
|
"signal::delete-event", midori_browser_delete_event_cb, browsers,
|
|
"signal::quit", midori_browser_quit_cb, browsers,
|
|
NULL);
|
|
browsers = g_list_prepend(browsers, new_browser);
|
|
gtk_widget_show (GTK_WIDGET (new_browser));
|
|
|
|
midori_browser_append_uri (new_browser, uri);
|
|
}
|
|
|
|
static void
|
|
locale_init (void)
|
|
{
|
|
#ifdef ENABLE_NLS
|
|
|
|
#if HAVE_LOCALE_H
|
|
setlocale (LC_ALL, "");
|
|
#endif
|
|
|
|
bindtextdomain (GETTEXT_PACKAGE, MIDORI_LOCALEDIR);
|
|
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
|
textdomain (GETTEXT_PACKAGE);
|
|
#endif
|
|
}
|
|
|
|
static MidoriWebSettings*
|
|
settings_new_from_file (const gchar* filename)
|
|
{
|
|
MidoriWebSettings* settings = midori_web_settings_new ();
|
|
GKeyFile* key_file = g_key_file_new ();
|
|
GError* error = NULL;
|
|
if (!g_key_file_load_from_file (key_file, filename,
|
|
G_KEY_FILE_KEEP_COMMENTS, &error))
|
|
{
|
|
if (error->code != G_FILE_ERROR_NOENT)
|
|
printf (_("The configuration couldn't be loaded. %s\n"),
|
|
error->message);
|
|
g_error_free (error);
|
|
}
|
|
GObjectClass* class = G_OBJECT_GET_CLASS (settings);
|
|
guint i, n_properties;
|
|
GParamSpec** pspecs = g_object_class_list_properties (class, &n_properties);
|
|
for (i = 0; i < n_properties; i++)
|
|
{
|
|
GParamSpec* pspec = pspecs[i];
|
|
if (!(pspec->flags & G_PARAM_WRITABLE))
|
|
continue;
|
|
GType type = G_PARAM_SPEC_TYPE (pspec);
|
|
const gchar* property = g_param_spec_get_name (pspec);
|
|
if (type == G_TYPE_PARAM_STRING)
|
|
{
|
|
gchar* string = sokoke_key_file_get_string_default (key_file,
|
|
"settings", property,
|
|
G_PARAM_SPEC_STRING (pspec)->default_value, NULL);
|
|
g_object_set (settings, property, string, NULL);
|
|
g_free (string);
|
|
}
|
|
else if (type == G_TYPE_PARAM_INT)
|
|
{
|
|
guint integer = sokoke_key_file_get_integer_default (key_file,
|
|
"settings", property,
|
|
G_PARAM_SPEC_INT (pspec)->default_value, NULL);
|
|
g_object_set (settings, property, integer, NULL);
|
|
}
|
|
else if (type == G_TYPE_PARAM_BOOLEAN)
|
|
{
|
|
gboolean boolean = sokoke_key_file_get_boolean_default (key_file,
|
|
"settings", property,
|
|
G_PARAM_SPEC_BOOLEAN (pspec)->default_value, NULL);
|
|
g_object_set (settings, property, boolean, NULL);
|
|
}
|
|
else if (type == G_TYPE_PARAM_ENUM)
|
|
{
|
|
GEnumClass* enum_class = G_ENUM_CLASS (
|
|
g_type_class_ref (pspec->value_type));
|
|
GEnumValue* enum_value = g_enum_get_value (enum_class,
|
|
G_PARAM_SPEC_ENUM (pspec)->default_value);
|
|
gchar* string = sokoke_key_file_get_string_default (key_file,
|
|
"settings", property,
|
|
enum_value->value_name, NULL);
|
|
enum_value = g_enum_get_value_by_name (enum_class, string);
|
|
g_object_set (settings, property, enum_value->value, NULL);
|
|
g_free (string);
|
|
g_type_class_unref (enum_class);
|
|
}
|
|
else
|
|
g_warning ("Unhandled settings property '%s'", property);
|
|
}
|
|
return settings;
|
|
}
|
|
|
|
static gboolean
|
|
settings_save_to_file (MidoriWebSettings* settings,
|
|
const gchar* filename,
|
|
GError** error)
|
|
{
|
|
GKeyFile* key_file = g_key_file_new ();
|
|
GObjectClass* class = G_OBJECT_GET_CLASS (settings);
|
|
guint i, n_properties;
|
|
GParamSpec** pspecs = g_object_class_list_properties (class, &n_properties);
|
|
for (i = 0; i < n_properties; i++)
|
|
{
|
|
GParamSpec* pspec = pspecs[i];
|
|
GType type = G_PARAM_SPEC_TYPE (pspec);
|
|
const gchar* property = g_param_spec_get_name (pspec);
|
|
if (!(pspec->flags & G_PARAM_WRITABLE))
|
|
{
|
|
gchar* comment = g_strdup_printf ("# %s", property);
|
|
g_key_file_set_string (key_file, "settings", comment, "");
|
|
g_free (comment);
|
|
continue;
|
|
}
|
|
if (type == G_TYPE_PARAM_STRING)
|
|
{
|
|
const gchar* string;
|
|
g_object_get (settings, property, &string, NULL);
|
|
g_key_file_set_string (key_file, "settings", property,
|
|
string ? string : "");
|
|
}
|
|
else if (type == G_TYPE_PARAM_INT)
|
|
{
|
|
gint integer;
|
|
g_object_get (settings, property, &integer, NULL);
|
|
g_key_file_set_integer (key_file, "settings", property, integer);
|
|
}
|
|
else if (type == G_TYPE_PARAM_BOOLEAN)
|
|
{
|
|
gboolean boolean;
|
|
g_object_get (settings, property, &boolean, NULL);
|
|
g_key_file_set_boolean (key_file, "settings", property, boolean);
|
|
}
|
|
else if (type == G_TYPE_PARAM_ENUM)
|
|
{
|
|
GEnumClass* enum_class = G_ENUM_CLASS (
|
|
g_type_class_ref (pspec->value_type));
|
|
gint integer;
|
|
g_object_get (settings, property, &integer, NULL);
|
|
GEnumValue* enum_value = g_enum_get_value (enum_class, integer);
|
|
g_key_file_set_string (key_file, "settings", property,
|
|
enum_value->value_name);
|
|
}
|
|
else
|
|
g_warning ("Unhandled settings property '%s'", property);
|
|
}
|
|
gboolean saved = sokoke_key_file_save_to_file (key_file, filename, error);
|
|
g_key_file_free (key_file);
|
|
return saved;
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
locale_init();
|
|
g_set_application_name(_("midori"));
|
|
|
|
// Parse cli options
|
|
gboolean version = FALSE;
|
|
GOptionEntry entries[] =
|
|
{
|
|
{ "version", 'v', 0, G_OPTION_ARG_NONE, &version,
|
|
N_("Display program version"), NULL }
|
|
};
|
|
|
|
GError* error = NULL;
|
|
if(!gtk_init_with_args(&argc, &argv, _("[URL]"), entries, GETTEXT_PACKAGE, &error))
|
|
{
|
|
g_error_free(error);
|
|
return 1;
|
|
}
|
|
|
|
if(version)
|
|
{
|
|
g_print(
|
|
"%s %s - Copyright (c) 2007-2008 Christian Dywan\n\n"
|
|
"GTK+2: \t\t%s\n"
|
|
"WebKit: \t\t%s\n"
|
|
"Libsexy:\t\t%s\n"
|
|
"libXML2:\t\t%s\n"
|
|
"\n"
|
|
"%s:\t\t%s\n"
|
|
"\n"
|
|
"%s\n"
|
|
"\t%s\n"
|
|
"%s\n"
|
|
"\thttp://software.twotoasts.de\n",
|
|
_("midori"), PACKAGE_VERSION,
|
|
GTK_VER, WEBKIT_VER, LIBSEXY_VER, LIBXML_VER,
|
|
_("Debugging"), SOKOKE_DEBUG_,
|
|
_("Please report comments, suggestions and bugs to:"),
|
|
PACKAGE_BUGREPORT,
|
|
_("Check for new versions at:")
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
// Load configuration files
|
|
GString* error_messages = g_string_new (NULL);
|
|
gchar* config_path = g_build_filename (g_get_user_config_dir (),
|
|
PACKAGE_NAME, NULL);
|
|
g_mkdir_with_parents (config_path, 0755);
|
|
gchar* config_file = g_build_filename (config_path, "config", NULL);
|
|
error = NULL;
|
|
MidoriWebSettings* settings = settings_new_from_file (config_file);
|
|
webSettings = settings;
|
|
katze_assign (config_file, g_build_filename (config_path, "accels", NULL));
|
|
gtk_accel_map_load (config_file);
|
|
katze_assign (config_file, g_build_filename (config_path, "search", NULL));
|
|
error = NULL;
|
|
searchEngines = search_engines_new ();
|
|
if (!search_engines_from_file (&searchEngines, config_file, &error))
|
|
{
|
|
// FIXME: We may have a "file empty" error, how do we recognize that?
|
|
/*if (error->code != G_FILE_ERROR_NOENT)
|
|
g_string_append_printf (error_messages,
|
|
_("The search engines couldn't be loaded. %s\n"),
|
|
error->message);*/
|
|
g_error_free (error);
|
|
}
|
|
katze_assign (config_file, g_build_filename (config_path, "bookmarks.xbel",
|
|
NULL));
|
|
bookmarks = katze_xbel_folder_new();
|
|
error = NULL;
|
|
if (!katze_xbel_folder_from_file (bookmarks, config_file, &error))
|
|
{
|
|
if (error->code != G_FILE_ERROR_NOENT)
|
|
g_string_append_printf (error_messages,
|
|
_("The bookmarks couldn't be loaded. %s\n"), error->message);
|
|
g_error_free (error);
|
|
}
|
|
g_free (config_file);
|
|
KatzeXbelItem* _session = katze_xbel_folder_new();
|
|
config = config_new ();
|
|
if(config->startup == CONFIG_STARTUP_SESSION)
|
|
{
|
|
config_file = g_build_filename (config_path, "session.xbel", NULL);
|
|
error = NULL;
|
|
if (!katze_xbel_folder_from_file (_session, config_file, &error))
|
|
{
|
|
if (error->code != G_FILE_ERROR_NOENT)
|
|
g_string_append_printf (error_messages,
|
|
_("The session couldn't be loaded. %s\n"), error->message);
|
|
g_error_free (error);
|
|
}
|
|
g_free (config_file);
|
|
}
|
|
config_file = g_build_filename (config_path, "tabtrash.xbel", NULL);
|
|
KatzeXbelItem* xbel_trash = katze_xbel_folder_new ();
|
|
error = NULL;
|
|
if (!katze_xbel_folder_from_file (xbel_trash, config_file, &error))
|
|
{
|
|
if (error->code != G_FILE_ERROR_NOENT)
|
|
g_string_append_printf(error_messages,
|
|
_("The trash couldn't be loaded. %s\n"), error->message);
|
|
g_error_free (error);
|
|
}
|
|
g_free (config_file);
|
|
|
|
// In case of errors
|
|
if (error_messages->len)
|
|
{
|
|
GtkWidget* dialog = gtk_message_dialog_new(NULL
|
|
, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_NONE
|
|
, _("The following errors occured:"));
|
|
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
|
|
gtk_window_set_title(GTK_WINDOW(dialog), g_get_application_name());
|
|
// FIXME: Use custom program icon
|
|
gtk_window_set_icon_name(GTK_WINDOW(dialog), "web-browser");
|
|
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog)
|
|
, "%s", error_messages->str);
|
|
gtk_dialog_add_buttons(GTK_DIALOG(dialog)
|
|
, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL
|
|
, "_Ignore", GTK_RESPONSE_ACCEPT
|
|
, NULL);
|
|
if(gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT)
|
|
{
|
|
config_free(config);
|
|
search_engines_free(searchEngines);
|
|
katze_xbel_item_unref(bookmarks);
|
|
katze_xbel_item_unref(_session);
|
|
katze_xbel_item_unref(xbel_trash);
|
|
g_string_free(error_messages, TRUE);
|
|
return 0;
|
|
}
|
|
gtk_widget_destroy(dialog);
|
|
/* FIXME: Since we will overwrite files that could not be loaded
|
|
, would we want to make backups? */
|
|
}
|
|
g_string_free (error_messages, TRUE);
|
|
|
|
// TODO: Handle any number of separate uris from argv
|
|
// Open as many tabs as we have uris, seperated by pipes
|
|
gchar* uri = argc > 1 ? strtok(g_strdup(argv[1]), "|") : NULL;
|
|
while(uri != NULL)
|
|
{
|
|
KatzeXbelItem* item = katze_xbel_bookmark_new();
|
|
gchar* uriReady = magic_uri(uri, FALSE);
|
|
katze_xbel_bookmark_set_href(item, uriReady);
|
|
g_free(uriReady);
|
|
katze_xbel_folder_append_item(_session, item);
|
|
uri = strtok(NULL, "|");
|
|
}
|
|
g_free(uri);
|
|
|
|
if(katze_xbel_folder_is_empty(_session))
|
|
{
|
|
KatzeXbelItem* item = katze_xbel_bookmark_new();
|
|
if(config->startup == CONFIG_STARTUP_BLANK)
|
|
katze_xbel_bookmark_set_href(item, "");
|
|
else
|
|
katze_xbel_bookmark_set_href(item, config->homepage);
|
|
katze_xbel_folder_prepend_item(_session, item);
|
|
}
|
|
g_free (config_path);
|
|
|
|
stock_items_init();
|
|
|
|
MidoriTrash* trash = g_object_new (MIDORI_TYPE_TRASH,
|
|
"limit", 10,
|
|
NULL);
|
|
guint n = katze_xbel_folder_get_n_items (xbel_trash);
|
|
guint i;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
KatzeXbelItem* item = katze_xbel_folder_get_nth_item (xbel_trash, i);
|
|
midori_trash_prepend_xbel_item (trash, item);
|
|
}
|
|
|
|
GtkAccelGroup* accel_group = gtk_accel_group_new();
|
|
GList* browsers = NULL;
|
|
|
|
MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER,
|
|
"settings", settings,
|
|
"trash", trash,
|
|
NULL);
|
|
gtk_window_add_accel_group (GTK_WINDOW (browser), accel_group);
|
|
g_object_connect (browser,
|
|
"signal::new-window", midori_browser_new_window_cb, browsers,
|
|
"signal::delete-event", midori_browser_delete_event_cb, browsers,
|
|
"signal::quit", midori_browser_quit_cb, browsers,
|
|
NULL);
|
|
browsers = g_list_prepend(browsers, browser);
|
|
gtk_widget_show (GTK_WIDGET (browser));
|
|
|
|
KatzeXbelItem* session = katze_xbel_folder_new ();
|
|
n = katze_xbel_folder_get_n_items (_session);
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
KatzeXbelItem* item = katze_xbel_folder_get_nth_item (_session, i);
|
|
midori_browser_append_xbel_item (browser, item);
|
|
}
|
|
katze_xbel_item_unref (_session);
|
|
|
|
gtk_main ();
|
|
|
|
g_object_unref (accel_group);
|
|
|
|
// Save configuration files
|
|
config_path = g_build_filename (g_get_user_config_dir(), PACKAGE_NAME,
|
|
NULL);
|
|
g_mkdir_with_parents (config_path, 0755);
|
|
config_file = g_build_filename (config_path, "search", NULL);
|
|
error = NULL;
|
|
if (!search_engines_to_file (searchEngines, config_file, &error))
|
|
{
|
|
g_warning("The search engines couldn't be saved. %s", error->message);
|
|
g_error_free(error);
|
|
}
|
|
search_engines_free(searchEngines);
|
|
g_free (config_file);
|
|
config_file = g_build_filename (config_path, "bookmarks.xbel", NULL);
|
|
error = NULL;
|
|
if (!katze_xbel_folder_to_file (bookmarks, config_file, &error))
|
|
{
|
|
g_warning("The bookmarks couldn't be saved. %s", error->message);
|
|
g_error_free(error);
|
|
}
|
|
katze_xbel_item_unref(bookmarks);
|
|
g_free (config_file);
|
|
config_file = g_build_filename (config_path, "tabtrash.xbel", NULL);
|
|
error = NULL;
|
|
if (!katze_xbel_folder_to_file (xbel_trash, config_file, &error))
|
|
{
|
|
g_warning ("The trash couldn't be saved. %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
katze_xbel_item_unref (xbel_trash);
|
|
if(config->startup == CONFIG_STARTUP_SESSION)
|
|
{
|
|
katze_assign (config_file, g_build_filename (config_path,
|
|
"session.xbel", NULL));
|
|
error = NULL;
|
|
if (!katze_xbel_folder_to_file (session, config_file, &error))
|
|
{
|
|
g_warning ("The session couldn't be saved. %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
katze_xbel_item_unref (session);
|
|
katze_assign (config_file, g_build_filename (config_path, "config", NULL));
|
|
error = NULL;
|
|
if (!settings_save_to_file (settings, config_file, &error))
|
|
{
|
|
g_warning ("The configuration couldn't be saved. %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
config_free (config);
|
|
katze_assign (config_file, g_build_filename (config_path, "accels", NULL));
|
|
gtk_accel_map_save (config_file);
|
|
g_free (config_file);
|
|
g_free (config_path);
|
|
return 0;
|
|
}
|