From: Christian Dywan Date: Sun, 1 Jun 2008 21:47:27 +0000 (+0200) Subject: Rename folder 'src' to 'midori' X-Git-Url: https://spindle.queued.net/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b511f12b9b4b063610161f2229b94a24a86be0fc;p=midori Rename folder 'src' to 'midori' --- diff --git a/Makefile.am b/Makefile.am index d8b5d3a9..5270e0d9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS = gnu -SUBDIRS = katze src po data +SUBDIRS = katze midori po data desktopdir = $(datadir)/applications desktop_in_files = midori.desktop diff --git a/configure.in b/configure.in index 784509be..72c121e5 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ # Register ourselves to autoconf AC_INIT([midori], [0.0.18], [christian@twotoasts.de]) -AC_CONFIG_SRCDIR([src/main.h]) +AC_CONFIG_SRCDIR([midori/main.h]) AC_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE([AC_PACKAGE_TARNAME()], [AC_PACKAGE_VERSION()]) @@ -101,19 +101,8 @@ fi AC_CONFIG_FILES([ Makefile \ katze/Makefile \ - src/Makefile \ + midori/Makefile \ po/Makefile.in \ data/Makefile ]) AC_OUTPUT - -# Show us what we have -echo -echo " GTK+2 $GTK_VER" -echo " WebKit $WEBKIT_VER" -echo " Libsexy $LIBSEXY_VER" -echo " libXML2 $LIBXML_VER" -echo -echo " Debugging $enable_debug" -echo -echo " Prefix $prefix" diff --git a/midori/Makefile.am b/midori/Makefile.am new file mode 100644 index 00000000..bda06d22 --- /dev/null +++ b/midori/Makefile.am @@ -0,0 +1,33 @@ +INCLUDES = \ + $(GTK_CFLAGS) \ + $(WEBKIT_CFLAGS) \ + $(LIBSEXY_CFLAGS) \ + -I../katze + +AM_CFLAGS = -DMIDORI_LOCALEDIR=\""$(localedir)"\" + +LDADD = \ + $(GTK_LIBS) \ + $(WEBKIT_LIBS) \ + $(LIBSEXY_LIBS) \ + $(INTLLIBS) \ + ../katze/libkatze.la + +bin_PROGRAMS = \ + midori + +midori_SOURCES = \ + main.c main.h \ + midori-app.c midori-app.h \ + midori-browser.c midori-browser.h \ + midori-panel.c midori-panel.h \ + midori-addons.c midori-addons.h \ + midori-console.c midori-console.h \ + midori-trash.c midori-trash.h \ + midori-webview.c midori-webview.h \ + midori-websettings.c midori-websettings.h \ + midori-preferences.c midori-preferences.h \ + webSearch.c webSearch.h \ + gjs.c gjs.h \ + sokoke.c sokoke.h \ + search.c search.h diff --git a/midori/gjs.c b/midori/gjs.c new file mode 100644 index 00000000..29148bbd --- /dev/null +++ b/midori/gjs.c @@ -0,0 +1,591 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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 "gjs.h" + +#include +#include + +#define G_OBJECT_NAME(object) G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object)) + +// FIXME: Return a GValue +JSValueRef +gjs_script_eval (JSContextRef js_context, + const gchar* script, + gchar** exception) +{ + g_return_val_if_fail (js_context, FALSE); + g_return_val_if_fail (script, FALSE); + + JSStringRef js_script = JSStringCreateWithUTF8CString (script); + JSValueRef js_exception = NULL; + JSValueRef js_value = JSEvaluateScript (js_context, js_script, + JSContextGetGlobalObject (js_context), NULL, 0, &js_exception); + if (!js_value && exception) + { + JSStringRef js_message = JSValueToStringCopy (js_context, + js_exception, NULL); + *exception = gjs_string_utf8 (js_message); + JSStringRelease (js_message); + js_value = JSValueMakeNull (js_context); + } + JSStringRelease (js_script); + return js_value; +} + +gboolean +gjs_script_check_syntax (JSContextRef js_context, + const gchar* script, + gchar** exception) +{ + g_return_val_if_fail (js_context, FALSE); + g_return_val_if_fail (script, FALSE); + + JSStringRef js_script = JSStringCreateWithUTF8CString (script); + JSValueRef js_exception = NULL; + bool result = JSCheckScriptSyntax (js_context, js_script, NULL, + 0, &js_exception); + if (!result && exception) + { + JSStringRef js_message = JSValueToStringCopy (js_context, + js_exception, NULL); + *exception = gjs_string_utf8 (js_message); + JSStringRelease (js_message); + } + JSStringRelease (js_script); + return result ? TRUE : FALSE; +} + +gboolean +gjs_script_from_file (JSContextRef js_context, + const gchar* filename, + gchar** exception) +{ + g_return_val_if_fail (js_context, FALSE); + g_return_val_if_fail (filename, FALSE); + + gboolean result = FALSE; + gchar* script; + GError* error = NULL; + if (g_file_get_contents (filename, &script, NULL, &error)) + { + if (gjs_script_eval (js_context, script, exception)) + result = TRUE; + g_free (script); + } + else if (error) + { + *exception = g_strdup (error->message); + g_error_free (error); + } + else + *exception = g_strdup (_("An unknown error occured.")); + return result; +} + +gchar* +gjs_string_utf8 (JSStringRef js_string) +{ + size_t size_utf8 = JSStringGetMaximumUTF8CStringSize (js_string); + gchar* string_utf8 = g_new (gchar, size_utf8); + JSStringGetUTF8CString (js_string, string_utf8, size_utf8); + return string_utf8; +} + +static void +_js_class_get_property_names_cb (JSContextRef js_context, + JSObjectRef js_object, + JSPropertyNameAccumulatorRef js_properties) +{ + GObject* object = JSObjectGetPrivate (js_object); + if (object) + { + guint n; + GParamSpec** pspecs = g_object_class_list_properties ( + G_OBJECT_GET_CLASS (object), &n); + gint i; + for (i = 0; i < n; i++) + { + const gchar* property = g_param_spec_get_name (pspecs[i]); + JSStringRef js_property = JSStringCreateWithUTF8CString (property); + JSPropertyNameAccumulatorAddName (js_properties, js_property); + JSStringRelease (js_property); + } + GType type = G_OBJECT_TYPE (object); + do + { + guint* signals = g_signal_list_ids (type, &n); + for (i = 0; i < n; i++) + { + const gchar* signal = g_signal_name (signals[i]); + JSStringRef js_signal = JSStringCreateWithUTF8CString (signal); + JSPropertyNameAccumulatorAddName (js_properties, js_signal); + JSStringRelease (js_signal); + } + type = g_type_parent (type); + } + while (type); + } +} + +static bool +_js_class_has_property_cb (JSContextRef js_context, + JSObjectRef js_object, + JSStringRef js_property) +{ + bool result = false; + gchar* property = gjs_string_utf8 (js_property); + GObject* object = JSObjectGetPrivate (js_object); + if (object) + { + if (g_signal_lookup (property, G_OBJECT_TYPE (object)) || + g_object_class_find_property (G_OBJECT_GET_CLASS (object), property)) + result = true; + } + else if (js_object == JSContextGetGlobalObject (js_context)) + { + GType type = g_type_from_name (property); + result = type ? type : false; + } + g_free (property); + return result; +} + +static void +_js_object_set_property (JSContextRef js_context, + JSObjectRef js_object, + const gchar* name, + JSValueRef js_value) +{ + JSStringRef js_name = JSStringCreateWithUTF8CString (name); + JSObjectSetProperty(js_context, js_object, js_name, js_value, + kJSPropertyAttributeNone, NULL); + JSStringRelease (js_name); +} + +static JSValueRef +_js_object_call_as_function_cb (JSContextRef js_context, + JSObjectRef js_function, + JSObjectRef js_this, + size_t n_arguments, + const JSValueRef js_arguments[], + JSValueRef* js_exception) +{ + GObject* object = JSObjectGetPrivate (js_this); + const gchar* function = JSObjectGetPrivate (js_function); + + g_return_val_if_fail (G_IS_OBJECT (object), JSValueMakeNull (js_context)); + g_return_val_if_fail (function, JSValueMakeNull (js_context)); + + guint signal_id = g_signal_lookup (function, G_OBJECT_TYPE (object)); + GSignalQuery query; + g_signal_query (signal_id, &query); + GValue* values = g_new0 (GValue, n_arguments + 1); + g_value_init (&values[0], G_OBJECT_TYPE (object)); + g_value_set_instance (&values[0], object); + gint i; + for (i = 0; i < n_arguments; i++) + { + GValue value = {0, }; + GType gtype; + switch (JSValueGetType (js_context, js_arguments[i])) + { + case kJSTypeBoolean: + gtype = G_TYPE_BOOLEAN; + g_value_init (&value, gtype); + g_value_set_boolean (&value, + JSValueToBoolean (js_context, js_arguments[i]) ? TRUE : FALSE); + break; + case kJSTypeNumber: + gtype = G_TYPE_DOUBLE; + g_value_init (&value, gtype); + g_value_set_double (&value, + JSValueToNumber (js_context, js_arguments[i], NULL)); + break; + case kJSTypeString: + gtype = G_TYPE_STRING; + g_value_init (&value, gtype); + JSStringRef js_string = JSValueToStringCopy (js_context, + js_arguments[i], NULL); + gchar* string = gjs_string_utf8 (js_string); + g_value_set_string (&value, string); + g_free (string); + JSStringRelease (js_string); + break; + case kJSTypeObject: + gtype = G_TYPE_OBJECT; + g_value_init (&value, gtype); + JSObjectRef js_object = JSValueToObject (js_context, + js_arguments[i], NULL); + GObject* object_value = JSObjectGetPrivate (js_object); + g_value_set_object (&value, object_value); + break; + case kJSTypeUndefined: + case kJSTypeNull: + default: + gtype = G_TYPE_NONE; + g_value_init (&value, gtype); + } + g_value_init (&values[i + 1], gtype); + if (query.n_params >= i + && g_value_type_compatible (gtype, query.param_types[i])) + // && g_value_type_transformable (gtype, query.param_types[i]) + g_value_copy (&value, &values[i + 1]); + // g_value_transform (&value, &values[i + 1]); + else + { + gchar* value_type = g_strdup_value_contents (&value); + // FIXME: exception + printf ("wrong value, expected %s\n", value_type); + g_free (value_type); + } + g_value_unset (&value); + } + GValue return_value = {0, }; + if (query.return_type != G_TYPE_NONE) + g_value_init (&return_value, query.return_type); + g_signal_emitv (values, signal_id, 0, &return_value); + + for (i = 0; i < n_arguments; i++) + g_value_unset (&values[i]); + // FIXME: return value + return JSValueMakeUndefined (js_context); +} + +static void +_js_object_add_function (JSContextRef js_context, + JSObjectRef js_object, + const gchar* func) +{ + JSStringRef js_func = JSStringCreateWithUTF8CString (func); + JSObjectRef js_function = JSObjectMakeFunctionWithCallback ( + js_context, js_func, _js_object_call_as_function_cb); + JSStringRelease (js_func); + _js_object_set_property (js_context, js_object, func, js_function); +} + +static JSValueRef +_js_class_get_property_cb (JSContextRef js_context, + JSObjectRef js_object, + JSStringRef js_property, + JSValueRef* js_exception) +{ + GObject* object = JSObjectGetPrivate (js_object); + + g_return_val_if_fail (G_IS_OBJECT (object), JSValueMakeNull (js_context)); + + JSValueRef js_result = NULL; + gchar* property = gjs_string_utf8 (js_property); + guint signal_id; + GParamSpec* pspec; + if ((signal_id = g_signal_lookup (property, G_OBJECT_TYPE (object)))) + { + GSignalQuery query; + g_signal_query (signal_id, &query); + if (query.signal_flags & G_SIGNAL_ACTION) + { + // We can't use JSObjectMakeFunctionWithCallback + // because it doesn't allocate private data + JSClassDefinition js_class_def = kJSClassDefinitionEmpty; + js_class_def.className = g_strdup (property); + js_class_def.callAsFunction = _js_object_call_as_function_cb; + JSClassRef js_class = JSClassCreate (&js_class_def); + JSObjectRef js_function = JSObjectMake (js_context, js_class, property); + return js_function; + } + g_free (property); + return JSValueMakeUndefined (js_context); + } + else if (!(pspec = g_object_class_find_property ( + G_OBJECT_GET_CLASS (object), property))) + { + gchar* message = g_strdup_printf (_("%s has no property '%s'"), + G_OBJECT_NAME (object), property); + JSStringRef js_message = JSStringCreateWithUTF8CString (message); + *js_exception = JSValueMakeString (js_context, js_message); + JSStringRelease (js_message); + g_free (message); + g_free (property); + return JSValueMakeNull (js_context); + } + if (!(pspec->flags & G_PARAM_READABLE)) + { + g_free (property); + return JSValueMakeUndefined (js_context); + } + GType type = G_PARAM_SPEC_TYPE (pspec); + if (type == G_TYPE_PARAM_STRING) + { + gchar* value; + g_object_get (object, property, &value, NULL); + if (value) + { + JSStringRef js_string = JSStringCreateWithUTF8CString (value); + js_result = JSValueMakeString (js_context, js_string); + } + } + else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT) + { + gint value; + g_object_get (object, property, &value, NULL); + js_result = JSValueMakeNumber (js_context, value); + } + else if (type == G_TYPE_PARAM_BOOLEAN) + { + gboolean value; + g_object_get (object, property, &value, NULL); + js_result = JSValueMakeBoolean (js_context, value ? true : false); + } + else if (type == G_TYPE_PARAM_OBJECT) + { + GObject* value; + g_object_get (object, property, &value, NULL); + if (value) + js_result = gjs_object_new (js_context, + G_OBJECT_NAME (value), value); + } + else if (type == G_TYPE_PARAM_ENUM) + { + gint value; + g_object_get (object, property, &value, NULL); + js_result = JSValueMakeNumber (js_context, value); + } + else + js_result = JSValueMakeUndefined (js_context); + g_free (property); + return js_result ? js_result : JSValueMakeNull (js_context); +} + +static bool +_js_class_set_property_cb (JSContextRef js_context, + JSObjectRef js_object, + JSStringRef js_property, + JSValueRef js_value, + JSValueRef* js_exception) +{ + GObject* object = JSObjectGetPrivate (js_object); + + g_return_val_if_fail (G_IS_OBJECT (object), false); + + bool result = false; + gchar* property = gjs_string_utf8 (js_property); + GParamSpec* pspec = g_object_class_find_property ( + G_OBJECT_GET_CLASS (object), property); + if (!pspec) + { + gchar* message = g_strdup_printf (_("%s has no property '%s'"), + G_OBJECT_NAME (object), property); + JSStringRef js_message = JSStringCreateWithUTF8CString (message); + *js_exception = JSValueMakeString (js_context, js_message); + JSStringRelease (js_message); + g_free (message); + g_free (property); + return false; + } + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_free (property); + return false; + } + GType type = G_PARAM_SPEC_TYPE (pspec); + if (type == G_TYPE_PARAM_STRING) + { + JSStringRef js_string_value = JSValueToStringCopy (js_context, + js_value, js_exception); + if (js_string_value) + { + gchar* string_value = gjs_string_utf8 (js_string_value); + g_object_set (object, property, string_value, NULL); + g_free (string_value); + } + } + else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT) + { + int value = JSValueToNumber (js_context, js_value, + js_exception); + g_object_set (object, property, value, NULL); + } + else if (type == G_TYPE_PARAM_BOOLEAN) + { + bool value = JSValueToBoolean (js_context, js_value); + g_object_set (object, property, value ? TRUE : FALSE, NULL); + } + else if (type == G_TYPE_PARAM_OBJECT) + { + JSObjectRef js_object_value = JSValueToObject ( + js_context, js_value, NULL); + GObject* object_value = JSObjectGetPrivate (js_object_value); + if (G_IS_OBJECT (object_value)) + g_object_set (object, property, object_value, NULL); + else + { + gchar* message = g_strdup_printf (_("%s cannot be assigned to %s.%s"), + "[object]", G_OBJECT_NAME (object), property); + JSStringRef js_message = JSStringCreateWithUTF8CString (message); + *js_exception = JSValueMakeString (js_context, js_message); + JSStringRelease (js_message); + g_free (message); + } + } + else + { + gchar* message = g_strdup_printf (_("%s.%s cannot be accessed"), + G_OBJECT_NAME (object), property); + JSStringRef js_message = JSStringCreateWithUTF8CString (message); + *js_exception = JSValueMakeString (js_context, js_message); + JSStringRelease (js_message); + g_free (message); + } + g_free (property); + return result; +} + +JSObjectRef +gjs_object_new (JSContextRef js_context, + const gchar* name, + gpointer instance) +{ + g_return_val_if_fail (js_context, NULL); + g_return_val_if_fail (name, NULL); + + JSClassDefinition js_class_def = kJSClassDefinitionEmpty; + js_class_def.className = g_strdup (name); + js_class_def.getPropertyNames = _js_class_get_property_names_cb; + js_class_def.hasProperty = _js_class_has_property_cb; + js_class_def.getProperty = _js_class_get_property_cb; + js_class_def.setProperty = _js_class_set_property_cb; + JSClassRef js_class = JSClassCreate (&js_class_def); + JSObjectRef js_object = JSObjectMake (js_context, js_class, instance); + return js_object; +} + +static JSObjectRef +_js_object_call_as_constructor_cb (JSContextRef js_context, + JSObjectRef js_object, + size_t n_arguments, + const JSValueRef js_arguments[], + JSValueRef* js_exception) +{ + const gchar* type_name = JSObjectGetPrivate (js_object); + + g_return_val_if_fail (type_name, NULL); + + GType type = g_type_from_name (type_name); + if (type) + return gjs_object_new (js_context, type_name, g_object_new (type, NULL)); + return NULL; +} + +static bool +_js_module_has_property_cb (JSContextRef js_context, + JSObjectRef js_object, + JSStringRef js_property) +{ + const gchar* namespace = JSObjectGetPrivate (js_object); + + g_return_val_if_fail (namespace, false); + + gchar* property = gjs_string_utf8 (js_property); + gchar* type_name = g_strdup_printf ("%s%s", namespace, property); + + GType type = g_type_from_name (type_name); + if (!type) + { + GModule* module = g_module_open (NULL, + G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + typedef GType (*gjs_get_type_func)(void); + // FIXME: Insert a space between each capital letter + gchar* type_func_name = g_strdup_printf ("%s_%s_get_type", + namespace, property); + gchar* type_func_name_small = g_utf8_strdown (type_func_name, -1); + gjs_get_type_func type_func; + if (g_module_symbol (module, + (const gchar*)type_func_name_small, &type_func)) + { + type = type_func (); + g_type_class_peek (type); + } + g_free (type_func_name_small); + g_free (type_func_name); + g_module_close (module); + } + bool result = type ? true : false; + g_free (type_name); + g_free (property); + return result; +} + +static JSValueRef +_js_module_get_property_cb (JSContextRef js_context, + JSObjectRef js_object, + JSStringRef js_property, + JSValueRef* js_exception) +{ + const gchar* namespace = JSObjectGetPrivate (js_object); + + g_return_val_if_fail (namespace, JSValueMakeNull (js_context)); + + gchar* property = gjs_string_utf8 (js_property); + gchar* type_name = g_strdup_printf ("%s%s", namespace, property); + GType type = g_type_from_name (type_name); + JSValueRef result; + if (type) + { + JSClassDefinition js_class_def = kJSClassDefinitionEmpty; + js_class_def.className = g_strdup (type_name); + js_class_def.callAsConstructor = _js_object_call_as_constructor_cb; + JSClassRef js_class = JSClassCreate (&js_class_def); + result = JSObjectMake (js_context, js_class, type_name); + } + else + { + result = JSValueMakeNull (js_context); + g_free (type_name); + } + g_free (property); + return result; +} + +JSObjectRef +gjs_module_new (JSContextRef js_context, + const gchar* namespace) +{ + g_return_val_if_fail (js_context, NULL); + g_return_val_if_fail (namespace, NULL); + + JSClassDefinition js_class_def = kJSClassDefinitionEmpty; + js_class_def.className = g_strdup (namespace); + js_class_def.hasProperty = _js_module_has_property_cb; + js_class_def.getProperty = _js_module_get_property_cb; + JSClassRef js_class = JSClassCreate (&js_class_def); + JSObjectRef js_module = JSObjectMake (js_context, js_class, (gpointer)namespace); + return js_module; +} + +JSGlobalContextRef +gjs_global_context_new (void) +{ + JSGlobalContextRef js_context = JSGlobalContextCreate (NULL); + JSObjectRef js_object = gjs_object_new (js_context, "GJS", NULL); + _js_object_set_property (js_context, JSContextGetGlobalObject (js_context), + "gjs", js_object); + + js_object = gjs_module_new (js_context, "Gtk"); + _js_object_set_property (js_context, JSContextGetGlobalObject (js_context), + "Gtk", js_object); + js_object = gjs_module_new (js_context, "WebKit"); + _js_object_set_property (js_context, JSContextGetGlobalObject (js_context), + "WebKit", js_object); + js_object = gjs_module_new (js_context, "Midori"); + _js_object_set_property (js_context, JSContextGetGlobalObject (js_context), + "Midori", js_object); + return js_context; +} diff --git a/midori/gjs.h b/midori/gjs.h new file mode 100644 index 00000000..47e9fced --- /dev/null +++ b/midori/gjs.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __GJS_H__ +#define __GJS_H__ + +#include +#include + +G_BEGIN_DECLS + +JSValueRef +gjs_script_eval (JSContextRef js_context, + const gchar* script, + gchar** exception); + +gboolean +gjs_script_check_syntax (JSContextRef js_context, + const gchar* script, + gchar** exception); + +gboolean +gjs_script_from_file (JSContextRef js_context, + const gchar* filename, + gchar** exception); + +gchar* +gjs_string_utf8 (JSStringRef js_string); + +JSObjectRef +gjs_object_new (JSContextRef context, + const gchar* name, + gpointer instance); + +JSGlobalContextRef +gjs_global_context_new (void); + +G_END_DECLS + +#endif /* __GJS_H__ */ diff --git a/midori/main.c b/midori/main.c new file mode 100644 index 00000000..6d4f03e8 --- /dev/null +++ b/midori/main.c @@ -0,0 +1,531 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + 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 "sokoke.h" +#include "search.h" + +#include "midori-app.h" +#include "midori-websettings.h" +#include "midori-trash.h" +#include "midori-browser.h" +#include "gjs.h" + +#include +#include +#include + +#include "config.h" + +#ifdef ENABLE_NLS + #include +#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_ADD, N_("_Add 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_LEAVE_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 void +locale_init (void) +{ +#ifdef ENABLE_NLS + 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) + { + gint 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_FLOAT) + { + gdouble number = sokoke_key_file_get_double_default (key_file, + "settings", property, + G_PARAM_SPEC_FLOAT (pspec)->default_value, NULL); + g_object_set (settings, property, number, 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); + if (enum_value) + g_object_set (settings, property, enum_value->value, NULL); + else + g_warning (_("Value '%s' is invalid for %s"), + string, property); + + g_free (string); + g_type_class_unref (enum_class); + } + else + g_warning (_("Unhandled settings value '%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_FLOAT) + { + gdouble number; + g_object_get (settings, property, &number, NULL); + g_key_file_set_double (key_file, "settings", property, number); + } + 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) +{ + MidoriStartup load_on_startup; + gchar* homepage; + + 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 }, + { 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; + } + + // Standalone gjs support + if (argc > 1 && argv[1] && g_str_has_suffix (argv[1], ".js")) + { + JSGlobalContextRef js_context = gjs_global_context_new (); + gchar* exception = NULL; + gjs_script_from_file (js_context, argv[1], &exception); + JSGlobalContextRelease (js_context); + if (!exception) + return 0; + printf ("%s - Exception: %s\n", argv[1], exception); + return 1; + } + + // 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); + 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 (); + g_object_get (settings, "load-on-startup", &load_on_startup, NULL); + if (load_on_startup == MIDORI_STARTUP_LAST_OPEN_PAGES) + { + 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) + { + 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* uri_ready = sokoke_magic_uri (uri, NULL); + katze_xbel_bookmark_set_href (item, uri_ready); + g_free (uri_ready); + 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 (load_on_startup == MIDORI_STARTUP_BLANK_PAGE) + katze_xbel_bookmark_set_href (item, ""); + else + { + g_object_get (settings, "homepage", &homepage, NULL); + katze_xbel_bookmark_set_href (item, homepage); + g_free (homepage); + } + katze_xbel_folder_prepend_item (_session, item); + } + g_free (config_path); + + stock_items_init (); + + MidoriApp* app = midori_app_new (); + g_object_set (app, "settings", settings, NULL); + + MidoriTrash* trash = midori_app_get_trash (app); + 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); + } + + MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER, + "settings", settings, + "trash", trash, + NULL); + g_signal_emit_by_name (app, "add-browser", 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_add_xbel_item (browser, item); + } + // FIXME: Switch to the last active page + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (_session, 0); + if (!strcmp (katze_xbel_bookmark_get_href (item), "")) + midori_browser_activate_action (browser, "Location"); + katze_xbel_item_unref (_session); + + // Load extensions + JSGlobalContextRef js_context = gjs_global_context_new (); + // FIXME: We want to honor system installed addons as well + gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, + "extensions", NULL); + GDir* addon_dir = g_dir_open (addon_path, 0, NULL); + if (addon_dir) + { + const gchar* filename; + while ((filename = g_dir_read_name (addon_dir))) + { + gchar* fullname = g_build_filename (addon_path, filename, NULL); + gchar* exception = NULL; + gjs_script_from_file (js_context, fullname, &exception); + if (exception) + // FIXME: Do we want to print this somewhere else? + // FIXME Convert the filename to UTF8 + printf ("%s - Exception: %s\n", filename, exception); + g_free (fullname); + } + g_dir_close (addon_dir); + } + + gtk_main (); + + JSGlobalContextRelease (js_context); + + // 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); + g_object_get (settings, "load-on-startup", &load_on_startup, NULL); + if(load_on_startup == MIDORI_STARTUP_LAST_OPEN_PAGES) + { + 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); + } + 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; +} diff --git a/midori/main.h b/midori/main.h new file mode 100644 index 00000000..3eab9b70 --- /dev/null +++ b/midori/main.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + 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. +*/ + +#ifndef __MAIN_H__ +#define __MAIN_H__ 1 + +#include + +#include +#include + +#include + +// FIXME: Remove these globals + +GList* searchEngines; // Items of type 'SearchEngine' +KatzeXbelItem* bookmarks; + +// Custom stock items + +// We should distribute these +// Names should match with epiphany and/ or xdg spec +/* NOTE: Those uncommented were replaced with remotely related icons + in order to reduce the amount of warnings :D */ + +#define STOCK_BOOKMARK GTK_STOCK_FILE // "stock_bookmark" "bookmark-web" +#define STOCK_FORM_FILL GTK_STOCK_JUSTIFY_FILL // "insert-text" "form-fill" +#define STOCK_NEWSFEED GTK_STOCK_INDEX + +// We assume that these legacy icon names are usually present + +#define STOCK_BOOKMARK_ADD "stock_add-bookmark" +#define STOCK_HOMEPAGE GTK_STOCK_HOME +#define STOCK_IMAGE "gnome-mime-image" +#define STOCK_LOCK_OPEN "stock_lock-open" +#define STOCK_LOCK_SECURE "stock_lock" +#define STOCK_LOCK_BROKEN "stock_lock-broken" +#define STOCK_NETWORK_OFFLINE "network-offline" +#define STOCK_SCRIPT "stock_script" +#define STOCK_SEND "stock_mail-send" +#define STOCK_TAB_NEW "stock_new-tab" +#define STOCK_THEME "gnome-settings-theme" +#define STOCK_USER_TRASH "gnome-stock-trash" +#define STOCK_WINDOW_NEW "stock_new-window" + +// For backwards compatibility + +#if !GTK_CHECK_VERSION(2, 10, 0) +#define GTK_STOCK_SELECT_ALL "gtk-select-all" +#endif +#if !GTK_CHECK_VERSION(2, 8, 0) +#define GTK_STOCK_FULLSCREEN "gtk-fullscreen" +#define GTK_STOCK_LEAVE_FULLSCREEN "gtk-leave-fullscreen" +#endif + +#endif /* !__MAIN_H__ */ diff --git a/midori/midori-addons.c b/midori/midori-addons.c new file mode 100644 index 00000000..a5a2985b --- /dev/null +++ b/midori/midori-addons.c @@ -0,0 +1,329 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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 "config.h" + +#include "midori-addons.h" + +#include "sokoke.h" +#include "gjs.h" +#include +#include +#include + +G_DEFINE_TYPE (MidoriAddons, midori_addons, GTK_TYPE_VBOX) + +struct _MidoriAddonsPrivate +{ + MidoriAddonKind kind; + GtkWidget* toolbar; + GtkWidget* treeview; +}; + +#define MIDORI_ADDONS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_ADDONS, MidoriAddonsPrivate)) + +GType +midori_addon_kind_get_type (void) +{ + static GType type = 0; + if (!type) + { + static const GEnumValue values[] = { + { MIDORI_ADDON_EXTENSIONS, "MIDORI_ADDON_EXTENSIONS", N_("Extensions") }, + { MIDORI_ADDON_USER_SCRIPTS, "MIDORI_USER_SCRIPTS", N_("Userscripts") }, + { MIDORI_ADDON_USER_STYLES, "MIDORI_USER_STYLES", N_("Userstyles") }, + { 0, NULL, NULL } + }; + type = g_enum_register_static ("MidoriAddonKind", values); + } + return type; +} + +static void +midori_addons_class_init (MidoriAddonsClass* class) +{ + g_type_class_add_private (class, sizeof (MidoriAddonsPrivate)); +} + +static const +gchar* _folder_for_kind (MidoriAddonKind kind) +{ + switch (kind) + { + case MIDORI_ADDON_EXTENSIONS: + return "extensions"; + case MIDORI_ADDON_USER_SCRIPTS: + return "scripts"; + case MIDORI_ADDON_USER_STYLES: + return "styles"; + default: + return NULL; + } +} + +static void +midori_addons_button_add_clicked_cb (GtkToolItem* toolitem, + MidoriAddons* addons) +{ + MidoriAddonsPrivate* priv = addons->priv; + + GtkWidget* dialog = gtk_message_dialog_new ( + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (addons))), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, + "Put scripts in the folder ~/.local/share/midori/%s", + _folder_for_kind (priv->kind)); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); +} + +static void +midori_addons_treeview_render_icon_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + // gchar* source_id; + // gtk_tree_model_get (model, iter, 2, &source_id, -1); + + g_object_set (renderer, "stock-id", GTK_STOCK_FILE, NULL); + + // g_free (source_id); +} + +static void +midori_addons_treeview_render_text_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + gchar* filename; + gint a; + gchar* b; + gtk_tree_model_get (model, iter, 0, &filename, 1, &a, 2, &b, -1); + + // FIXME: Convert filename to UTF8 + gchar* text = g_strdup_printf ("%s", filename); + g_object_set (renderer, "text", text, NULL); + g_free (text); + + g_free (filename); + g_free (b); +} + +static void +midori_addons_treeview_row_activated_cb (GtkTreeView* treeview, + GtkTreePath* path, + GtkTreeViewColumn* column, + MidoriAddons* addons) +{ + /*GtkTreeModel* model = gtk_tree_view_get_model (treeview); + GtkTreeIter iter; + if (gtk_tree_model_get_iter (model, &iter, path)) + { + gchar* b; + gtk_tree_model_get (model, &iter, 2, &b, -1); + g_free (b); + }*/ +} + +static void +midori_addons_init (MidoriAddons* addons) +{ + addons->priv = MIDORI_ADDONS_GET_PRIVATE (addons); + + MidoriAddonsPrivate* priv = addons->priv; + + GtkTreeViewColumn* column; + GtkCellRenderer* renderer_text; + GtkCellRenderer* renderer_pixbuf; + priv->treeview = gtk_tree_view_new (); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE); + column = gtk_tree_view_column_new (); + renderer_pixbuf = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf, + (GtkTreeCellDataFunc)midori_addons_treeview_render_icon_cb, + priv->treeview, NULL); + renderer_text = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer_text, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer_text, + (GtkTreeCellDataFunc)midori_addons_treeview_render_text_cb, + priv->treeview, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column); + g_signal_connect (priv->treeview, "row-activated", + G_CALLBACK (midori_addons_treeview_row_activated_cb), + addons); + gtk_widget_show (priv->treeview); + gtk_box_pack_start (GTK_BOX (addons), priv->treeview, TRUE, TRUE, 0); +} + +static gboolean +_js_script_from_file (JSContextRef js_context, + const gchar* filename, + gchar** exception) +{ + gboolean result = FALSE; + gchar* script; + GError* error = NULL; + if (g_file_get_contents (filename, &script, NULL, &error)) + { + // Wrap the script to prevent global variables + gchar* wrapped_script = g_strdup_printf ( + "var wrapped = function () { %s }; wrapped ();", script); + if (gjs_script_eval (js_context, wrapped_script, exception)) + result = TRUE; + g_free (wrapped_script); + g_free (script); + } + else + { + *exception = g_strdup (error->message); + g_error_free (error); + } + return result; +} + +static void +midori_web_widget_window_object_cleared_cb (GtkWidget* web_widget, + WebKitWebFrame* web_frame, + JSGlobalContextRef js_context, + JSObjectRef js_window, + MidoriAddons* addons) +{ + MidoriAddonsPrivate* priv = addons->priv; + + // FIXME: We want to honor system installed addons as well + gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, + _folder_for_kind (priv->kind), NULL); + GDir* addon_dir = g_dir_open (addon_path, 0, NULL); + if (addon_dir) + { + const gchar* filename; + while ((filename = g_dir_read_name (addon_dir))) + { + gchar* fullname = g_build_filename (addon_path, filename, NULL); + gchar* exception; + if (!_js_script_from_file (js_context, fullname, &exception)) + { + gchar* message = g_strdup_printf ("console.error ('%s');", + exception); + gjs_script_eval (js_context, message, NULL); + g_free (message); + g_free (exception); + } + g_free (fullname); + } + g_dir_close (addon_dir); + } +} + +/** + * midori_addons_new: + * @web_widget: a web widget + * @kind: the kind of addon + * @extension: a file extension mask + * + * Creates a new addons widget. + * + * @web_widget can be one of the following: + * %MidoriBrowser, %MidoriWebView, %WebKitWebView + * + * Note: Currently @extension has no effect. + * + * Return value: a new #MidoriAddons + **/ +GtkWidget* +midori_addons_new (GtkWidget* web_widget, + MidoriAddonKind kind) +{ + g_return_val_if_fail (GTK_IS_WIDGET (web_widget), NULL); + + MidoriAddons* addons = g_object_new (MIDORI_TYPE_ADDONS, + // "kind", kind, + NULL); + + MidoriAddonsPrivate* priv = addons->priv; + priv->kind = kind; + + if (kind == MIDORI_ADDON_USER_SCRIPTS) + g_signal_connect (web_widget, "window-object-cleared", + G_CALLBACK (midori_web_widget_window_object_cleared_cb), addons); + + GtkListStore* liststore = gtk_list_store_new (3, G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_STRING); + // FIXME: We want to honor system installed addons as well + gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, + _folder_for_kind (priv->kind), NULL); + GDir* addon_dir = g_dir_open (addon_path, 0, NULL); + if (addon_dir) + { + const gchar* filename; + while ((filename = g_dir_read_name (addon_dir))) + { + GtkTreeIter iter; + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, + 0, filename, 1, 0, 2, "", -1); + } + g_dir_close (addon_dir); + } + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), + GTK_TREE_MODEL (liststore)); + + return GTK_WIDGET (addons); +} + +/** + * midori_addons_get_toolbar: + * + * Retrieves the toolbar of the addons. A new widget is created on + * the first call of this function. + * + * Return value: a new #MidoriAddons + **/ +GtkWidget* +midori_addons_get_toolbar (MidoriAddons* addons) +{ + MidoriAddonsPrivate* priv = addons->priv; + + g_return_val_if_fail (MIDORI_IS_ADDONS (addons), NULL); + + if (!priv->toolbar) + { + GtkWidget* toolbar = gtk_toolbar_new (); + gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); + GtkToolItem* toolitem = gtk_tool_item_new (); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); + gtk_widget_show (GTK_WIDGET (toolitem)); + toolitem = gtk_separator_tool_item_new (); + gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), + FALSE); + gtk_tool_item_set_expand (toolitem, TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); + gtk_widget_show (GTK_WIDGET (toolitem)); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ADD); + gtk_tool_item_set_is_important (toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_addons_button_add_clicked_cb), addons); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); + gtk_widget_show (GTK_WIDGET (toolitem)); + priv->toolbar = toolbar; + } + + return priv->toolbar; +} diff --git a/midori/midori-addons.h b/midori/midori-addons.h new file mode 100644 index 00000000..940ff73c --- /dev/null +++ b/midori/midori-addons.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_ADDONS_H__ +#define __MIDORI_ADDONS_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_ADDONS \ + (midori_addons_get_type ()) +#define MIDORI_ADDONS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_ADDONS, MidoriAddons)) +#define MIDORI_ADDONS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_ADDONS, MidoriAddonsClass)) +#define MIDORI_IS_ADDONS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_ADDONS)) +#define MIDORI_IS_ADDONS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_ADDONS)) +#define MIDORI_ADDONS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_ADDONS, MidoriAddonsClass)) + +typedef struct _MidoriAddons MidoriAddons; +typedef struct _MidoriAddonsPrivate MidoriAddonsPrivate; +typedef struct _MidoriAddonsClass MidoriAddonsClass; + +struct _MidoriAddons +{ + GtkVBox parent_instance; + + MidoriAddonsPrivate* priv; +}; + +struct _MidoriAddonsClass +{ + GtkVBoxClass parent_class; +}; + +typedef enum +{ + MIDORI_ADDON_EXTENSIONS, + MIDORI_ADDON_USER_SCRIPTS, + MIDORI_ADDON_USER_STYLES +} MidoriAddonKind; + +GType +midori_addon_kind_get_type (void) G_GNUC_CONST; + +#define MIDORI_TYPE_ADDON_KIND \ + (midori_addon_kind_get_type ()) + +GType +midori_addons_get_type (void); + +GtkWidget* +midori_addons_new (GtkWidget* web_widget, + MidoriAddonKind kind); + +GtkWidget* +midori_addons_get_toolbar (MidoriAddons* console); + +G_END_DECLS + +#endif /* __MIDORI_ADDONS_H__ */ diff --git a/midori/midori-app.c b/midori/midori-app.c new file mode 100644 index 00000000..5d41e255 --- /dev/null +++ b/midori/midori-app.c @@ -0,0 +1,385 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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 "midori-app.h" + +#include +#include + +G_DEFINE_TYPE (MidoriApp, midori_app, G_TYPE_OBJECT) + +static MidoriApp* _midori_app_singleton = NULL; + +struct _MidoriAppPrivate +{ + GList* browsers; + MidoriBrowser* browser; + GtkAccelGroup* accel_group; + + MidoriWebSettings* settings; + MidoriTrash* trash; +}; + +#define MIDORI_APP_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_APP, MidoriAppPrivate)) + +enum +{ + PROP_0, + + PROP_SETTINGS, + PROP_TRASH, + PROP_BROWSER, + PROP_BROWSER_COUNT +}; + +enum { + ADD_BROWSER, + QUIT, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static GObject* +midori_app_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam* construct_properties); + +static void +midori_app_finalize (GObject* object); + +static void +midori_app_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_app_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static void +midori_app_add_browser (MidoriApp* app, + MidoriBrowser* browser); + +static void +midori_app_quit (MidoriApp* app); + +static void +midori_app_class_init (MidoriAppClass* class) +{ + signals[ADD_BROWSER] = g_signal_new ( + "add-browser", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriAppClass, add_browser), + 0, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + MIDORI_TYPE_BROWSER); + + signals[QUIT] = g_signal_new ( + "quit", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriAppClass, quit), + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->constructor = midori_app_constructor; + gobject_class->finalize = midori_app_finalize; + gobject_class->set_property = midori_app_set_property; + gobject_class->get_property = midori_app_get_property; + + MidoriAppClass* midoriapp_class = MIDORI_APP_CLASS (class); + midoriapp_class->add_browser = midori_app_add_browser; + midoriapp_class->quit = midori_app_quit; + + g_object_class_install_property (gobject_class, + PROP_SETTINGS, + g_param_spec_object ( + "settings", + _("Settings"), + _("The associated settings"), + MIDORI_TYPE_WEB_SETTINGS, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_TRASH, + g_param_spec_object ( + "trash", + _("Trash"), + _("The trash, collecting recently closed tabs and windows"), + MIDORI_TYPE_TRASH, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_BROWSER, + g_param_spec_object ( + "browser", + _("Browser"), + _("The current browser"), + MIDORI_TYPE_BROWSER, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_BROWSER_COUNT, + g_param_spec_uint ( + "browser-count", + _("Browser Count"), + _("The current number of browsers"), + 0, G_MAXUINT, 0, + G_PARAM_READABLE)); + + g_type_class_add_private (class, sizeof (MidoriAppPrivate)); +} + +static GObject* +midori_app_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam* construct_properties) +{ + if (_midori_app_singleton) + return g_object_ref (_midori_app_singleton); + else + return G_OBJECT_CLASS (midori_app_parent_class)->constructor ( + type, n_construct_properties, construct_properties); +} + +static void +midori_app_init (MidoriApp* app) +{ + g_assert (!_midori_app_singleton); + + _midori_app_singleton = app; + + app->priv = MIDORI_APP_GET_PRIVATE (app); + + MidoriAppPrivate* priv = app->priv; + + priv->accel_group = gtk_accel_group_new (); + + priv->settings = midori_web_settings_new (); + priv->trash = midori_trash_new (10); +} + +static void +midori_app_finalize (GObject* object) +{ + MidoriApp* app = MIDORI_APP (object); + MidoriAppPrivate* priv = app->priv; + + g_list_free (priv->browsers); + g_object_unref (priv->accel_group); + + g_object_unref (priv->settings); + g_object_unref (priv->trash); + + G_OBJECT_CLASS (midori_app_parent_class)->finalize (object); +} + +static void +midori_app_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriApp* app = MIDORI_APP (object); + MidoriAppPrivate* priv = app->priv; + + switch (prop_id) + { + case PROP_SETTINGS: + katze_object_assign (priv->settings, g_value_get_object (value)); + g_object_ref (priv->settings); + // FIXME: Propagate settings to all browsers + break; + case PROP_TRASH: + katze_object_assign (priv->trash, g_value_get_object (value)); + g_object_ref (priv->trash); + // FIXME: Propagate trash to all browsers + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_app_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriApp* app = MIDORI_APP (object); + MidoriAppPrivate* priv = app->priv; + + switch (prop_id) + { + case PROP_SETTINGS: + g_value_set_object (value, priv->settings); + break; + case PROP_TRASH: + g_value_set_object (value, priv->trash); + break; + case PROP_BROWSER: + g_value_set_object (value, priv->browser); + break; + case PROP_BROWSER_COUNT: + g_value_set_uint (value, g_list_length (priv->browsers)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_browser_focus_in_event_cb (MidoriBrowser* browser, + GdkEventFocus* event, + MidoriApp* app) +{ + MidoriAppPrivate* priv = app->priv; + + priv->browser = browser; +} + +static void +midori_browser_new_window_cb (MidoriBrowser* browser, + const gchar* uri, + MidoriApp* app) +{ + MidoriAppPrivate* priv = app->priv; + + MidoriBrowser* new_browser = g_object_new (MIDORI_TYPE_BROWSER, + "settings", priv->settings, + "trash", priv->trash, + NULL); + midori_browser_add_uri (new_browser, uri); + gtk_widget_show (GTK_WIDGET (new_browser)); + + g_signal_emit (app, signals[ADD_BROWSER], 0, new_browser); +} + +static gboolean +midori_browser_delete_event_cb (MidoriBrowser* browser, + GdkEvent* event, + MidoriApp* app) +{ + return FALSE; +} + +static gboolean +midori_browser_destroy_cb (MidoriBrowser* browser, + MidoriApp* app) +{ + MidoriAppPrivate* priv = app->priv; + + priv->browsers = g_list_remove (priv->browsers, browser); + if (g_list_nth (priv->browsers, 0)) + return FALSE; + g_signal_emit (app, signals[QUIT], 0); + return TRUE; +} + +static void +midori_browser_quit_cb (MidoriBrowser* browser, + MidoriApp* app) +{ + g_signal_emit (app, signals[QUIT], 0); +} + +static void +midori_app_add_browser (MidoriApp* app, + MidoriBrowser* browser) +{ + MidoriAppPrivate* priv = app->priv; + + gtk_window_add_accel_group (GTK_WINDOW (browser), priv->accel_group); + g_object_connect (browser, + "signal::focus-in-event", midori_browser_focus_in_event_cb, app, + "signal::new-window", midori_browser_new_window_cb, app, + "signal::delete-event", midori_browser_delete_event_cb, app, + "signal::destroy", midori_browser_destroy_cb, app, + "signal::quit", midori_browser_quit_cb, app, + NULL); + + priv->browsers = g_list_prepend (priv->browsers, browser); +} + +static void +midori_app_quit (MidoriApp* app) +{ + gtk_main_quit (); +} + +/** + * midori_app_new: + * + * Instantiates a new #MidoriApp singleton. + * + * Subsequent calls will ref the initial instance. + * + * Return value: a new #MidoriApp + **/ +MidoriApp* +midori_app_new (void) +{ + MidoriApp* app = g_object_new (MIDORI_TYPE_APP, + NULL); + + return app; +} + +/** + * midori_app_get_settings: + * @app: a #MidoriApp + * + * Retrieves the #MidoriWebSettings of the app. + * + * Return value: the assigned #MidoriWebSettings + **/ +MidoriWebSettings* +midori_app_get_settings (MidoriApp* app) +{ + g_return_val_if_fail (MIDORI_IS_APP (app), NULL); + + MidoriAppPrivate* priv = app->priv; + + return priv->settings; +} + +/** + * midori_app_get_trash: + * @app: a #MidoriApp + * + * Retrieves the #MidoriTrash of the app. + * + * Return value: the assigned #MidoriTrash + **/ +MidoriTrash* +midori_app_get_trash (MidoriApp* app) +{ + g_return_val_if_fail (MIDORI_IS_APP (app), NULL); + + MidoriAppPrivate* priv = app->priv; + + return priv->trash; +} diff --git a/midori/midori-app.h b/midori/midori-app.h new file mode 100644 index 00000000..b5aaa45c --- /dev/null +++ b/midori/midori-app.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_APP_H__ +#define __MIDORI_APP_H__ + +#include + +#include "midori-browser.h" +#include "midori-websettings.h" +#include "midori-trash.h" + +G_BEGIN_DECLS + +#define MIDORI_TYPE_APP \ + (midori_app_get_type ()) +#define MIDORI_APP(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_APP, MidoriApp)) +#define MIDORI_APP_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_APP, MidoriAppClass)) +#define MIDORI_IS_APP(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_APP)) +#define MIDORI_IS_APP_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_APP)) +#define MIDORI_APP_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_APP, MidoriAppClass)) + +typedef struct _MidoriApp MidoriApp; +typedef struct _MidoriAppPrivate MidoriAppPrivate; +typedef struct _MidoriAppClass MidoriAppClass; + +struct _MidoriApp +{ + GObject parent_instance; + + MidoriAppPrivate* priv; +}; + +struct _MidoriAppClass +{ + GObjectClass parent_class; + + /* Signals */ + void + (*add_browser) (MidoriApp* app, + MidoriBrowser* browser); + void + (*quit) (MidoriApp* app); +}; + +GType +midori_app_get_type (void); + +MidoriApp* +midori_app_new (void); + +MidoriWebSettings* +midori_app_get_web_settings (MidoriApp* app); + +MidoriTrash* +midori_app_get_trash (MidoriApp* app); + +G_END_DECLS + +#endif /* __MIDORI_APP_H__ */ diff --git a/midori/midori-browser.c b/midori/midori-browser.c new file mode 100644 index 00000000..459818f5 --- /dev/null +++ b/midori/midori-browser.c @@ -0,0 +1,3639 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + 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 "config.h" + +#include "midori-browser.h" + +#include "webSearch.h" + +#include "main.h" +#include "sokoke.h" +#include "midori-webview.h" +#include "midori-preferences.h" +#include "midori-panel.h" +#include "midori-addons.h" +#include "midori-console.h" +#include "midori-trash.h" + +#include +#include +#include +#include +#include + +G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW) + +struct _MidoriBrowserPrivate +{ + GtkActionGroup* action_group; + GtkWidget* menubar; + GtkWidget* menu_bookmarks; + GtkWidget* menu_tools; + GtkWidget* menu_window; + GtkWidget* popup_bookmark; + GtkWidget* throbber; + GtkWidget* navigationbar; + GtkWidget* button_tab_new; + GtkWidget* button_homepage; + GtkWidget* location_icon; + GtkWidget* location; + GtkWidget* search; + GtkWidget* button_trash; + GtkWidget* button_fullscreen; + GtkWidget* bookmarkbar; + + GtkWidget* panel; + GtkWidget* panel_bookmarks; + GtkWidget* panel_console; + GtkWidget* panel_pageholder; + GtkWidget* notebook; + + GtkWidget* find; + GtkWidget* find_text; + GtkToolItem* find_case; + GtkToolItem* find_highlight; + + GtkWidget* statusbar; + GtkWidget* progressbar; + + gchar* uri; + gchar* title; + gchar* statusbar_text; + MidoriWebSettings* settings; + + KatzeXbelItem* proxy_xbel_folder; + MidoriTrash* trash; +}; + +#define MIDORI_BROWSER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_BROWSER, MidoriBrowserPrivate)) + +enum +{ + PROP_0, + + PROP_MENUBAR, + PROP_NAVIGATIONBAR, + PROP_TAB, + PROP_STATUSBAR, + PROP_SETTINGS, + PROP_STATUSBAR_TEXT, + PROP_TRASH +}; + +enum +{ + WINDOW_OBJECT_CLEARED, + STATUSBAR_TEXT_CHANGED, + ELEMENT_MOTION, + NEW_WINDOW, + + ADD_TAB, + ADD_URI, + ACTIVATE_ACTION, + QUIT, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_browser_finalize (GObject* object); + +static void +midori_browser_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_browser_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static GtkAction* +_action_by_name (MidoriBrowser* browser, + const gchar* name) +{ + MidoriBrowserPrivate* priv = browser->priv; + + return gtk_action_group_get_action (priv->action_group, name); +} + +static void +_action_set_sensitive (MidoriBrowser* browser, + const gchar* name, + gboolean sensitive) +{ + gtk_action_set_sensitive (_action_by_name (browser, name), sensitive); +} + +static void +_action_set_active (MidoriBrowser* browser, + const gchar* name, + gboolean active) +{ + GtkAction* action = _action_by_name (browser, name); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active); +} + +static void +_midori_browser_update_actions (MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + guint n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), n > 1); + _action_set_sensitive (browser, "TabClose", n > 1); + _action_set_sensitive (browser, "TabPrevious", n > 1); + _action_set_sensitive (browser, "TabNext", n > 1); + + if (priv->trash) + { + gboolean trash_empty = midori_trash_is_empty (priv->trash); + _action_set_sensitive (browser, "UndoTabClose", !trash_empty); + _action_set_sensitive (browser, "Trash", !trash_empty); + } +} + +static void +_midori_browser_update_interface (MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean loading = FALSE; + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + if (web_view) + { + loading = midori_web_view_is_loading (MIDORI_WEB_VIEW (web_view)); + _action_set_sensitive (browser, "ZoomNormal", + midori_web_view_get_zoom_level (MIDORI_WEB_VIEW (web_view)) != 1.0); + if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_view), + "zoom-level")) + { + _action_set_sensitive (browser, "ZoomIn", FALSE); + _action_set_sensitive (browser, "ZoomOut", FALSE); + } + _action_set_sensitive (browser, "Back", + webkit_web_view_can_go_back (WEBKIT_WEB_VIEW (web_view))); + _action_set_sensitive (browser, "Forward", + webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW (web_view))); + _action_set_sensitive (browser, "Reload", !loading); + _action_set_sensitive (browser, "Stop", loading); + _action_set_sensitive (browser, "Print", TRUE); + } + else + _action_set_sensitive (browser, "Print", FALSE); + + GtkAction* action = gtk_action_group_get_action (priv->action_group, + "ReloadStop"); + if (!loading) + { + gtk_widget_set_sensitive (priv->throbber, FALSE); + g_object_set (action, + "stock-id", GTK_STOCK_REFRESH, + "tooltip", _("Reload the current page"), NULL); + gtk_widget_hide (priv->progressbar); + } + else + { + gtk_widget_set_sensitive (priv->throbber, TRUE); + g_object_set (action, + "stock-id", GTK_STOCK_STOP, + "tooltip", _("Stop loading the current page"), NULL); + gtk_widget_show (priv->progressbar); + } + katze_throbber_set_animated (KATZE_THROBBER (priv->throbber), loading); + gtk_image_set_from_stock (GTK_IMAGE (priv->location_icon), + GTK_STOCK_FILE, GTK_ICON_SIZE_MENU); +} + +static GtkWidget* +_midori_browser_scrolled_for_child (MidoriBrowser* browser, + GtkWidget* child) +{ + GtkWidget* scrolled = gtk_widget_get_parent (child); + if (GTK_IS_VIEWPORT (scrolled)) + scrolled = gtk_widget_get_parent (scrolled); + return scrolled; +} + +static GtkWidget* +_midori_browser_child_for_scrolled (MidoriBrowser* browser, + GtkWidget* scrolled) +{ + GtkWidget* child = gtk_bin_get_child (GTK_BIN (scrolled)); + if (GTK_IS_VIEWPORT (child)) + child = gtk_bin_get_child (GTK_BIN (child)); + return child; +} + +static void +_midori_browser_set_statusbar_text (MidoriBrowser* browser, + const gchar* text) +{ + MidoriBrowserPrivate* priv = browser->priv; + + katze_assign (priv->statusbar_text, g_strdup (text)); + gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar), 1); + gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar), 1, + priv->statusbar_text ? priv->statusbar_text : ""); +} + +static void +_midori_browser_set_current_page_smartly (MidoriBrowser* browser, + gint n) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean open_tabs_in_the_background; + g_object_get (priv->settings, "open-tabs-in-the-background", + &open_tabs_in_the_background, NULL); + if (!open_tabs_in_the_background) + midori_browser_set_current_page (browser, n); +} + +static void +_midori_browser_update_progress (MidoriBrowser* browser, + gint progress) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (progress > -1) + { + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progressbar), + progress ? progress / 100.0 : 0); + gchar* message = g_strdup_printf (_("%d%% loaded"), progress); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progressbar), + message); + g_free (message); + } + else + { + gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->progressbar)); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progressbar), + NULL); + } +} + +static void +midori_web_view_window_object_cleared_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + JSGlobalContextRef js_context, + JSObjectRef js_window, + MidoriBrowser* browser) +{ + g_signal_emit (browser, signals[WINDOW_OBJECT_CLEARED], 0, + web_frame, js_context, js_window); +} + +static void +midori_web_view_load_started_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + { + _midori_browser_update_interface (browser); + _midori_browser_set_statusbar_text (browser, NULL); + } +} + +static void +midori_web_view_progress_started_cb (GtkWidget* web_view, + guint progress, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + _midori_browser_update_progress (browser, progress); +} + +static void +midori_web_view_progress_changed_cb (GtkWidget* web_view, + guint progress, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + _midori_browser_update_progress (browser, progress); +} + +static void +midori_web_view_progress_done_cb (GtkWidget* web_view, + guint progress, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + _midori_browser_update_progress (browser, progress); +} + +static void +midori_web_view_load_done_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + { + _midori_browser_update_interface (browser); + _midori_browser_set_statusbar_text (browser, NULL); + } +} + +static void +midori_web_view_title_changed_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + const gchar* title, + MidoriBrowser* browser) +{ + if (web_view == midori_browser_get_current_web_view (browser)) + { + const gchar* title = midori_web_view_get_display_title ( + MIDORI_WEB_VIEW (web_view)); + gchar* window_title = g_strconcat (title, " - ", + g_get_application_name (), NULL); + gtk_window_set_title (GTK_WINDOW (browser), window_title); + g_free (window_title); + } +} + +static void +midori_web_view_statusbar_text_changed_cb (MidoriWebView* web_view, + const gchar* text, + MidoriBrowser* browser) +{ + _midori_browser_set_statusbar_text (browser, text); +} + +static void +midori_web_view_element_motion_cb (MidoriWebView* web_View, + const gchar* link_uri, + MidoriBrowser* browser) +{ + _midori_browser_set_statusbar_text (browser, link_uri); +} + +static void +midori_web_view_load_committed_cb (GtkWidget* web_view, + WebKitWebFrame* web_frame, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (web_view == midori_browser_get_current_web_view (browser)) + { + const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); + gtk_entry_set_text (GTK_ENTRY (priv->location), uri); + _midori_browser_set_statusbar_text (browser, NULL); + } +} + +static gboolean +midori_web_view_console_message_cb (GtkWidget* web_view, + const gchar* message, + gint line, + const gchar* source_id, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + midori_console_add (MIDORI_CONSOLE (priv->panel_console), + message, line, source_id); + return TRUE; +} + +static void +midori_web_view_populate_popup_cb (GtkWidget* web_view, + GtkWidget* menu, + MidoriBrowser* browser) +{ + const gchar* uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); + if (uri) + { + // TODO: bookmark link + } + + if (webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) + { + // TODO: view selection source + } + + if (!uri && !webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) + { + GtkAction* action = _action_by_name (browser, "UndoTabClose"); + GtkWidget* menuitem = gtk_action_create_menu_item (action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + menuitem = gtk_separator_menu_item_new (); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + action = _action_by_name (browser, "BookmarkAdd"); + menuitem = gtk_action_create_menu_item (action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + action = _action_by_name (browser, "SaveAs"); + menuitem = gtk_action_create_menu_item (action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + action = _action_by_name (browser, "SourceView"); + menuitem = gtk_action_create_menu_item (action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + action = _action_by_name (browser, "Print"); + menuitem = gtk_action_create_menu_item (action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + } +} + +static gboolean +midori_web_view_leave_notify_event_cb (GtkWidget* web_view, + GdkEventCrossing* event, + MidoriBrowser* browser) +{ + _midori_browser_set_statusbar_text (browser, NULL); + return TRUE; +} + +static void +midori_web_view_new_tab_cb (GtkWidget* web_view, + const gchar* uri, + MidoriBrowser* browser) +{ + gint n = midori_browser_add_uri (browser, uri); + _midori_browser_set_current_page_smartly (browser, n); +} + +static void +midori_web_view_new_window_cb (GtkWidget* web_view, + const gchar* uri, + MidoriBrowser* browser) +{ + g_signal_emit (browser, signals[NEW_WINDOW], 0, uri); +} + +static void +midori_web_view_close_cb (GtkWidget* web_view, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (priv->proxy_xbel_folder) + { + KatzeXbelItem* xbel_item = midori_web_view_get_proxy_xbel_item ( + MIDORI_WEB_VIEW (web_view)); + const gchar* uri = katze_xbel_bookmark_get_href (xbel_item); + if (priv->trash && uri && *uri) + midori_trash_prepend_xbel_item (priv->trash, xbel_item); + katze_xbel_folder_remove_item (priv->proxy_xbel_folder, xbel_item); + katze_xbel_item_unref (xbel_item); + } + GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, web_view); + guint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); + gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), n); + + _midori_browser_update_actions (browser); +} + +static gboolean +midori_web_view_destroy_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + _midori_browser_update_actions (browser); + return FALSE; +} + +static void +midori_cclosure_marshal_VOID__OBJECT_POINTER_POINTER (GClosure* closure, + GValue* return_value, + guint n_param_values, + const GValue* param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean(*GMarshalFunc_VOID__OBJECT_POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer arg_3, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_POINTER_POINTER callback; + register GCClosure* cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__OBJECT_POINTER_POINTER) (marshal_data + ? marshal_data : cc->callback); + + callback (data1, + g_value_get_object (param_values + 1), + g_value_get_pointer (param_values + 2), + g_value_get_pointer (param_values + 3), + data2); +} + +static void +midori_cclosure_marshal_INT__OBJECT (GClosure* closure, + GValue* return_value, + guint n_param_values, + const GValue* param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gint(*GMarshalFunc_INT__OBJECT) (gpointer data1, + gpointer arg_1, + gpointer data2); + register GMarshalFunc_INT__OBJECT callback; + register GCClosure* cc = (GCClosure*) closure; + register gpointer data1, data2; + gint v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_INT__OBJECT) (marshal_data + ? marshal_data : cc->callback); + v_return = callback (data1, + g_value_get_object (param_values + 1), + data2); + g_value_set_int (return_value, v_return); +} + +static void +midori_cclosure_marshal_INT__STRING (GClosure* closure, + GValue* return_value, + guint n_param_values, + const GValue* param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gint(*GMarshalFunc_INT__STRING) (gpointer data1, + const gchar* arg_1, + gpointer data2); + register GMarshalFunc_INT__STRING callback; + register GCClosure* cc = (GCClosure*) closure; + register gpointer data1, data2; + gint v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_INT__STRING) (marshal_data + ? marshal_data : cc->callback); + v_return = callback (data1, + g_value_get_string (param_values + 1), + data2); + g_value_set_int (return_value, v_return); +} + +static void +midori_browser_class_init (MidoriBrowserClass* class) +{ + signals[WINDOW_OBJECT_CLEARED] = g_signal_new ( + "window-object-cleared", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriBrowserClass, window_object_cleared), + 0, + NULL, + midori_cclosure_marshal_VOID__OBJECT_POINTER_POINTER, + G_TYPE_NONE, 3, + WEBKIT_TYPE_WEB_FRAME, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[STATUSBAR_TEXT_CHANGED] = g_signal_new ( + "statusbar-text-changed", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriBrowserClass, statusbar_text_changed), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[ELEMENT_MOTION] = g_signal_new ( + "element-motion", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriBrowserClass, element_motion), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[NEW_WINDOW] = g_signal_new ( + "new-window", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriBrowserClass, new_window), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[ADD_TAB] = g_signal_new ( + "add-tab", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriBrowserClass, add_tab), + 0, + NULL, + midori_cclosure_marshal_INT__OBJECT, + G_TYPE_INT, 1, + GTK_TYPE_WIDGET); + + signals[ADD_URI] = g_signal_new ( + "add-uri", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriBrowserClass, add_uri), + 0, + NULL, + midori_cclosure_marshal_INT__STRING, + G_TYPE_INT, 1, + G_TYPE_STRING); + + signals[ACTIVATE_ACTION] = g_signal_new ( + "activate-action", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriBrowserClass, activate_action), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[QUIT] = g_signal_new ( + "quit", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriBrowserClass, quit), + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + class->add_tab = midori_browser_add_tab; + class->add_uri = midori_browser_add_uri; + class->activate_action = midori_browser_activate_action; + class->quit = midori_browser_quit; + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_browser_finalize; + gobject_class->set_property = midori_browser_set_property; + gobject_class->get_property = midori_browser_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_MENUBAR, + g_param_spec_object ( + "menubar", + _("Menubar"), + _("The menubar"), + GTK_TYPE_MENU_BAR, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_NAVIGATIONBAR, + g_param_spec_object ( + "navigationbar", + _("Navigationbar"), + _("The navigationbar"), + GTK_TYPE_TOOLBAR, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_TAB, + g_param_spec_object ( + "tab", + _("Tab"), + _("The current tab"), + GTK_TYPE_WIDGET, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_STATUSBAR, + g_param_spec_object ( + "statusbar", + _("Statusbar"), + _("The statusbar"), + GTK_TYPE_STATUSBAR, + G_PARAM_READABLE)); + + /** + * MidoriBrowser:settings: + * + * An associated settings instance that is shared among all web views. + * + * Setting this value is propagated to every present web view. Also + * every newly created web view will use this instance automatically. + */ + g_object_class_install_property (gobject_class, + PROP_SETTINGS, + g_param_spec_object ( + "settings", + _("Settings"), + _("The associated settings"), + MIDORI_TYPE_WEB_SETTINGS, + G_PARAM_READWRITE)); + + /** + * MidoriBrowser:statusbar-text: + * + * The text that is displayed in the statusbar. + * + * This value reflects changes to the text visible in the statusbar, such + * as the uri of a hyperlink the mouse hovers over or the description of + * a menuitem. + * + * Setting this value changes the displayed text until the next change. + */ + g_object_class_install_property (gobject_class, + PROP_STATUSBAR_TEXT, + g_param_spec_string ( + "statusbar-text", + _("Statusbar Text"), + _("The text that is displayed in the statusbar"), + "", + flags)); + + /** + * MidoriBrowser:trash: + * + * The trash, that collects all closed tabs and windows. + * + * This is actually a reference to a trash instance, so if a trash should + * be used it must be initially set. + * + * Note: In the future the trash might collect other types of items. + */ + g_object_class_install_property (gobject_class, + PROP_TRASH, + g_param_spec_object ( + "trash", + _("Trash"), + _("The trash, collecting recently closed tabs and windows"), + MIDORI_TYPE_TRASH, + G_PARAM_READWRITE)); + + g_type_class_add_private (class, sizeof (MidoriBrowserPrivate)); +} + +static void +_action_window_new_activate (GtkAction* action, + MidoriBrowser* browser) +{ + g_signal_emit (browser, signals[NEW_WINDOW], 0, ""); +} + +static void +_action_tab_new_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gint n = midori_browser_add_uri (browser, ""); + midori_browser_set_current_page (browser, n); + gtk_widget_grab_focus (priv->location); +} + +static void +_action_open_activate (GtkAction* action, + MidoriBrowser* browser) +{ + static gchar* last_dir = NULL; + gchar* uri = NULL; + gboolean folder_set = FALSE; + GtkWidget* dialog = gtk_file_chooser_dialog_new ( + ("Open file"), GTK_WINDOW (browser), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_OPEN); + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (browser)); + + // base the start folder on the current web view's uri if it is local + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + if (web_view) + g_object_get (web_view, "uri", &uri, NULL); + if (uri) + { + gchar* filename = g_filename_from_uri (uri, NULL, NULL); + if (filename) + { + gchar* dirname = g_path_get_dirname (filename); + if (dirname && g_file_test (dirname, G_FILE_TEST_IS_DIR)) + { + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dirname); + folder_set = TRUE; + } + + g_free (dirname); + g_free (filename); + } + g_free (uri); + } + + if (!folder_set && last_dir && *last_dir) + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), last_dir); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + gchar* folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); + g_object_set (web_view, "uri", uri, NULL); + + g_free (last_dir); + last_dir = folder; + g_free (uri); + } + gtk_widget_destroy (dialog); +} + +static void +_action_tab_close_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = midori_browser_get_current_tab (browser); + GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); + gtk_widget_destroy (scrolled); +} + +static void +_action_window_close_activate (GtkAction* action, + MidoriBrowser* browser) +{ + gtk_widget_destroy (GTK_WIDGET (browser)); +} + +static void +_action_print_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_tab (browser); + if (web_view) + webkit_web_view_execute_script (WEBKIT_WEB_VIEW (web_view), "print ();"); +} + +static void +_action_quit_activate (GtkAction* action, + MidoriBrowser* browser) +{ + g_signal_emit (browser, signals[QUIT], 0); +} + +static void +_action_edit_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + gboolean can_cut = FALSE, can_copy = FALSE, can_paste = FALSE; + gboolean has_selection; + + if (WEBKIT_IS_WEB_VIEW (widget)) + { + WebKitWebView* web_view = WEBKIT_WEB_VIEW (widget); + can_cut = webkit_web_view_can_cut_clipboard (web_view); + can_copy = webkit_web_view_can_copy_clipboard (web_view); + can_paste = webkit_web_view_can_paste_clipboard (web_view); + } + else if (GTK_IS_EDITABLE (widget)) + { + GtkEditable* editable = GTK_EDITABLE (widget); + has_selection = gtk_editable_get_selection_bounds (editable, NULL, NULL); + can_cut = has_selection && gtk_editable_get_editable (editable); + can_copy = has_selection; + can_paste = gtk_editable_get_editable (editable); + } + + _action_set_sensitive (browser, "Cut", can_cut); + _action_set_sensitive (browser, "Copy", can_copy); + _action_set_sensitive (browser, "Paste", can_paste); + _action_set_sensitive (browser, "Delete", can_cut); + _action_set_sensitive (browser, "SelectAll", FALSE); +} + +static void +_action_cut_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + g_signal_emit_by_name (widget, "cut-clipboard"); +} + +static void +_action_copy_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + g_signal_emit_by_name (widget, "copy-clipboard"); +} + +static void +_action_paste_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + g_signal_emit_by_name (widget, "paste-clipboard"); +} + +static void +_action_delete_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + { + if (WEBKIT_IS_WEB_VIEW (widget)) + webkit_web_view_delete_selection (WEBKIT_WEB_VIEW (widget)); + else if (GTK_IS_EDITABLE(widget)) + gtk_editable_delete_selection (GTK_EDITABLE (widget)); + } +} + +static void +_action_select_all_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); + if (G_LIKELY (widget)) + { + if (GTK_IS_EDITABLE (widget)) + gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1); + else + g_signal_emit_by_name (widget, "select-all"); + } +} + +static void +_action_find_activate(GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (GTK_WIDGET_VISIBLE (priv->find)) + { + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (web_view)); + gtk_toggle_tool_button_set_active ( + GTK_TOGGLE_TOOL_BUTTON (priv->find_highlight), FALSE); + gtk_widget_hide (priv->find); + } + else + { + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FIND, + GTK_ICON_SIZE_MENU); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->find_text), + SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE (icon)); + gtk_entry_set_text (GTK_ENTRY (priv->find_text), ""); + gtk_widget_show (priv->find); + gtk_widget_grab_focus (GTK_WIDGET (priv->find_text)); + } +} + +static void +_midori_browser_find (MidoriBrowser* browser, + gboolean forward) +{ + MidoriBrowserPrivate* priv = browser->priv; + + const gchar* text = gtk_entry_get_text (GTK_ENTRY (priv->find_text)); + const gboolean case_sensitive = gtk_toggle_tool_button_get_active ( + GTK_TOGGLE_TOOL_BUTTON(priv->find_case)); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + if (GTK_WIDGET_VISIBLE (priv->find)) + webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (web_view)); + gboolean found = webkit_web_view_search_text (WEBKIT_WEB_VIEW (web_view), + text, case_sensitive, forward, TRUE); + if (GTK_WIDGET_VISIBLE (priv->find)) + { + GtkWidget* icon; + if (found) + icon = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); + else + icon = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->find_text), + SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); + webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (web_view), text, + case_sensitive, 0); + const gboolean highlight = gtk_toggle_tool_button_get_active ( + GTK_TOGGLE_TOOL_BUTTON (priv->find_highlight)); + webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (web_view), + highlight); + } +} + +static void +_action_find_next_activate (GtkAction* action, + MidoriBrowser* browser) +{ + _midori_browser_find (browser, TRUE); +} + +static void +_action_find_previous_activate (GtkAction* action, + MidoriBrowser* browser) +{ + _midori_browser_find (browser, FALSE); +} + +static void +_find_highlight_toggled (GtkToggleToolButton* toolitem, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gboolean highlight = gtk_toggle_tool_button_get_active (toolitem); + webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (web_view), + highlight); +} + +static void +midori_browser_find_button_close_clicked_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gtk_widget_hide (priv->find); +} + +static void +midori_browser_navigationbar_notify_style_cb (GObject* object, + GParamSpec* arg1, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + MidoriToolbarStyle toolbar_style; + GtkToolbarStyle gtk_toolbar_style; + + g_object_get (priv->settings, "toolbar-style", &toolbar_style, NULL); + if (toolbar_style == MIDORI_TOOLBAR_DEFAULT) + { + g_object_get (priv->settings, + "gtk-toolbar-style", >k_toolbar_style, NULL); + gtk_toolbar_set_style (GTK_TOOLBAR (priv->navigationbar), + gtk_toolbar_style); + } +} + +static void +midori_browser_menu_trash_item_activate_cb (GtkWidget* menuitem, + MidoriBrowser* browser) +{ + // Create a new web view with an uri which has been closed before + KatzeXbelItem* item = g_object_get_data (G_OBJECT (menuitem), + "KatzeXbelItem"); + const gchar* uri = katze_xbel_bookmark_get_href (item); + gint n = midori_browser_add_uri (browser, uri); + midori_browser_set_current_page (browser, n); + katze_xbel_item_unref (item); +} + +static void +midori_browser_menu_trash_activate_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* menu = gtk_menu_new (); + guint n = midori_trash_get_n_items (priv->trash); + GtkWidget* menuitem; + guint i; + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, i); + const gchar* title = katze_xbel_item_get_title (item); + const gchar* uri = katze_xbel_bookmark_get_href (item); + menuitem = gtk_image_menu_item_new_with_label (title ? title : uri); + // FIXME: Get the real icon + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); + gtk_menu_shell_append(GTK_MENU_SHELL (menu), menuitem); + g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_menu_trash_item_activate_cb), browser); + gtk_widget_show (menuitem); + } + + menuitem = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + GtkAction* action = gtk_action_group_get_action (priv->action_group, + "TrashEmpty"); + menuitem = gtk_action_create_menu_item (action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + if (GTK_IS_MENU_ITEM (widget)) + gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), menu); + else + sokoke_widget_popup (widget, GTK_MENU (menu), NULL, + SOKOKE_MENU_POSITION_RIGHT); +} + +static void +_action_preferences_activate (GtkAction* action, + MidoriBrowser* browser) +{ + // Show the preferences dialog. Create it if necessary. + static GtkWidget* dialog = NULL; + if (GTK_IS_DIALOG (dialog)) + gtk_window_present (GTK_WINDOW (dialog)); + else + { + MidoriBrowserPrivate* priv = browser->priv; + + dialog = midori_preferences_new (GTK_WINDOW (browser), + priv->settings); + gtk_widget_show (dialog); + } +} + +static void +_action_navigationbar_activate (GtkToggleAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean active = gtk_toggle_action_get_active (action); + g_object_set (priv->settings, "show-navigationbar", active, NULL); + sokoke_widget_set_visible (priv->navigationbar, active); +} + +static void +_action_bookmarkbar_activate (GtkToggleAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean active = gtk_toggle_action_get_active (action); + g_object_set (priv->settings, "show-bookmarkbar", active, NULL); + sokoke_widget_set_visible (priv->bookmarkbar, active); +} + +static void +_action_statusbar_activate (GtkToggleAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean active = gtk_toggle_action_get_active (action); + g_object_set (priv->settings, "show-statusbar", active, NULL); + sokoke_widget_set_visible (priv->statusbar, active); +} + +static void +_action_reload_stop_activate (GtkAction* action, + MidoriBrowser* browser) +{ + gchar* stock_id; + g_object_get (action, "stock-id", &stock_id, NULL); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + // Refresh or stop, depending on the stock id + if (!strcmp (stock_id, GTK_STOCK_REFRESH)) + { + /*GdkModifierType state = (GdkModifierType)0; + gint x, y; + gdk_window_get_pointer (NULL, &x, &y, &state); + gboolean from_cache = state & GDK_SHIFT_MASK;*/ + webkit_web_view_reload (WEBKIT_WEB_VIEW (web_view)); + } + else + webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view)); + g_free (stock_id); +} + +static void +_action_zoom_in_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + if (web_view && g_object_class_find_property ( + G_OBJECT_GET_CLASS (web_view), "zoom-level")) + { + MidoriBrowserPrivate* priv = browser->priv; + + gfloat zoom_level, zoom_step; + g_object_get (web_view, "zoom-level", &zoom_level, NULL); + g_object_get (priv->settings, "zoom-step", &zoom_step, NULL); + g_object_set (web_view, "zoom-level", zoom_level + zoom_step, NULL); + } +} + +static void +_action_zoom_out_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + if (web_view && g_object_class_find_property ( + G_OBJECT_GET_CLASS (web_view), "zoom-level")) + { + MidoriBrowserPrivate* priv = browser->priv; + + gfloat zoom_level, zoom_step; + g_object_get (web_view, "zoom-level", &zoom_level, NULL); + g_object_get (priv->settings, "zoom-step", &zoom_step, NULL); + g_object_set (web_view, "zoom-level", zoom_level - zoom_step, NULL); + } +} + +static void +_action_zoom_normal_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + if (web_view && g_object_class_find_property ( + G_OBJECT_GET_CLASS (web_view), "zoom-level")) + g_object_set (web_view, "zoom-level", 1.0, NULL); +} + +/*static void +_action_source_view_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + gchar* source = webkit_web_view_copy_source (WEBKIT_WEB_VIEW (web_view)); + webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (web_view), source, ""); + g_free (source); +}*/ + +static void +_action_fullscreen_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GdkWindowState state = gdk_window_get_state (GTK_WIDGET (browser)->window); + if (state & GDK_WINDOW_STATE_FULLSCREEN) + gtk_window_unfullscreen (GTK_WINDOW (browser)); + else + gtk_window_fullscreen (GTK_WINDOW (browser)); +} + +static void +_action_back_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + webkit_web_view_go_back (WEBKIT_WEB_VIEW (web_view)); +} + +static void +_action_forward_activate (GtkAction* action, + MidoriBrowser* browser) +{ + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + webkit_web_view_go_forward (WEBKIT_WEB_VIEW (web_view)); +} + +static void +_action_homepage_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gchar* homepage; + + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + g_object_get (priv->settings, "homepage", &homepage, NULL); + g_object_set (web_view, "uri", homepage, NULL); + g_free (homepage); +} + +static gboolean +midori_browser_location_key_press_event_cb (GtkWidget* widget, + GdkEventKey* event, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + gchar* location_entry_search; + + switch (event->keyval) + { + case GDK_ISO_Enter: + case GDK_KP_Enter: + case GDK_Return: + { + const gchar* uri = gtk_entry_get_text (GTK_ENTRY (widget)); + if (uri) + { + g_object_get (priv->settings, "location-entry-search", + &location_entry_search, NULL); + gchar* new_uri = sokoke_magic_uri (uri, location_entry_search); + g_free (location_entry_search); + // TODO: Use new_uri intermediately when completion is better + /* TODO Completion should be generated from history, that is + the uri as well as the title. */ + sokoke_entry_append_completion (GTK_ENTRY (widget), uri); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + g_object_set (web_view, "uri", new_uri, NULL); + g_free (new_uri); + gtk_widget_grab_focus (web_view); + } + return TRUE; + } + case GDK_Escape: + { + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gchar* uri = midori_web_view_get_display_uri ( + MIDORI_WEB_VIEW (web_view)); + gtk_entry_set_text (GTK_ENTRY (widget), uri); + return TRUE; + } + } + return FALSE; +} + +static void +_action_location_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (!GTK_WIDGET_VISIBLE (priv->navigationbar)) + gtk_widget_show (priv->navigationbar); + gtk_widget_grab_focus (priv->location); +} + +static gboolean +midori_browser_location_focus_out_event_cb (GtkWidget* widget, + GdkEventFocus* event, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean show_navigationbar; + g_object_get (priv->settings, + "show-navigationbar", &show_navigationbar, + NULL); + if (!show_navigationbar) + gtk_widget_hide (priv->navigationbar); + return FALSE; +} + +static void +_action_search_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (!GTK_WIDGET_VISIBLE (priv->search)) + gtk_widget_show (priv->search); + if (!GTK_WIDGET_VISIBLE (priv->navigationbar)) + gtk_widget_show (priv->navigationbar); + gtk_widget_grab_focus (priv->search); +} + +static gboolean +midori_browser_search_focus_out_event_cb (GtkWidget* widget, + GdkEventFocus* event, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean show_navigationbar; + gboolean show_web_search; + g_object_get (priv->settings, + "show-navigationbar", &show_navigationbar, + "show-web-search", &show_web_search, + NULL); + if (!show_navigationbar) + gtk_widget_hide (priv->navigationbar); + if (!show_web_search) + gtk_widget_hide (priv->search); + return FALSE; +} + +static void +midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, + KatzeXbelItem* bookmark) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean new_bookmark = !bookmark; + GtkWidget* dialog = gtk_dialog_new_with_buttons ( + new_bookmark ? _("New bookmark") : _("Edit bookmark"), + GTK_WINDOW (browser), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + new_bookmark ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_window_set_icon_name (GTK_WINDOW (dialog), + new_bookmark ? GTK_STOCK_ADD : GTK_STOCK_REMOVE); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5); + GtkSizeGroup* sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + if (new_bookmark) + bookmark = katze_xbel_bookmark_new (); + + GtkWidget* hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + GtkWidget* label = gtk_label_new_with_mnemonic (_("_Title:")); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_title = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_title), TRUE); + if (!new_bookmark) + { + const gchar* title = katze_xbel_item_get_title (bookmark); + gtk_entry_set_text (GTK_ENTRY (entry_title), title ? title : ""); + } + gtk_box_pack_start (GTK_BOX (hbox), entry_title, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + + hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + label = gtk_label_new_with_mnemonic (_("_Description:")); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_desc = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_desc), TRUE); + if (!new_bookmark) + { + const gchar* desc = katze_xbel_item_get_desc (bookmark); + gtk_entry_set_text (GTK_ENTRY (entry_desc), desc ? desc : ""); + } + gtk_box_pack_start (GTK_BOX (hbox), entry_desc, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + + GtkWidget* entry_uri = NULL; + if (katze_xbel_item_is_bookmark (bookmark)) + { + hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + label = gtk_label_new_with_mnemonic (_("_URL:")); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + entry_uri = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE); + if (!new_bookmark) + gtk_entry_set_text (GTK_ENTRY (entry_uri), + katze_xbel_bookmark_get_href (bookmark)); + gtk_box_pack_start (GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + } + + GtkWidget* combo_folder = NULL; + if (new_bookmark) + { + hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + label = gtk_label_new_with_mnemonic (_("_Folder:")); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + combo_folder = gtk_combo_box_new_text (); + gtk_combo_box_append_text (GTK_COMBO_BOX (combo_folder), _("Root")); + gtk_widget_set_sensitive (combo_folder, FALSE); + gtk_box_pack_start (GTK_BOX (hbox), combo_folder, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); + gtk_widget_show_all (hbox); + } + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + katze_xbel_item_set_title (bookmark, + gtk_entry_get_text (GTK_ENTRY (entry_title))); + katze_xbel_item_set_desc (bookmark, + gtk_entry_get_text(GTK_ENTRY(entry_desc))); + if (katze_xbel_item_is_bookmark (bookmark)) + katze_xbel_bookmark_set_href (bookmark, + gtk_entry_get_text (GTK_ENTRY (entry_uri))); + + // FIXME: We want to choose a folder + if (new_bookmark) + { + katze_xbel_folder_append_item (bookmarks, bookmark); + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeModel* treemodel = gtk_tree_view_get_model (treeview); + GtkTreeIter iter; + gtk_tree_store_insert_with_values (GTK_TREE_STORE (treemodel), + &iter, NULL, G_MAXINT, 0, bookmark, -1); + katze_xbel_item_ref (bookmark); + } + + // FIXME: update navigationbar + // FIXME: Update panel in other windows + } + gtk_widget_destroy (dialog); +} + +static void +midori_panel_bookmarks_row_activated_cb (GtkTreeView* treeview, + GtkTreePath* path, + GtkTreeViewColumn* column, + MidoriBrowser* browser) +{ + GtkTreeModel* model = gtk_tree_view_get_model (treeview); + GtkTreeIter iter; + if (gtk_tree_model_get_iter (model, &iter, path)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (katze_xbel_item_is_bookmark (item)) + { + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gchar* uri = katze_xbel_bookmark_get_href (item); + g_object_set (web_view, "uri", uri, NULL); + } + } +} + +static void +midori_panel_bookmarks_cursor_or_row_changed_cb (GtkTreeView* treeview, + MidoriBrowser* browser) +{ + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + + gboolean is_separator = katze_xbel_item_is_separator (item); + _action_set_sensitive (browser, "BookmarkEdit", !is_separator); + _action_set_sensitive (browser, "BookmarkDelete", TRUE); + } + else + { + _action_set_sensitive (browser, "BookmarkEdit", FALSE); + _action_set_sensitive (browser, "BookmarkDelete", FALSE); + } + } +} + +static void +_midori_panel_bookmarks_popup (GtkWidget* widget, + GdkEventButton* event, + KatzeXbelItem* item, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean is_bookmark = katze_xbel_item_is_bookmark (item); + + _action_set_sensitive (browser, "BookmarkOpen", is_bookmark); + _action_set_sensitive (browser, "BookmarkOpenTab", is_bookmark); + _action_set_sensitive (browser, "BookmarkOpenWindow", is_bookmark); + + sokoke_widget_popup (widget, GTK_MENU (priv->popup_bookmark), + event, SOKOKE_MENU_POSITION_CURSOR); +} + +static gboolean +midori_panel_bookmarks_button_release_event_cb (GtkWidget* widget, + GdkEventButton* event, + MidoriBrowser* browser) +{ + if (event->button != 2 && event->button != 3) + return FALSE; + + GtkTreeSelection* selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (widget)); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (event->button == 2 && katze_xbel_item_is_bookmark (item)) + { + const gchar* uri = katze_xbel_bookmark_get_href (item); + gint n = midori_browser_add_uri (browser, uri); + midori_browser_set_current_page (browser, n); + } + else + _midori_panel_bookmarks_popup (widget, event, item, browser); + return TRUE; + } + } + return FALSE; +} + +static void +midori_panel_bookmarks_popup_menu_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + GtkTreeSelection* selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (widget)); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + _midori_panel_bookmarks_popup (widget, NULL, item, browser); + } + } +} + +static void +_tree_store_insert_folder (GtkTreeStore* treestore, + GtkTreeIter* parent, + KatzeXbelItem* folder) +{ + guint n = katze_xbel_folder_get_n_items (folder); + guint i; + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i); + GtkTreeIter iter; + gtk_tree_store_insert_with_values (treestore, &iter, parent, n, + 0, item, -1); + katze_xbel_item_ref (item); + if (katze_xbel_item_is_folder (item)) + _tree_store_insert_folder (treestore, &iter, item); + } +} + +static void +midori_browser_bookmarks_item_render_icon_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + KatzeXbelItem* item; + gtk_tree_model_get (model, iter, 0, &item, -1); + + if (G_UNLIKELY (!item)) + return; + if (G_UNLIKELY (!katze_xbel_item_get_parent (item))) + { + gtk_tree_store_remove (GTK_TREE_STORE (model), iter); + katze_xbel_item_unref (item); + return; + } + + // TODO: Would it be better to not do this on every redraw? + GdkPixbuf* pixbuf = NULL; + if (katze_xbel_item_is_bookmark (item)) + pixbuf = gtk_widget_render_icon (treeview, STOCK_BOOKMARK, + GTK_ICON_SIZE_MENU, NULL); + else if (katze_xbel_item_is_folder (item)) + pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY, + GTK_ICON_SIZE_MENU, NULL); + g_object_set (renderer, "pixbuf", pixbuf, NULL); + if (pixbuf) + g_object_unref (pixbuf); +} + +static void +midori_browser_bookmarks_item_render_text_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + KatzeXbelItem* item; + gtk_tree_model_get (model, iter, 0, &item, -1); + + if (G_UNLIKELY (!item)) + return; + if (G_UNLIKELY (!katze_xbel_item_get_parent (item))) + { + gtk_tree_store_remove (GTK_TREE_STORE (model), iter); + katze_xbel_item_unref (item); + return; + } + + if (katze_xbel_item_is_separator (item)) + g_object_set (renderer, "markup", _("Separator"), NULL); + else + g_object_set (renderer, "markup", NULL, + "text", katze_xbel_item_get_title (item), NULL); +} + +static void +_midori_browser_create_bookmark_menu (MidoriBrowser* browser, + KatzeXbelItem* folder, + GtkWidget* menu); + +static void +midori_browser_bookmark_menu_folder_activate_cb (GtkWidget* menuitem, + MidoriBrowser* browser) +{ + GtkWidget* menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menuitem)); + gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) gtk_widget_destroy, NULL);//... + KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT (menuitem), "KatzeXbelItem"); + _midori_browser_create_bookmark_menu (browser, folder, menu); + // Remove all menuitems when the menu is hidden. + // FIXME: We really *want* the line below, but it won't work like that + //g_signal_connect_after (menu, "hide", G_CALLBACK (gtk_container_foreach), gtk_widget_destroy); + gtk_widget_show (menuitem); +} + +static void +midori_browser_bookmarkbar_folder_activate_cb (GtkToolItem* toolitem, + MidoriBrowser* browser) +{ + GtkWidget* menu = gtk_menu_new (); + KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data ( + G_OBJECT (toolitem), "KatzeXbelItem"); + _midori_browser_create_bookmark_menu (browser, folder, menu); + // Remove all menuitems when the menu is hidden. + // FIXME: We really *should* run the line below, but it won't work like that + /*g_signal_connect (menu, "hide", G_CALLBACK (gtk_container_foreach), + gtk_widget_destroy);*/ + sokoke_widget_popup (GTK_WIDGET (toolitem), GTK_MENU (menu), + NULL, SOKOKE_MENU_POSITION_LEFT); +} + +static void +midori_browser_menu_bookmarks_item_activate_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + KatzeXbelItem* item = (KatzeXbelItem*)g_object_get_data (G_OBJECT (widget), + "KatzeXbelItem"); + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + g_object_set (web_view, "uri", katze_xbel_bookmark_get_href (item), NULL); + gtk_widget_grab_focus (web_view); +} + +static void +_midori_browser_create_bookmark_menu (MidoriBrowser* browser, + KatzeXbelItem* folder, + GtkWidget* menu) +{ + guint n = katze_xbel_folder_get_n_items (folder); + guint i; + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i); + const gchar* title = katze_xbel_item_is_separator (item) + ? "" : katze_xbel_item_get_title (item); + /* const gchar* desc = katze_xbel_item_is_separator (item) + ? "" : katze_xbel_item_get_desc (item); */ + GtkWidget* menuitem = NULL; + switch (katze_xbel_item_get_kind (item)) + { + case KATZE_XBEL_ITEM_KIND_FOLDER: + // FIXME: what about katze_xbel_folder_is_folded? + menuitem = gtk_image_menu_item_new_with_label (title); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), + gtk_image_new_from_stock (GTK_STOCK_DIRECTORY, + GTK_ICON_SIZE_MENU)); + GtkWidget* _menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), _menu); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_bookmark_menu_folder_activate_cb), + browser); + g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); + break; + case KATZE_XBEL_ITEM_KIND_BOOKMARK: + menuitem = gtk_image_menu_item_new_with_label (title); + GtkWidget* image = gtk_image_new_from_stock (STOCK_BOOKMARK, + GTK_ICON_SIZE_MENU); + gtk_widget_show (image); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), + image); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_menu_bookmarks_item_activate_cb), + browser); + g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); + break; + case KATZE_XBEL_ITEM_KIND_SEPARATOR: + menuitem = gtk_separator_menu_item_new (); + break; + default: + g_warning ("Unknown xbel item kind"); + } + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + } +} + +static void +_action_bookmark_add_activate (GtkAction* action, + MidoriBrowser* browser) +{ + midori_browser_edit_bookmark_dialog_new (browser, NULL); +} + +static void +_action_manage_search_engines_activate (GtkAction* action, + MidoriBrowser* browser) +{ + // Show the Manage search engines dialog. Create it if necessary. + static GtkWidget* dialog; + if (GTK_IS_DIALOG (dialog)) + gtk_window_present (GTK_WINDOW (dialog)); + else + { + dialog = webSearch_manageSearchEngines_dialog_new (browser); + gtk_widget_show (dialog); + } +} + +static void +_action_tab_previous_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n - 1); +} + +static void +_action_tab_next_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + // Advance one tab or jump to the first one if we are at the last one + gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); + if (n == gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)) - 1) + n = -1; + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n + 1); +} + +static void +midori_browser_window_menu_item_activate_cb (GtkWidget* widget, + GtkWidget* web_view) +{ + MidoriBrowser* browser = MIDORI_BROWSER (gtk_widget_get_toplevel (web_view)); + if (!browser) + { + g_warning ("Orphaned web view"); + return; + } + + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, web_view); + guint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); +} + +static const gchar* credits_authors[] = { + "Christian Dywan ", NULL }; +static const gchar* credits_documenters/*[]*/ = /*{ + */NULL/* }*/; +static const gchar* credits_artists[] = { + "Nancy Runge ", NULL }; + +static const gchar* license = + "This library is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU Lesser General Public\n" + "License as published by the Free Software Foundation; either\n" + "version 2.1 of the License, or (at your option) any later version.\n"; + +static void +_action_about_activate (GtkAction* action, + MidoriBrowser* browser) +{ + gtk_show_about_dialog (GTK_WINDOW (browser), + "logo-icon-name", gtk_window_get_icon_name (GTK_WINDOW (browser)), + "name", PACKAGE_NAME, + "version", PACKAGE_VERSION, + "comments", _("A lightweight web browser."), + "copyright", "Copyright © 2007-2008 Christian Dywan", + "website", "http://software.twotoasts.de", + "authors", credits_authors, + "documenters", credits_documenters, + "artists", credits_artists, + "license", license, + "wrap-license", TRUE, + "translator-credits", _("translator-credits"), + NULL); +} + +static void +midori_browser_location_changed_cb (GtkWidget* widget, + MidoriBrowser* browser) +{ + // Preserve changes to the uri + /*const gchar* newUri = gtk_entry_get_text(GTK_ENTRY(widget)); + katze_xbel_bookmark_set_href(browser->sessionItem, newUri);*/ + // FIXME: If we want this feature, this is the wrong approach +} + +static void +_action_panel_activate (GtkToggleAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean active = gtk_toggle_action_get_active (action); + g_object_set (priv->settings, "show-panel", active, NULL); + sokoke_widget_set_visible (priv->panel, active); +} + +static void +_action_open_in_panel_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); + // FIXME: Don't assign the uri here, update it properly while navigating + g_object_set (priv->settings, "last-pageholder-uri", uri, NULL); + gint n = midori_panel_page_num (MIDORI_PANEL (priv->panel), + priv->panel_pageholder); + midori_panel_set_current_page (MIDORI_PANEL (priv->panel), n); + gtk_widget_show (priv->panel); + g_object_set (priv->panel_pageholder, "uri", uri, NULL); +} + + +static void +midori_panel_notify_position_cb (GObject* object, + GParamSpec* arg1, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean position = gtk_paned_get_position (GTK_PANED (object)); + g_object_set (priv->settings, "last-panel-position", position, NULL); +} + +static gboolean +midori_panel_close_cb (MidoriPanel* panel, + MidoriBrowser* browser) +{ + _action_set_active (browser, "Panel", FALSE); + return FALSE; +} + +static void +gtk_notebook_switch_page_cb (GtkWidget* widget, + GtkNotebookPage* page, + guint page_num, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* web_view = midori_browser_get_current_web_view (browser); + const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); + gtk_entry_set_text (GTK_ENTRY (priv->location), uri); + const gchar* title = midori_web_view_get_display_title ( + MIDORI_WEB_VIEW (web_view)); + gchar* window_title = g_strconcat (title, " - ", + g_get_application_name (), NULL); + gtk_window_set_title (GTK_WINDOW (browser), window_title); + g_free (window_title); + _midori_browser_set_statusbar_text (browser, NULL); + _midori_browser_update_interface (browser); +} + +static void +_action_bookmark_open_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (katze_xbel_item_is_bookmark (item)) + g_object_set (midori_browser_get_current_web_view (browser), + "uri", katze_xbel_bookmark_get_href(item), NULL); + } + } +} + +static void +_action_bookmark_open_tab_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (katze_xbel_item_is_bookmark (item)) + { + gint n = midori_browser_add_xbel_item (browser, item); + _midori_browser_set_current_page_smartly (browser, n); + } + } + } +} + +static void +_action_bookmark_open_window_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (katze_xbel_item_is_bookmark (item)) + { + gint n = midori_browser_add_xbel_item (browser, item); + _midori_browser_set_current_page_smartly (browser, n); + } + } + } +} + +static void +_action_bookmark_edit_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + if (!katze_xbel_item_is_separator (item)) + midori_browser_edit_bookmark_dialog_new (browser, item); + } + } +} + +static void +_action_undo_tab_close_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + // Reopen the most recent trash item + KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, 0); + gint n = midori_browser_add_xbel_item (browser, item); + midori_browser_set_current_page (browser, n); + midori_trash_remove_nth_item (priv->trash, 0); + _midori_browser_update_actions (browser); +} + +static void +_action_trash_empty_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + midori_trash_empty (priv->trash); + _midori_browser_update_actions (browser); +} + +static void +_action_bookmark_delete_activate (GtkAction* action, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); + if (selection) + { + GtkTreeModel* model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + KatzeXbelItem* item; + gtk_tree_model_get (model, &iter, 0, &item, -1); + KatzeXbelItem* parent = katze_xbel_item_get_parent (item); + katze_xbel_folder_remove_item (parent, item); + katze_xbel_item_unref (item); + } + } +} + +static const GtkActionEntry entries[] = { + { "File", NULL, N_("_File") }, + { "WindowNew", STOCK_WINDOW_NEW, + NULL, "n", + N_("Open a new window"), G_CALLBACK (_action_window_new_activate) }, + { "TabNew", STOCK_TAB_NEW, + NULL, "t", + N_("Open a new tab"), G_CALLBACK (_action_tab_new_activate) }, + { "Open", GTK_STOCK_OPEN, + NULL, "o", + N_("Open a file"), G_CALLBACK (_action_open_activate) }, + { "SaveAs", GTK_STOCK_SAVE_AS, + NULL, "s", + N_("Save to a file"), NULL/*G_CALLBACK (_action_saveas_activate)*/ }, + { "TabClose", NULL, + N_("_Close Tab"), "w", + N_("Close the current tab"), G_CALLBACK (_action_tab_close_activate) }, + { "WindowClose", NULL, + N_("C_lose Window"), "w", + N_("Close this window"), G_CALLBACK (_action_window_close_activate) }, + { "PageSetup", GTK_STOCK_PROPERTIES, + N_("Pa_ge Setup"), "", + "Configure your print settings", NULL/*G_CALLBACK (_action_page_setup_activate)*/ }, + { "PrintPreview", GTK_STOCK_PRINT_PREVIEW, + NULL, "", + N_("Show a preview of the printed page"), NULL/*G_CALLBACK (_action_print_preview_activate)*/ }, + { "Print", GTK_STOCK_PRINT, + NULL, "p", + N_("Print the current page"), G_CALLBACK (_action_print_activate) }, + { "Quit", GTK_STOCK_QUIT, + NULL, "q", + N_("Quit the application"), G_CALLBACK (_action_quit_activate) }, + + { "Edit", NULL, N_("_Edit"), NULL, NULL, G_CALLBACK (_action_edit_activate) }, + { "Undo", GTK_STOCK_UNDO, + NULL, "z", + N_("Undo the last modification"), NULL/*G_CALLBACK (_action_undo_activate)*/ }, + { "Redo", GTK_STOCK_REDO, + NULL, "z", + N_("Redo the last modification"), NULL/*G_CALLBACK (_action_redo_activate)*/ }, + { "Cut", GTK_STOCK_CUT, + NULL, "x", + N_("Cut the selected text"), G_CALLBACK (_action_cut_activate) }, + { "Copy", GTK_STOCK_COPY, + NULL, "c", + N_("Copy the selected text"), G_CALLBACK (_action_copy_activate) }, + { "Copy_", GTK_STOCK_COPY, + NULL, "c", + N_("Copy the selected text"), G_CALLBACK (_action_copy_activate) }, + { "Paste", GTK_STOCK_PASTE, + NULL, "v", + N_("Paste text from the clipboard"), G_CALLBACK (_action_paste_activate) }, + { "Delete", GTK_STOCK_DELETE, + NULL, NULL, + N_("Delete the selected text"), G_CALLBACK (_action_delete_activate) }, + { "SelectAll", GTK_STOCK_SELECT_ALL, + NULL, "a", + N_("Select all text"), G_CALLBACK (_action_select_all_activate) }, + { "Find", GTK_STOCK_FIND, + NULL, "f", + N_("Find a word or phrase in the page"), G_CALLBACK (_action_find_activate) }, + { "FindNext", GTK_STOCK_GO_FORWARD, + N_("Find _Next"), "g", + N_("Find the next occurrence of a word or phrase"), G_CALLBACK (_action_find_next_activate) }, + { "FindPrevious", GTK_STOCK_GO_BACK, + N_("Find _Previous"), "g", + N_("Find the previous occurrence of a word or phrase"), G_CALLBACK (_action_find_previous_activate) }, + { "FindQuick", GTK_STOCK_FIND, + N_("_Quick Find"), "period", + N_("Quickly jump to a word or phrase"), NULL/*G_CALLBACK (_action_find_quick_activate)*/ }, + { "Preferences", GTK_STOCK_PREFERENCES, + NULL, "p", + N_("Configure the application preferences"), G_CALLBACK (_action_preferences_activate) }, + + { "View", NULL, N_("_View") }, + { "Toolbars", NULL, N_("_Toolbars") }, + { "Reload", GTK_STOCK_REFRESH, + NULL, "r", + N_("Reload the current page"), G_CALLBACK (_action_reload_stop_activate) }, + { "Stop", GTK_STOCK_STOP, + NULL, "Escape", + N_("Stop loading the current page"), G_CALLBACK (_action_reload_stop_activate) }, + { "ReloadStop", GTK_STOCK_STOP, + NULL, "r", + N_("Reload the current page"), G_CALLBACK (_action_reload_stop_activate) }, + { "ZoomIn", GTK_STOCK_ZOOM_IN, + NULL, "plus", + N_("Increase the zoom level"), G_CALLBACK (_action_zoom_in_activate) }, + { "ZoomOut", GTK_STOCK_ZOOM_OUT, + NULL, "minus", + N_("Decrease the zoom level"), G_CALLBACK (_action_zoom_out_activate) }, + { "ZoomNormal", GTK_STOCK_ZOOM_100, + NULL, "0", + N_("Reset the zoom level"), G_CALLBACK (_action_zoom_normal_activate) }, + { "SourceView", NULL, + N_("View Source"), "", + N_("View the source code of the page"), /*G_CALLBACK (_action_source_view_activate)*/ }, + { "SelectionSourceView", NULL, + N_("View Selection Source"), "", + N_("View the source code of the selection"), NULL/*G_CALLBACK (_action_selection_source_view_activate)*/ }, + { "Fullscreen", GTK_STOCK_FULLSCREEN, + NULL, "F11", + N_("Toggle fullscreen view"), G_CALLBACK (_action_fullscreen_activate) }, + + { "Go", NULL, N_("_Go") }, + { "Back", GTK_STOCK_GO_BACK, + NULL, "Left", + N_("Go back to the previous page"), G_CALLBACK (_action_back_activate) }, + { "Forward", GTK_STOCK_GO_FORWARD, + NULL, "Right", + N_("Go forward to the next page"), G_CALLBACK (_action_forward_activate) }, + { "Homepage", STOCK_HOMEPAGE, + NULL, "Home", + N_("Go to your homepage"), G_CALLBACK (_action_homepage_activate) }, + { "Location", GTK_STOCK_JUMP_TO, + N_("Location..."), "l", + N_("Open a particular location"), G_CALLBACK (_action_location_activate) }, + { "Search", GTK_STOCK_FIND, + N_("Web Search..."), "f", + N_("Run a web search"), G_CALLBACK (_action_search_activate) }, + { "OpenInPageholder", GTK_STOCK_JUMP_TO, + N_("Open in Page_holder..."), "", + N_("Open the current page in the pageholder"), G_CALLBACK (_action_open_in_panel_activate) }, + { "Trash", STOCK_USER_TRASH, + N_("Closed Tabs and Windows"), "", + N_("Reopen a previously closed tab or window"), NULL }, + { "TrashEmpty", GTK_STOCK_CLEAR, + N_("Empty Trash"), "", + N_("Delete the contents of the trash"), G_CALLBACK (_action_trash_empty_activate) }, + { "UndoTabClose", GTK_STOCK_UNDELETE, + N_("Undo Close Tab"), "", + N_("Open the last closed tab"), G_CALLBACK (_action_undo_tab_close_activate) }, + + { "Bookmarks", NULL, N_("_Bookmarks") }, + { "BookmarkAdd", STOCK_BOOKMARK_ADD, + NULL, "d", + N_("Add a new bookmark"), G_CALLBACK (_action_bookmark_add_activate) }, + { "BookmarksManage", NULL, + N_("_Manage Bookmarks"), "b", + N_("Add, edit and remove bookmarks..."), NULL/*G_CALLBACK (_action_bookmarks_manage_activate)*/ }, + { "BookmarkOpen", GTK_STOCK_OPEN, + NULL, "", + N_("Open the selected bookmark"), G_CALLBACK (_action_bookmark_open_activate) }, + { "BookmarkOpenTab", STOCK_TAB_NEW, + N_("Open in New _Tab"), "", + N_("Open the selected bookmark in a new tab"), G_CALLBACK (_action_bookmark_open_tab_activate) }, + { "BookmarkOpenWindow", STOCK_WINDOW_NEW, + N_("Open in New _Window"), "", + N_("Open the selected bookmark in a new window"), G_CALLBACK (_action_bookmark_open_window_activate) }, + { "BookmarkEdit", GTK_STOCK_EDIT, + NULL, "", + N_("Edit the selected bookmark"), G_CALLBACK (_action_bookmark_edit_activate) }, + { "BookmarkDelete", GTK_STOCK_DELETE, + NULL, "", + N_("Delete the selected bookmark"), G_CALLBACK (_action_bookmark_delete_activate) }, + + { "Tools", NULL, N_("_Tools") }, + { "ManageSearchEngines", GTK_STOCK_PROPERTIES, + N_("_Manage Search Engines"), "s", + N_("Add, edit and remove search engines..."), + G_CALLBACK (_action_manage_search_engines_activate) }, + + { "Window", NULL, N_("_Window") }, + { "TabPrevious", GTK_STOCK_GO_BACK, + N_("_Previous Tab"), "Page_Up", + N_("Switch to the previous tab"), G_CALLBACK (_action_tab_previous_activate) }, + { "TabNext", GTK_STOCK_GO_FORWARD, + N_("_Next Tab"), "Page_Down", + N_("Switch to the next tab"), G_CALLBACK (_action_tab_next_activate) }, + { "TabOverview", NULL, + N_("Tab _Overview"), "", + N_("Show an overview of all open tabs"), NULL/*G_CALLBACK (_action_tab_overview_activate)*/ }, + + { "Help", NULL, N_("_Help") }, + { "HelpContents", GTK_STOCK_HELP, + N_("_Contents"), "F1", + N_("Show the documentation"), NULL/*G_CALLBACK (_action_help_contents_activate)*/ }, + { "About", GTK_STOCK_ABOUT, + NULL, "", + N_("Show information about the program"), G_CALLBACK (_action_about_activate) }, + }; + static const guint entries_n = G_N_ELEMENTS (entries); + +static const GtkToggleActionEntry toggle_entries[] = { + { "PrivateBrowsing", NULL, + N_("P_rivate Browsing"), "", + N_("Don't save any private data while browsing"), NULL/*G_CALLBACK (_action_private_browsing_activate)*/, + FALSE }, + { "WorkOffline", GTK_STOCK_DISCONNECT, + N_("_Work Offline"), "", + N_("Work without a network connection"), NULL/*G_CALLBACK (_action_work_offline_activate)*/, + FALSE }, + + { "Navigationbar", NULL, + N_("_Navigationbar"), "", + N_("Show navigationbar"), G_CALLBACK (_action_navigationbar_activate), + FALSE }, + { "Panel", NULL, + N_("Side_panel"), "F9", + N_("Show sidepanel"), G_CALLBACK (_action_panel_activate), + FALSE }, + { "Bookmarkbar", NULL, + N_("_Bookmarkbar"), "", + N_("Show bookmarkbar"), G_CALLBACK (_action_bookmarkbar_activate), + FALSE }, + { "Transferbar", NULL, + N_("_Transferbar"), "", + N_("Show transferbar"), NULL/*G_CALLBACK (_action_transferbar_activate)*/, + FALSE }, + { "Statusbar", NULL, + N_("_Statusbar"), "", + N_("Show statusbar"), G_CALLBACK (_action_statusbar_activate), + FALSE }, + }; + static const guint toggle_entries_n = G_N_ELEMENTS (toggle_entries); + +static void +midori_browser_window_state_event_cb (MidoriBrowser* browser, + GdkEventWindowState* event) +{ + MidoriBrowserPrivate* priv = browser->priv; + + if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) + { + if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) + { + gtk_widget_hide (priv->menubar); + g_object_set (priv->button_fullscreen, + "stock-id", GTK_STOCK_LEAVE_FULLSCREEN, NULL); + gtk_widget_show (priv->button_fullscreen); + } + else + { + gtk_widget_show (priv->menubar); + gtk_widget_hide (priv->button_fullscreen); + g_object_set (priv->button_fullscreen, + "stock-id", GTK_STOCK_FULLSCREEN, NULL); + } + } +} + +static void +midori_browser_size_allocate_cb (MidoriBrowser* browser, + GtkAllocation* allocation) +{ + MidoriBrowserPrivate* priv = browser->priv; + GtkWidget* widget = GTK_WIDGET (browser); + + if (GTK_WIDGET_REALIZED (widget)) + { + GdkWindowState state = gdk_window_get_state (widget->window); + if (!(state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN))) + { + g_object_set (priv->settings, + "last-window-width", allocation->width, + "last-window-height", allocation->height, NULL); + } + } +} + +static void +midori_browser_destroy_cb (MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + // Destroy tabs first, so widgets can still see window elements on destroy + gtk_container_foreach (GTK_CONTAINER (priv->notebook), + (GtkCallback) gtk_widget_destroy, NULL); +} + +static const gchar* ui_markup = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + // Closed tabs shall be prepended here + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + // Bookmarks shall be appended here + "" + "" + "" + // Panel items shall be appended here + "" + "" + "" + "" + "" + "" + // All open tabs shall be appended here + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + +static void +midori_browser_realize_cb (GtkStyle* style, MidoriBrowser* browser) +{ + GdkScreen* screen = gtk_widget_get_screen (GTK_WIDGET (browser)); + if (screen) + { + GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen); + if (gtk_icon_theme_has_icon (icon_theme, "midori")) + gtk_window_set_icon_name (GTK_WINDOW (browser), "midori"); + else + gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser"); + } +} + +static void +midori_browser_init (MidoriBrowser* browser) +{ + browser->priv = MIDORI_BROWSER_GET_PRIVATE (browser); + + MidoriBrowserPrivate* priv = browser->priv; + + // Setup the window metrics + g_signal_connect (browser, "realize", + G_CALLBACK (midori_browser_realize_cb), browser); + g_signal_connect (browser, "window-state-event", + G_CALLBACK (midori_browser_window_state_event_cb), NULL); + g_signal_connect (browser, "size-allocate", + G_CALLBACK (midori_browser_size_allocate_cb), NULL); + g_signal_connect (browser, "destroy", + G_CALLBACK (midori_browser_destroy_cb), NULL); + gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser"); + gtk_window_set_title (GTK_WINDOW (browser), g_get_application_name ()); + GtkWidget* vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (browser), vbox); + gtk_widget_show (vbox); + + // Let us see some ui manager magic + priv->action_group = gtk_action_group_new ("Browser"); + gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions (priv->action_group, + entries, entries_n, browser); + gtk_action_group_add_toggle_actions (priv->action_group, + toggle_entries, toggle_entries_n, browser); + GtkUIManager* ui_manager = gtk_ui_manager_new (); + gtk_ui_manager_insert_action_group (ui_manager, priv->action_group, 0); + gtk_window_add_accel_group (GTK_WINDOW (browser), + gtk_ui_manager_get_accel_group (ui_manager)); + + GError* error = NULL; + if (!gtk_ui_manager_add_ui_from_string(ui_manager, ui_markup, -1, &error)) + { + // TODO: Should this be a message dialog? When does this happen? + g_message ("User interface couldn't be created: %s", error->message); + g_error_free (error); + } + + GtkAction* action; + // Make all actions except toplevel menus which lack a callback insensitive + // This will vanish once all actions are implemented + guint i; + for (i = 0; i < entries_n; i++) + { + action = gtk_action_group_get_action(priv->action_group, + entries[i].name); + gtk_action_set_sensitive (action, + entries[i].callback || !entries[i].tooltip); + } + for (i = 0; i < toggle_entries_n; i++) + { + action = gtk_action_group_get_action (priv->action_group, + toggle_entries[i].name); + gtk_action_set_sensitive (action, toggle_entries[i].callback != NULL); + } + + //_action_set_active(browser, "Transferbar", config->toolbarTransfers); + + // Create the menubar + priv->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar"); + GtkWidget* menuitem = gtk_menu_item_new (); + gtk_widget_show (menuitem); + priv->throbber = katze_throbber_new(); + gtk_widget_show(priv->throbber); + gtk_container_add (GTK_CONTAINER (menuitem), priv->throbber); + gtk_widget_set_sensitive (menuitem, FALSE); + gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menubar), menuitem); + gtk_box_pack_start (GTK_BOX (vbox), priv->menubar, FALSE, FALSE, 0); + menuitem = gtk_ui_manager_get_widget (ui_manager, "/menubar/Go/Trash"); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_menu_trash_activate_cb), + browser); + priv->menu_bookmarks = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( + gtk_ui_manager_get_widget (ui_manager, "/menubar/Bookmarks"))); + menuitem = gtk_separator_menu_item_new (); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_bookmarks), menuitem); + priv->popup_bookmark = gtk_ui_manager_get_widget ( + ui_manager, "/popup_bookmark"); + g_object_ref (priv->popup_bookmark); + priv->menu_tools = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( + gtk_ui_manager_get_widget (ui_manager, "/menubar/Tools"))); + menuitem = gtk_separator_menu_item_new(); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_tools), menuitem); + priv->menu_window = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( + gtk_ui_manager_get_widget (ui_manager, "/menubar/Window"))); + menuitem = gtk_separator_menu_item_new(); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_window), menuitem); + gtk_widget_show (priv->menubar); + _action_set_sensitive (browser, "PrivateBrowsing", FALSE); + _action_set_sensitive (browser, "WorkOffline", FALSE); + + // Create the navigationbar + priv->navigationbar = gtk_ui_manager_get_widget ( + ui_manager, "/toolbar_navigation"); + // FIXME: settings should be connected with screen changes + GtkSettings* gtk_settings = gtk_widget_get_settings (GTK_WIDGET (browser)); + if (gtk_settings) + g_signal_connect (gtk_settings, "notify::gtk-toolbar-style", + G_CALLBACK (midori_browser_navigationbar_notify_style_cb), browser); + gtk_toolbar_set_show_arrow (GTK_TOOLBAR (priv->navigationbar), TRUE); + gtk_box_pack_start (GTK_BOX (vbox), priv->navigationbar, FALSE, FALSE, 0); + priv->button_tab_new = gtk_ui_manager_get_widget ( + ui_manager, "/toolbar_navigation/TabNew"); + g_object_set (_action_by_name (browser, "Back"), "is-important", TRUE, NULL); + priv->button_homepage = gtk_ui_manager_get_widget ( + ui_manager, "/toolbar_navigation/Homepage"); + + // Location + priv->location = sexy_icon_entry_new (); + sokoke_entry_setup_completion (GTK_ENTRY (priv->location)); + priv->location_icon = gtk_image_new (); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->location) + , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE (priv->location_icon)); + sexy_icon_entry_add_clear_button (SEXY_ICON_ENTRY (priv->location)); + g_object_connect (priv->location, + "signal::key-press-event", + midori_browser_location_key_press_event_cb, browser, + "signal::focus-out-event", + midori_browser_location_focus_out_event_cb, browser, + "signal::changed", + midori_browser_location_changed_cb, browser, + NULL); + GtkToolItem* toolitem = gtk_tool_item_new (); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); + gtk_container_add (GTK_CONTAINER(toolitem), priv->location); + gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1); + + // Search + priv->search = sexy_icon_entry_new (); + sexy_icon_entry_set_icon_highlight (SEXY_ICON_ENTRY (priv->search), + SEXY_ICON_ENTRY_PRIMARY, TRUE); + // TODO: Make this actively resizable or enlarge to fit contents? + // FIXME: The interface is somewhat awkward and ought to be rethought + // TODO: Display "show in context menu" search engines as "completion actions" + sokoke_entry_setup_completion (GTK_ENTRY (priv->search)); + g_object_connect (priv->search, + "signal::icon-released", + on_webSearch_icon_released, browser, + "signal::key-press-event", + on_webSearch_key_down, browser, + "signal::scroll-event", + on_webSearch_scroll, browser, + "signal::activate", + on_webSearch_activate, browser, + "signal::focus-out-event", + midori_browser_search_focus_out_event_cb, browser, + NULL); + toolitem = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (toolitem), priv->search); + gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1); + action = gtk_action_group_get_action (priv->action_group, "Trash"); + priv->button_trash = gtk_action_create_tool_item (action); + g_signal_connect (priv->button_trash, "clicked", + G_CALLBACK (midori_browser_menu_trash_activate_cb), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), + GTK_TOOL_ITEM (priv->button_trash), -1); + sokoke_container_show_children (GTK_CONTAINER (priv->navigationbar)); + action = gtk_action_group_get_action (priv->action_group, "Fullscreen"); + priv->button_fullscreen = gtk_action_create_tool_item (action); + gtk_widget_hide (priv->button_fullscreen); + g_signal_connect (priv->button_fullscreen, "clicked", + G_CALLBACK (_action_fullscreen_activate), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), + GTK_TOOL_ITEM (priv->button_fullscreen), -1); + + // Bookmarkbar + priv->bookmarkbar = gtk_toolbar_new (); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->bookmarkbar), + GTK_ICON_SIZE_MENU); + gtk_toolbar_set_style (GTK_TOOLBAR (priv->bookmarkbar), + GTK_TOOLBAR_BOTH_HORIZ); + _midori_browser_create_bookmark_menu (browser, bookmarks, + priv->menu_bookmarks); + for (i = 0; i < katze_xbel_folder_get_n_items (bookmarks); i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (bookmarks, i); + const gchar* title = katze_xbel_item_is_separator (item) + ? "" : katze_xbel_item_get_title (item); + const gchar* desc = katze_xbel_item_is_separator (item) + ? "" : katze_xbel_item_get_desc (item); + switch (katze_xbel_item_get_kind (item)) + { + case KATZE_XBEL_ITEM_KIND_FOLDER: + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DIRECTORY); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title); + gtk_tool_item_set_is_important(toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_browser_bookmarkbar_folder_activate_cb), + browser); + sokoke_tool_item_set_tooltip_text(toolitem, desc); + g_object_set_data (G_OBJECT (toolitem), "KatzeXbelItem", item); + break; + case KATZE_XBEL_ITEM_KIND_BOOKMARK: + toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title); + gtk_tool_item_set_is_important(toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_browser_menu_bookmarks_item_activate_cb), + browser); + sokoke_tool_item_set_tooltip_text(toolitem, desc); + g_object_set_data (G_OBJECT (toolitem), "KatzeXbelItem", item); + break; + case KATZE_XBEL_ITEM_KIND_SEPARATOR: + toolitem = gtk_separator_tool_item_new (); + break; + default: + g_warning ("Unknown item kind"); + } + gtk_toolbar_insert (GTK_TOOLBAR (priv->bookmarkbar), toolitem, -1); + } + sokoke_container_show_children (GTK_CONTAINER (priv->bookmarkbar)); + gtk_box_pack_start (GTK_BOX (vbox), priv->bookmarkbar, FALSE, FALSE, 0); + + // Superuser warning + GtkWidget* hbox; + if ((hbox = sokoke_superuser_warning_new ())) + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + // Create the panel + GtkWidget* hpaned = gtk_hpaned_new (); + g_signal_connect (hpaned, "notify::position", + G_CALLBACK (midori_panel_notify_position_cb), + browser); + gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0); + gtk_widget_show (hpaned); + priv->panel = g_object_new (MIDORI_TYPE_PANEL, + "shadow-type", GTK_SHADOW_IN, + "menu", priv->menu_tools, + NULL); + g_signal_connect (priv->panel, "close", + G_CALLBACK (midori_panel_close_cb), browser); + gtk_paned_pack1 (GTK_PANED (hpaned), priv->panel, FALSE, FALSE); + + // Bookmarks + GtkWidget* box = gtk_vbox_new (FALSE, 0); + GtkTreeViewColumn* column; + GtkCellRenderer* renderer_text; + GtkCellRenderer* renderer_pixbuf; + GtkTreeStore* treestore = gtk_tree_store_new (1, KATZE_TYPE_XBEL_ITEM); + GtkWidget* treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore)); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); + column = gtk_tree_view_column_new (); + renderer_pixbuf = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf, + (GtkTreeCellDataFunc)midori_browser_bookmarks_item_render_icon_cb, + treeview, NULL); + renderer_text = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer_text, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer_text, + (GtkTreeCellDataFunc)midori_browser_bookmarks_item_render_text_cb, + treeview, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + _tree_store_insert_folder (GTK_TREE_STORE (treestore), NULL, bookmarks); + g_object_unref (treestore); + g_object_connect (treeview, + "signal::row-activated", + midori_panel_bookmarks_row_activated_cb, browser, + "signal::cursor-changed", + midori_panel_bookmarks_cursor_or_row_changed_cb, browser, + "signal::columns-changed", + midori_panel_bookmarks_cursor_or_row_changed_cb, browser, + "signal::button-release-event", + midori_panel_bookmarks_button_release_event_cb, browser, + "signal::popup-menu", + midori_panel_bookmarks_popup_menu_cb, browser, + NULL); + midori_panel_bookmarks_cursor_or_row_changed_cb (GTK_TREE_VIEW (treeview), + browser); + gtk_box_pack_start (GTK_BOX (box), treeview, TRUE, TRUE, 0); + priv->panel_bookmarks = treeview; + gtk_widget_show_all (box); + GtkWidget* toolbar = gtk_ui_manager_get_widget (ui_manager, + "/toolbar_bookmarks"); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU); + gtk_widget_show_all (toolbar); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + box, toolbar, + "vcard", _("Bookmarks")); + + // Transfers + GtkWidget* panel = midori_web_view_new (); + gtk_widget_show (panel); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + panel, NULL, + "package", _("Transfers")); + + // Console + priv->panel_console = midori_console_new (); + gtk_widget_show (priv->panel_console); + toolbar = midori_console_get_toolbar (MIDORI_CONSOLE (priv->panel_console)); + gtk_widget_show (toolbar); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + priv->panel_console, toolbar, + "terminal", _("Console")); + + // History + panel = midori_web_view_new (); + gtk_widget_show (panel); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + panel, NULL, + "document-open-recent", _("History")); + + // Pageholder + priv->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", "", + NULL); + gtk_widget_show (priv->panel_pageholder); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + priv->panel_pageholder, NULL, + GTK_STOCK_CONVERT, _("Pageholder")); + + // Userscripts + panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_SCRIPTS); + gtk_widget_show (panel); + toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel)); + gtk_widget_show (toolbar); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + panel, toolbar, + "", _("Userscripts")); + // Userstyles + /*panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_STYLES); + gtk_widget_show (panel); + toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel)); + gtk_widget_show (toolbar); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + panel, toolbar, + "", _("Userstyles"));*/ + + // Notebook, containing all web_views + priv->notebook = gtk_notebook_new (); + gtk_notebook_set_scrollable (GTK_NOTEBOOK (priv->notebook), TRUE); + gtk_paned_pack2 (GTK_PANED (hpaned), priv->notebook, FALSE, FALSE); + g_signal_connect_after (priv->notebook, "switch-page", + G_CALLBACK (gtk_notebook_switch_page_cb), + browser); + gtk_widget_show (priv->notebook); + + // Incremental findbar + priv->find = gtk_toolbar_new (); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->find), GTK_ICON_SIZE_MENU); + gtk_toolbar_set_style (GTK_TOOLBAR (priv->find), GTK_TOOLBAR_BOTH_HORIZ); + toolitem = gtk_tool_item_new (); + gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6); + gtk_container_add (GTK_CONTAINER (toolitem), + gtk_label_new_with_mnemonic (_("_Inline find:"))); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + priv->find_text = sexy_icon_entry_new (); + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FIND, + GTK_ICON_SIZE_MENU); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY(priv->find_text), + SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); + sexy_icon_entry_add_clear_button (SEXY_ICON_ENTRY(priv->find_text)); + g_signal_connect (priv->find_text, "activate", + G_CALLBACK (_action_find_next_activate), browser); + toolitem = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (toolitem), priv->find_text); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR(priv->find), toolitem, -1); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK); + gtk_tool_item_set_is_important (toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (_action_find_previous_activate), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD); + gtk_tool_item_set_is_important (toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (_action_find_next_activate), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + priv->find_case = gtk_toggle_tool_button_new_from_stock ( + GTK_STOCK_SPELL_CHECK); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->find_case), _("Match Case")); + gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->find_case), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), priv->find_case, -1); + priv->find_highlight = gtk_toggle_tool_button_new_from_stock ( + GTK_STOCK_SELECT_ALL); + g_signal_connect (priv->find_highlight, "toggled", + G_CALLBACK (_find_highlight_toggled), browser); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->find_highlight), + "Highlight Matches"); + gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->find_highlight), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), priv->find_highlight, -1); + toolitem = gtk_separator_tool_item_new (); + gtk_separator_tool_item_set_draw ( + GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("Close Findbar")); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_browser_find_button_close_clicked_cb), browser); + gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); + sokoke_container_show_children (GTK_CONTAINER (priv->find)); + gtk_box_pack_start (GTK_BOX (vbox), priv->find, FALSE, FALSE, 0); + + // Statusbar + // TODO: fix children overlapping statusbar border + priv->statusbar = gtk_statusbar_new (); + gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0); + priv->progressbar = gtk_progress_bar_new (); + // Setting the progressbar's height to 1 makes it fit in the statusbar + gtk_widget_set_size_request (priv->progressbar, -1, 1); + gtk_box_pack_start (GTK_BOX (priv->statusbar), priv->progressbar, + FALSE, FALSE, 3); + + // Extensions + panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_EXTENSIONS); + gtk_widget_show (panel); + toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel)); + gtk_widget_show (toolbar); + midori_panel_append_page (MIDORI_PANEL (priv->panel), + panel, toolbar, + "", _("Extensions")); + + g_object_unref (ui_manager); +} + +static void +midori_browser_finalize (GObject* object) +{ + MidoriBrowser* browser = MIDORI_BROWSER (object); + MidoriBrowserPrivate* priv = browser->priv; + + g_free (priv->uri); + g_free (priv->title); + g_free (priv->statusbar_text); + + if (priv->proxy_xbel_folder) + katze_xbel_item_unref (priv->proxy_xbel_folder); + + if (priv->settings) + g_object_unref (priv->settings); + if (priv->trash) + g_object_unref (priv->trash); + + G_OBJECT_CLASS (midori_browser_parent_class)->finalize (object); +} + +static void +_midori_browser_set_toolbar_style (MidoriBrowser* browser, + MidoriToolbarStyle toolbar_style) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkToolbarStyle gtk_toolbar_style; + GtkSettings* gtk_settings = gtk_widget_get_settings (GTK_WIDGET (browser)); + if (toolbar_style == MIDORI_TOOLBAR_DEFAULT && gtk_settings) + g_object_get (gtk_settings, "gtk-toolbar-style", >k_toolbar_style, NULL); + else + { + switch (toolbar_style) + { + case MIDORI_TOOLBAR_ICONS: + gtk_toolbar_style = GTK_TOOLBAR_ICONS; + break; + case MIDORI_TOOLBAR_TEXT: + gtk_toolbar_style = GTK_TOOLBAR_TEXT; + break; + case MIDORI_TOOLBAR_BOTH: + gtk_toolbar_style = GTK_TOOLBAR_BOTH; + break; + case MIDORI_TOOLBAR_BOTH_HORIZ: + case MIDORI_TOOLBAR_DEFAULT: + gtk_toolbar_style = GTK_TOOLBAR_BOTH_HORIZ; + } + } + gtk_toolbar_set_style (GTK_TOOLBAR (priv->navigationbar), + gtk_toolbar_style); +} + +static void +_midori_browser_update_settings (MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gboolean remember_last_window_size; + gint last_window_width, last_window_height; + gint last_panel_position, last_panel_page; + gboolean show_navigationbar, show_bookmarkbar, show_panel, show_statusbar; + gboolean small_toolbar, show_new_tab, show_homepage, + show_web_search, show_trash; + MidoriToolbarStyle toolbar_style; + gint last_web_search; + gchar* last_pageholder_uri; + g_object_get (priv->settings, + "remember-last-window-size", &remember_last_window_size, + "last-window-width", &last_window_width, + "last-window-height", &last_window_height, + "last-panel-position", &last_panel_position, + "last-panel-page", &last_panel_page, + "show-navigationbar", &show_navigationbar, + "show-bookmarkbar", &show_bookmarkbar, + "show-panel", &show_panel, + "show-statusbar", &show_statusbar, + "small-toolbar", &small_toolbar, + "show-new-tab", &show_new_tab, + "show-homepage", &show_homepage, + "show-web-search", &show_web_search, + "show-trash", &show_trash, + "toolbar-style", &toolbar_style, + "last-web-search", &last_web_search, + "last-pageholder-uri", &last_pageholder_uri, + NULL); + + GdkScreen* screen = gtk_window_get_screen (GTK_WINDOW (browser)); + const gint default_width = (gint)gdk_screen_get_width (screen) / 1.7; + const gint default_height = (gint)gdk_screen_get_height (screen) / 1.7; + + if (remember_last_window_size) + { + if (last_window_width && last_window_height) + gtk_window_set_default_size (GTK_WINDOW (browser), + last_window_width, last_window_height); + else + gtk_window_set_default_size (GTK_WINDOW (browser), + default_width, default_height); + } + + _midori_browser_set_toolbar_style (browser, toolbar_style); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->navigationbar), + small_toolbar ? GTK_ICON_SIZE_SMALL_TOOLBAR + : GTK_ICON_SIZE_LARGE_TOOLBAR); + + update_searchEngine (last_web_search, priv->search); + + gtk_paned_set_position (GTK_PANED (gtk_widget_get_parent (priv->panel)), + last_panel_position); + midori_panel_set_current_page (MIDORI_PANEL (priv->panel), last_panel_page); + g_object_set (priv->panel_pageholder, "uri", last_pageholder_uri, NULL); + + _action_set_active (browser, "Navigationbar", show_navigationbar); + _action_set_active (browser, "Bookmarkbar", show_bookmarkbar); + _action_set_active (browser, "Panel", show_panel); + _action_set_active (browser, "Statusbar", show_statusbar); + + sokoke_widget_set_visible (priv->button_tab_new, show_new_tab); + sokoke_widget_set_visible (priv->button_homepage, show_homepage); + sokoke_widget_set_visible (priv->search, show_web_search); + sokoke_widget_set_visible (priv->button_trash, show_trash); + + g_free (last_pageholder_uri); +} + +static void +midori_browser_settings_notify (MidoriWebSettings* web_settings, + GParamSpec* pspec, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv = browser->priv; + + const gchar* name = g_intern_string (pspec->name); + GValue value = {0, }; + + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (priv->settings), name, &value); + + if (name == g_intern_string ("toolbar-style")) + _midori_browser_set_toolbar_style (browser, g_value_get_enum (&value)); + else if (name == g_intern_string ("small-toolbar")) + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->navigationbar), + g_value_get_boolean (&value) ? GTK_ICON_SIZE_SMALL_TOOLBAR + : GTK_ICON_SIZE_LARGE_TOOLBAR); + else if (name == g_intern_string ("show-new-tab")) + sokoke_widget_set_visible (priv->button_tab_new, + g_value_get_boolean (&value)); + else if (name == g_intern_string ("show-homepage")) + sokoke_widget_set_visible (priv->button_homepage, + g_value_get_boolean (&value)); + else if (name == g_intern_string ("show-web-search")) + sokoke_widget_set_visible (priv->search, + g_value_get_boolean (&value)); + else if (name == g_intern_string ("show-trash")) + sokoke_widget_set_visible (priv->button_trash, + g_value_get_boolean (&value)); + else if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_settings), + name)) + g_warning (_("Unexpected setting '%s'"), name); + g_value_unset (&value); +} + +static void +midori_browser_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriBrowser* browser = MIDORI_BROWSER (object); + MidoriBrowserPrivate* priv = browser->priv; + + switch (prop_id) + { + case PROP_TAB: + midori_browser_set_current_tab (browser, g_value_get_object (value)); + break; + case PROP_STATUSBAR_TEXT: + _midori_browser_set_statusbar_text (browser, g_value_get_string (value)); + break; + case PROP_SETTINGS: + if (priv->settings) + g_signal_handlers_disconnect_by_func (priv->settings, + midori_browser_settings_notify, + browser); + katze_object_assign (priv->settings, g_value_get_object (value)); + g_object_ref (priv->settings); + _midori_browser_update_settings (browser); + g_signal_connect (priv->settings, "notify", + G_CALLBACK (midori_browser_settings_notify), browser); + // FIXME: Assigning settings must be conditional, if web view or not + // FIXME: Assign settings only if the same settings object was used + gtk_container_foreach (GTK_CONTAINER (priv->notebook), + (GtkCallback) midori_web_view_set_settings, + priv->settings); + break; + case PROP_TRASH: + ; // FIXME: Disconnect handlers + katze_object_assign (priv->trash, g_value_get_object (value)); + g_object_ref (priv->trash); + // FIXME: Connect to updates + _midori_browser_update_actions (browser); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_browser_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriBrowser* browser = MIDORI_BROWSER (object); + MidoriBrowserPrivate* priv = browser->priv; + + switch (prop_id) + { + case PROP_MENUBAR: + g_value_set_object (value, priv->menubar); + break; + case PROP_NAVIGATIONBAR: + g_value_set_object (value, priv->navigationbar); + break; + case PROP_TAB: + g_value_set_object (value, midori_browser_get_current_tab (browser)); + break; + case PROP_STATUSBAR: + g_value_set_object (value, priv->statusbar); + break; + case PROP_STATUSBAR_TEXT: + g_value_set_string (value, priv->statusbar_text); + break; + case PROP_SETTINGS: + g_value_set_object (value, priv->settings); + break; + case PROP_TRASH: + g_value_set_object (value, priv->trash); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_browser_new: + * + * Creates a new browser widget. + * + * A browser is a window with a menubar, toolbars, a notebook, panels + * and a statusbar. You should mostly treat it as an opaque widget. + * + * Return value: a new #MidoriBrowser + **/ +MidoriBrowser* +midori_browser_new (void) +{ + MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER, + NULL); + + return browser; +} + +/** + * midori_browser_add_tab: + * @browser: a #MidoriBrowser + * @widget: a tab + * + * Appends an arbitrary widget in the form of a new tab and creates an + * according item in the Window menu. + * + * Return value: the index of the new tab, or -1 in case of an error + **/ +gint +midori_browser_add_tab (MidoriBrowser* browser, + GtkWidget* widget) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), -1); + + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS); + GtkWidget* child; + GObjectClass* gobject_class = G_OBJECT_GET_CLASS (widget); + if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal) + child = widget; + else + { + child = gtk_viewport_new (NULL, NULL); + gtk_widget_show (child); + gtk_container_add (GTK_CONTAINER (child), widget); + } + gtk_container_add (GTK_CONTAINER (scrolled), child); + gtk_widget_show (scrolled); + + GtkWidget* label = NULL; + GtkWidget* menuitem = NULL; + + if (MIDORI_IS_WEB_VIEW (widget)) + { + label = midori_web_view_get_proxy_tab_label (MIDORI_WEB_VIEW (widget)); + + menuitem = midori_web_view_get_proxy_menu_item (MIDORI_WEB_VIEW (widget)); + + if (priv->proxy_xbel_folder) + { + KatzeXbelItem* xbel_item = midori_web_view_get_proxy_xbel_item ( + MIDORI_WEB_VIEW (widget)); + katze_xbel_item_ref (xbel_item); + katze_xbel_folder_append_item (priv->proxy_xbel_folder, xbel_item); + } + + g_object_connect (widget, + "signal::window-object-cleared", + midori_web_view_window_object_cleared_cb, browser, + "signal::load-started", + midori_web_view_load_started_cb, browser, + "signal::load-committed", + midori_web_view_load_committed_cb, browser, + "signal::progress-started", + midori_web_view_progress_started_cb, browser, + "signal::progress-changed", + midori_web_view_progress_changed_cb, browser, + "signal::progress-done", + midori_web_view_progress_done_cb, browser, + "signal::load-done", + midori_web_view_load_done_cb, browser, + "signal::title-changed", + midori_web_view_title_changed_cb, browser, + "signal::status-bar-text-changed", + midori_web_view_statusbar_text_changed_cb, browser, + "signal::element-motion", + midori_web_view_element_motion_cb, browser, + "signal::console-message", + midori_web_view_console_message_cb, browser, + "signal::close", + midori_web_view_close_cb, browser, + "signal::new-tab", + midori_web_view_new_tab_cb, browser, + "signal::new-window", + midori_web_view_new_window_cb, browser, + "signal::populate-popup", + midori_web_view_populate_popup_cb, browser, + "signal::leave-notify-event", + midori_web_view_leave_notify_event_cb, browser, + "signal::destroy", + midori_web_view_destroy_cb, browser, + NULL); + } + + if (menuitem) + { + gtk_widget_show (menuitem); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_browser_window_menu_item_activate_cb), scrolled); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_window), menuitem); + } + + guint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); + gtk_notebook_insert_page (GTK_NOTEBOOK (priv->notebook), scrolled, + label, n + 1); + #if GTK_CHECK_VERSION(2, 10, 0) + gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (priv->notebook), + scrolled, TRUE); + gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (priv->notebook), + scrolled, TRUE); + #endif + _midori_browser_update_actions (browser); + + n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); + return n; +} + +/** + * midori_browser_remove_tab: + * @browser: a #MidoriBrowser + * @widget: a tab + * + * Removes an existing tab from the browser, including an associated menu item. + **/ +void +midori_browser_remove_tab (MidoriBrowser* browser, + GtkWidget* widget) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); + gtk_container_remove (GTK_CONTAINER (priv->notebook), scrolled); + + // FIXME: Remove the menuitem if this is a web view +} + +/** + * midori_browser_add_xbel_item: + * @browser: a #MidoriBrowser + * @xbel_item: a bookmark + * + * Appends a #KatzeXbelItem in the form of a new tab. + * + * Return value: the index of the new tab, or -1 in case of an error + **/ +gint +midori_browser_add_xbel_item (MidoriBrowser* browser, + KatzeXbelItem* xbel_item) +{ + MidoriBrowserPrivate* priv = browser->priv; + + g_return_val_if_fail (katze_xbel_item_is_bookmark (xbel_item), -1); + + const gchar* uri = katze_xbel_bookmark_get_href (xbel_item); + const gchar* title = katze_xbel_item_get_title (xbel_item); + GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", uri, + "title", title, + "settings", priv->settings, + NULL); + gtk_widget_show (web_view); + + return midori_browser_add_tab (browser, web_view); +} + +/** + * midori_browser_add_uri: + * @browser: a #MidoriBrowser + * @uri: an URI + * + * Appends an uri in the form of a new tab. + * + * Return value: the index of the new tab, or -1 + **/ +gint +midori_browser_add_uri (MidoriBrowser* browser, + const gchar* uri) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, + "uri", uri, + "settings", priv->settings, + NULL); + gtk_widget_show (web_view); + + return midori_browser_add_tab (browser, web_view); +} + +/** + * midori_browser_activate_action: + * @browser: a #MidoriBrowser + * @name: name of the action + * + * Activates the specified action. + **/ +void +midori_browser_activate_action (MidoriBrowser* browser, + const gchar* name) +{ + GtkAction* action = _action_by_name (browser, name); + if (action) + gtk_action_activate (action); + else + g_warning (_("Unexpected action '%s'."), name); +} + +/** + * midori_browser_set_current_page: + * @browser: a #MidoriBrowser + * @n: the index of a page + * + * Switches to the page with the index @n. + * + * The widget will also grab the focus automatically. + **/ +void +midori_browser_set_current_page (MidoriBrowser* browser, + gint n) +{ + MidoriBrowserPrivate* priv = browser->priv; + + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); + GtkWidget* scrolled = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n); + GtkWidget* widget = _midori_browser_child_for_scrolled (browser, scrolled); + if (widget && MIDORI_IS_WEB_VIEW (widget) + && !strcmp (midori_web_view_get_display_uri ( + MIDORI_WEB_VIEW (widget)), "")) + gtk_widget_grab_focus (priv->location); + else + gtk_widget_grab_focus (widget); +} + +/** + * midori_browser_get_current_page: + * @browser: a #MidoriBrowser + * + * Determines the currently selected page. + * + * If there is no page present at all, %NULL is returned. + * + * Return value: the selected page, or -1 + **/ +gint +midori_browser_get_current_page (MidoriBrowser* browser) +{ + g_return_val_if_fail (MIDORI_IS_BROWSER (browser), -1); + + MidoriBrowserPrivate* priv = browser->priv; + + return gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); +} + +/** + * midori_browser_set_current_tab: + * @browser: a #MidoriBrowser + * @widget: a #GtkWidget + * + * Switches to the page containing @widget. + * + * The widget will also grab the focus automatically. + **/ +void +midori_browser_set_current_tab (MidoriBrowser* browser, + GtkWidget* widget) +{ + MidoriBrowserPrivate* priv = browser->priv; + + GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); + gint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); + if (widget && MIDORI_IS_WEB_VIEW (widget) + && !strcmp (midori_web_view_get_display_uri ( + MIDORI_WEB_VIEW (widget)), "")) + gtk_widget_grab_focus (priv->location); + else + gtk_widget_grab_focus (widget); +} + +/** + * midori_browser_get_current_tab: + * @browser: a #MidoriBrowser + * + * Retrieves the currently selected tab. + * + * If there is no tab present at all, %NULL is returned. + * + * Return value: the selected tab, or %NULL + **/ +GtkWidget* +midori_browser_get_current_tab (MidoriBrowser* browser) +{ + g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); + + MidoriBrowserPrivate* priv = browser->priv; + + gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); + if (n >= 0) + { + GtkWidget* widget = _midori_browser_child_for_scrolled (browser, + gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n)); + return widget; + } + else + return NULL; +} + +/** + * midori_browser_get_current_web_view: + * @browser: a #MidoriBrowser + * + * Determines the currently selected web view. + * + * If there is no web view selected or if there is no tab present + * at all, %NULL is returned. + * + * See also midori_browser_get_current_page + * + * Return value: the selected web view, or %NULL + **/ +GtkWidget* +midori_browser_get_current_web_view (MidoriBrowser* browser) +{ + g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); + + GtkWidget* web_view = midori_browser_get_current_tab (browser); + return MIDORI_IS_WEB_VIEW (web_view) ? web_view : NULL; +} + +/** + * midori_browser_get_proxy_xbel_folder: + * @browser: a #MidoriBrowser + * + * Retrieves a proxy xbel folder representing the respective proxy xbel items + * of the present web views that can be used for session management. + * + * The folder is created on the first call and will be updated to reflect + * changes to all items automatically. + * + * Note that this implicitly creates proxy xbel items of all web views. + * + * Return value: the proxy #KatzeXbelItem + **/ +KatzeXbelItem* +midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser) +{ + g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); + + MidoriBrowserPrivate* priv = browser->priv; + + if (!priv->proxy_xbel_folder) + { + priv->proxy_xbel_folder = katze_xbel_folder_new (); + // FIXME: Fill in xbel items of all present web views + } + return priv->proxy_xbel_folder; +} + +/** + * midori_browser_quit: + * @browser: a #MidoriBrowser + * + * Quits the browser, including any other browser windows. + **/ +void +midori_browser_quit (MidoriBrowser* browser) +{ + g_return_if_fail (MIDORI_IS_BROWSER (browser)); + + g_signal_emit (browser, signals[QUIT], 0); +} diff --git a/midori/midori-browser.h b/midori/midori-browser.h new file mode 100644 index 00000000..d029e6a1 --- /dev/null +++ b/midori/midori-browser.h @@ -0,0 +1,129 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_BROWSER_H__ +#define __MIDORI_BROWSER_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_BROWSER \ + (midori_browser_get_type ()) +#define MIDORI_BROWSER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_BROWSER, MidoriBrowser)) +#define MIDORI_BROWSER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_BROWSER, MidoriBrowserClass)) +#define MIDORI_IS_BROWSER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_BROWSER)) +#define MIDORI_IS_BROWSER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_BROWSER)) +#define MIDORI_BROWSER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_BROWSER, MidoriBrowserClass)) + +typedef struct _MidoriBrowser MidoriBrowser; +typedef struct _MidoriBrowserPrivate MidoriBrowserPrivate; +typedef struct _MidoriBrowserClass MidoriBrowserClass; + +struct _MidoriBrowser +{ + GtkWindow parent_instance; + + MidoriBrowserPrivate* priv; +}; + +struct _MidoriBrowserClass +{ + GtkWindowClass parent_class; + + /* Signals */ + void + (*window_object_cleared) (MidoriBrowser* browser, + WebKitWebFrame* web_frame, + JSContextRef* context, + JSObjectRef* window_object); + void + (*statusbar_text_changed) (MidoriBrowser* browser, + const gchar* text); + void + (*element_motion) (MidoriBrowser* browser, + const gchar* link_uri); + void + (*new_window) (MidoriBrowser* browser, + const gchar* uri); + + void + (*add_tab) (MidoriBrowser* browser, + GtkWidget* widget); + void + (*add_uri) (MidoriBrowser* browser, + const gchar* uri); + void + (*activate_action) (MidoriBrowser* browser, + const gchar* name); + void + (*quit) (MidoriBrowser* browser); +}; + +GType +midori_browser_get_type (void); + +MidoriBrowser* +midori_browser_new (void); + +gint +midori_browser_add_tab (MidoriBrowser* browser, + GtkWidget* widget); + +void +midori_browser_remove_tab (MidoriBrowser* browser, + GtkWidget* widget); + +gint +midori_browser_add_xbel_item (MidoriBrowser* browser, + KatzeXbelItem* xbel_item); + +gint +midori_browser_add_uri (MidoriBrowser* browser, + const gchar* uri); + +void +midori_browser_activate_action (MidoriBrowser* browser, + const gchar* name); + +void +midori_browser_set_current_page (MidoriBrowser* browser, + gint n); + +gint +midori_browser_get_current_page (MidoriBrowser* browser); + +void +midori_browser_set_current_tab (MidoriBrowser* browser, + GtkWidget* widget); + +GtkWidget* +midori_browser_get_current_tab (MidoriBrowser* browser); + +GtkWidget* +midori_browser_get_current_web_view (MidoriBrowser* browser); + +KatzeXbelItem* +midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser); + +void +midori_browser_quit (MidoriBrowser* browser); + +G_END_DECLS + +#endif /* __MIDORI_BROWSER_H__ */ diff --git a/midori/midori-console.c b/midori/midori-console.c new file mode 100644 index 00000000..693608da --- /dev/null +++ b/midori/midori-console.c @@ -0,0 +1,215 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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 "midori-console.h" + +#include "sokoke.h" +#include + +G_DEFINE_TYPE (MidoriConsole, midori_console, GTK_TYPE_VBOX) + +struct _MidoriConsolePrivate +{ + GtkWidget* toolbar; + GtkWidget* treeview; +}; + +#define MIDORI_CONSOLE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_CONSOLE, MidoriConsolePrivate)) + +static void +midori_console_class_init (MidoriConsoleClass* class) +{ + g_type_class_add_private (class, sizeof (MidoriConsolePrivate)); +} + +static void +midori_console_button_clear_clicked_cb (GtkToolItem* toolitem, + MidoriConsole* console) +{ + MidoriConsolePrivate* priv = console->priv; + + GtkTreeModel* model = gtk_tree_view_get_model ( + GTK_TREE_VIEW (priv->treeview)); + gtk_tree_store_clear (GTK_TREE_STORE (model)); +} + +static void +midori_console_treeview_render_icon_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + // gchar* source_id; + // gtk_tree_model_get (model, iter, 2, &source_id, -1); + + g_object_set (renderer, "stock-id", GTK_STOCK_DIALOG_WARNING, NULL); + + // g_free (source_id); +} + +static void +midori_console_treeview_render_text_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + gchar* message; + gint line; + gchar* source_id; + gtk_tree_model_get (model, iter, 0, &message, 1, &line, 2, &source_id, -1); + + gchar* text = g_strdup_printf ("%d @ %s\n%s", line, source_id, message); + g_object_set (renderer, "text", text, NULL); + g_free (text); + + g_free (message); + g_free (source_id); +} + +static void +midori_console_treeview_row_activated_cb (GtkTreeView* treeview, + GtkTreePath* path, + GtkTreeViewColumn* column, + MidoriConsole* console) +{ + /*GtkTreeModel* model = gtk_tree_view_get_model (treeview); + GtkTreeIter iter; + if (gtk_tree_model_get_iter (model, &iter, path)) + { + gchar* source_id; + gtk_tree_model_get (model, &iter, 2, &source_id, -1); + g_free (source_id); + }*/ +} + +static void +midori_console_init (MidoriConsole* console) +{ + console->priv = MIDORI_CONSOLE_GET_PRIVATE (console); + + MidoriConsolePrivate* priv = console->priv; + + // Create the treeview + GtkTreeViewColumn* column; + GtkCellRenderer* renderer_text; + GtkCellRenderer* renderer_pixbuf; + GtkTreeStore* treestore = gtk_tree_store_new (3, G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_STRING); + priv->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore)); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE); + column = gtk_tree_view_column_new (); + renderer_pixbuf = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf, + (GtkTreeCellDataFunc)midori_console_treeview_render_icon_cb, + priv->treeview, NULL); + renderer_text = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer_text, FALSE); + gtk_tree_view_column_set_cell_data_func (column, renderer_text, + (GtkTreeCellDataFunc)midori_console_treeview_render_text_cb, + priv->treeview, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column); + g_object_unref (treestore); + g_signal_connect (priv->treeview, "row-activated", + G_CALLBACK (midori_console_treeview_row_activated_cb), + console); + gtk_widget_show (priv->treeview); + gtk_box_pack_start (GTK_BOX (console), priv->treeview, TRUE, TRUE, 0); +} + +/** + * midori_console_new: + * + * Creates a new empty console. + * + * Return value: a new #MidoriConsole + **/ +GtkWidget* +midori_console_new (void) +{ + MidoriConsole* console = g_object_new (MIDORI_TYPE_CONSOLE, + NULL); + + return GTK_WIDGET (console); +} + +/** + * midori_console_get_toolbar: + * + * Retrieves the toolbar of the console. A new widget is created on + * the first call of this function. + * + * Return value: a new #MidoriConsole + **/ +GtkWidget* +midori_console_get_toolbar (MidoriConsole* console) +{ + g_return_val_if_fail (MIDORI_IS_CONSOLE (console), NULL); + + MidoriConsolePrivate* priv = console->priv; + + if (!priv->toolbar) + { + GtkWidget* toolbar = gtk_toolbar_new (); + gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); + GtkToolItem* toolitem = gtk_tool_item_new (); + // TODO: What about a find entry here that filters e.g. by url? + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); + gtk_widget_show (GTK_WIDGET (toolitem)); + toolitem = gtk_separator_tool_item_new (); + gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), + FALSE); + gtk_tool_item_set_expand (toolitem, TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); + gtk_widget_show (GTK_WIDGET (toolitem)); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLEAR); + gtk_tool_item_set_is_important (toolitem, TRUE); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_console_button_clear_clicked_cb), console); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); + gtk_widget_show (GTK_WIDGET (toolitem)); + priv->toolbar = toolbar; + } + + return priv->toolbar; +} + +/** + * midori_console_add: + * @console: a #MidoriConsole + * @message: a descriptive message + * @line: the line in the source file + * @source_id: the source + * + * Adds a new message to the console. + **/ +void +midori_console_add (MidoriConsole* console, + const gchar* message, + gint line, + const gchar* source_id) +{ + g_return_if_fail (MIDORI_IS_CONSOLE (console)); + + MidoriConsolePrivate* priv = console->priv; + + GtkTreeView* treeview = GTK_TREE_VIEW (priv->treeview); + GtkTreeModel* treemodel = gtk_tree_view_get_model (treeview); + gtk_tree_store_insert_with_values (GTK_TREE_STORE (treemodel), + NULL, NULL, G_MAXINT, + 0, message, 1, line, 2, source_id, -1); +} diff --git a/midori/midori-console.h b/midori/midori-console.h new file mode 100644 index 00000000..884c2b2b --- /dev/null +++ b/midori/midori-console.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_CONSOLE_H__ +#define __MIDORI_CONSOLE_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_CONSOLE \ + (midori_console_get_type ()) +#define MIDORI_CONSOLE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_CONSOLE, MidoriConsole)) +#define MIDORI_CONSOLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_CONSOLE, MidoriConsoleClass)) +#define MIDORI_IS_CONSOLE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_CONSOLE)) +#define MIDORI_IS_CONSOLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_CONSOLE)) +#define MIDORI_CONSOLE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_CONSOLE, MidoriConsoleClass)) + +typedef struct _MidoriConsole MidoriConsole; +typedef struct _MidoriConsolePrivate MidoriConsolePrivate; +typedef struct _MidoriConsoleClass MidoriConsoleClass; + +struct _MidoriConsole +{ + GtkVBox parent_instance; + + MidoriConsolePrivate* priv; +}; + +struct _MidoriConsoleClass +{ + GtkVBoxClass parent_class; +}; + +GType +midori_console_get_type (void); + +GtkWidget* +midori_console_new (void); + +GtkWidget* +midori_console_get_toolbar (MidoriConsole* console); + +void +midori_console_add (MidoriConsole* console, + const gchar* message, + gint line, + const gchar* source_id); + +G_END_DECLS + +#endif /* __MIDORI_CONSOLE_H__ */ diff --git a/midori/midori-panel.c b/midori/midori-panel.c new file mode 100644 index 00000000..9c321d1e --- /dev/null +++ b/midori/midori-panel.c @@ -0,0 +1,561 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + 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 "midori-panel.h" + +#include "sokoke.h" +#include + +G_DEFINE_TYPE (MidoriPanel, midori_panel, GTK_TYPE_HBOX) + +struct _MidoriPanelPrivate +{ + GtkWidget* toolbar; + GtkWidget* toolbar_label; + GtkWidget* frame; + GtkWidget* toolbook; + GtkWidget* notebook; + GSList* group; + GtkMenu* menu; +}; + +#define MIDORI_PANEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_PANEL, MidoriPanelPrivate)) + +enum +{ + PROP_0, + + PROP_SHADOW_TYPE, + PROP_MENU, + PROP_PAGE +}; + +enum { + CLOSE, + SWITCH_PAGE, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_panel_finalize (GObject* object); + +static void +midori_panel_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_panel_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static gboolean +midori_panel_close_cb (MidoriPanel* panel) +{ + gtk_widget_hide (GTK_WIDGET (panel)); + return FALSE; +} + +static void +midori_cclosure_marshal_BOOLEAN__VOID (GClosure* closure, + GValue* return_value, + guint n_param_values, + const GValue* param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean(*GMarshalFunc_BOOLEAN__VOID) (gpointer data1, + gpointer data2); + register GMarshalFunc_BOOLEAN__VOID callback; + register GCClosure* cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 1); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data + ? marshal_data : cc->callback); + v_return = callback (data1, data2); + g_value_set_boolean (return_value, v_return); +} + +static void +midori_panel_class_init (MidoriPanelClass* class) +{ + + signals[CLOSE] = g_signal_new ( + "close", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriPanelClass, close), + g_signal_accumulator_true_handled, + NULL, + midori_cclosure_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + signals[SWITCH_PAGE] = g_signal_new ( + "switch-page", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriPanelClass, switch_page), + 0, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + class->close = midori_panel_close_cb; + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_panel_finalize; + gobject_class->set_property = midori_panel_set_property; + gobject_class->get_property = midori_panel_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_SHADOW_TYPE, + g_param_spec_enum ( + "shadow-type", + "Shadow Type", + _("Appearance of the shadow around each panel"), + GTK_TYPE_SHADOW_TYPE, + GTK_SHADOW_NONE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_MENU, + g_param_spec_object ( + "menu", + "Menu", + _("Menu to hold panel items"), + GTK_TYPE_MENU, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_PAGE, + g_param_spec_int ( + "page", + "Page", + _("The index of the current page"), + -1, G_MAXINT, -1, + flags)); + + g_type_class_add_private (class, sizeof (MidoriPanelPrivate)); +} + +static void +midori_panel_button_close_clicked_cb (GtkWidget* toolitem, + MidoriPanel* panel) +{ + gboolean return_value; + g_signal_emit (panel, signals[CLOSE], 0, &return_value); +} + +static void +midori_panel_init (MidoriPanel* panel) +{ + panel->priv = MIDORI_PANEL_GET_PRIVATE (panel); + + MidoriPanelPrivate* priv = panel->priv; + + // Create the sidebar + priv->toolbar = gtk_toolbar_new (); + gtk_toolbar_set_style (GTK_TOOLBAR (priv->toolbar), GTK_TOOLBAR_BOTH); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->toolbar), + GTK_ICON_SIZE_BUTTON); + gtk_toolbar_set_orientation (GTK_TOOLBAR (priv->toolbar), + GTK_ORIENTATION_VERTICAL); + gtk_box_pack_start (GTK_BOX (panel), priv->toolbar, FALSE, FALSE, 0); + gtk_widget_show_all (priv->toolbar); + GtkWidget* vbox = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0); + + // Create the titlebar + GtkWidget* labelbar = gtk_toolbar_new (); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (labelbar), GTK_ICON_SIZE_MENU); + gtk_toolbar_set_style (GTK_TOOLBAR (labelbar), GTK_TOOLBAR_ICONS); + GtkToolItem* toolitem = gtk_tool_item_new (); + gtk_tool_item_set_expand (toolitem, TRUE); + priv->toolbar_label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (priv->toolbar_label), 0, 0.5); + gtk_container_add (GTK_CONTAINER (toolitem), priv->toolbar_label); + gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6); + gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1); + toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("Close panel")); + sokoke_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem), _("Close panel")); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_panel_button_close_clicked_cb), panel); + gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1); + gtk_box_pack_start (GTK_BOX (vbox), labelbar, FALSE, FALSE, 0); + gtk_widget_show_all (vbox); + + // Create the toolbook + priv->toolbook = gtk_notebook_new (); + gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->toolbook), FALSE); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->toolbook), FALSE); + gtk_box_pack_start (GTK_BOX (vbox), priv->toolbook, FALSE, FALSE, 0); + gtk_widget_show (priv->toolbook); + + // Create the notebook + priv->notebook = gtk_notebook_new (); + gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE); + priv->frame = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (priv->frame), priv->notebook); + gtk_box_pack_start (GTK_BOX (vbox), priv->frame, TRUE, TRUE, 0); + gtk_widget_show_all (priv->frame); +} + +static void +midori_panel_finalize (GObject* object) +{ + MidoriPanel* panel = MIDORI_PANEL (object); + MidoriPanelPrivate* priv = panel->priv; + + if (priv->menu) + { + // FIXME: Remove all menu items + } + + G_OBJECT_CLASS (midori_panel_parent_class)->finalize (object); +} + +static void +midori_panel_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriPanel* panel = MIDORI_PANEL (object); + MidoriPanelPrivate* priv = panel->priv; + + switch (prop_id) + { + case PROP_SHADOW_TYPE: + gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), + g_value_get_enum (value)); + break; + case PROP_MENU: + katze_object_assign (priv->menu, g_value_get_object (value)); + // FIXME: Move existing items to the new menu + break; + case PROP_PAGE: + midori_panel_set_current_page (panel, g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_panel_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriPanel* panel = MIDORI_PANEL (object); + MidoriPanelPrivate* priv = panel->priv; + + switch (prop_id) + { + case PROP_SHADOW_TYPE: + g_value_set_enum (value, + gtk_frame_get_shadow_type (GTK_FRAME (priv->frame))); + break; + case PROP_MENU: + g_value_set_object (value, priv->menu); + break; + case PROP_PAGE: + g_value_set_int (value, midori_panel_get_current_page (panel)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_panel_new: + * + * Creates a new empty panel. + * + * Return value: a new #MidoriPanel + **/ +GtkWidget* +midori_panel_new (void) +{ + MidoriPanel* panel = g_object_new (MIDORI_TYPE_PANEL, + NULL); + + return GTK_WIDGET (panel); +} + +static void +midori_panel_menu_item_activate_cb (GtkWidget* widget, + MidoriPanel* panel) +{ + GtkWidget* child = g_object_get_data (G_OBJECT (widget), "page"); + guint n = midori_panel_page_num (panel, child); + midori_panel_set_current_page (panel, n); + g_signal_emit (panel, signals[SWITCH_PAGE], 0, n); +} + +/** + * midori_panel_append_page: + * @panel: a #MidoriPanel + * @child: the child widget + * @toolbar: a toolbar widget, or %NULL + * @icon: a stock ID or icon name, or %NULL + * @label: a string to use as the label, or %NULL + * + * Appends a new page to the panel. If @toolbar is specified it will + * be packaged above @child. + * + * If @icon is an icon name, the according image is used as an + * icon for this page. + * + * If @label is given, it is used as the label of this page. + * + * In the case of an error, -1 is returned. + * + * Return value: the index of the new page, or -1 + **/ +gint +midori_panel_append_page (MidoriPanel* panel, + GtkWidget* child, + GtkWidget* toolbar, + const gchar* icon, + const gchar* label) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); + g_return_val_if_fail (GTK_IS_WIDGET (child), -1); + g_return_val_if_fail (!toolbar || GTK_IS_WIDGET (toolbar), -1); + + MidoriPanelPrivate* priv = panel->priv; + + GtkWidget* scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS); + gtk_widget_show (scrolled); + GtkWidget* widget; + GObjectClass* gobject_class = G_OBJECT_GET_CLASS (child); + if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal) + widget = child; + else + { + widget = gtk_viewport_new (NULL, NULL); + gtk_widget_show (widget); + gtk_container_add (GTK_CONTAINER (widget), child); + } + gtk_container_add (GTK_CONTAINER (scrolled), widget); + gtk_container_add (GTK_CONTAINER (priv->notebook), scrolled); + + if (!toolbar) + toolbar = gtk_event_box_new (); + gtk_widget_show (toolbar); + gtk_container_add (GTK_CONTAINER (priv->toolbook), toolbar); + + guint n = midori_panel_page_num (panel, child); + + const gchar* text = label ? label : _("Untitled"); + g_object_set_data (G_OBJECT (child), "label", (gchar*)text); + + GtkWidget* image; + GtkToolItem* toolitem = gtk_radio_tool_button_new (priv->group); + priv->group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON ( + toolitem)); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), text); + if (icon) + { + image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_BUTTON); + gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image); + } + g_object_set_data (G_OBJECT (toolitem), "page", child); + g_signal_connect (toolitem, "clicked", + G_CALLBACK (midori_panel_menu_item_activate_cb), panel); + gtk_widget_show_all (GTK_WIDGET (toolitem)); + gtk_toolbar_insert (GTK_TOOLBAR (priv->toolbar), toolitem, -1); + + if (priv->menu) + { + GtkWidget* menuitem = gtk_image_menu_item_new_with_label (text); + if (icon) + { + image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), + image); + } + gtk_widget_show_all (menuitem); + g_object_set_data (G_OBJECT (menuitem), "page", child); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_panel_menu_item_activate_cb), + panel); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menuitem); + } + + return n; +} + +/** + * midori_panel_get_current_page: + * @panel: a #MidoriPanel + * + * Retrieves the index of the currently selected page. + * + * If @panel has no children, -1 is returned. + * + * Return value: the index of the current page, or -1 + **/ +gint +midori_panel_get_current_page (MidoriPanel* panel) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); + + MidoriPanelPrivate* priv = panel->priv; + + return gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); +} + +static GtkWidget* +_midori_panel_child_for_scrolled (MidoriPanel* panel, + GtkWidget* scrolled) +{ + GtkWidget* child = gtk_bin_get_child (GTK_BIN (scrolled)); + if (GTK_IS_VIEWPORT (child)) + child = gtk_bin_get_child (GTK_BIN (child)); + return child; +} + +/** + * midori_panel_get_nth_page: + * @panel: a #MidoriPanel + * + * Retrieves the child widget of the nth page. + * + * If @panel has no children, %NULL is returned. + * + * Return value: the child widget of the new page, or %NULL + **/ +GtkWidget* +midori_panel_get_nth_page (MidoriPanel* panel, + guint page_num) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), NULL); + + MidoriPanelPrivate* priv = panel->priv; + + GtkWidget* scrolled = gtk_notebook_get_nth_page ( + GTK_NOTEBOOK (priv->notebook), page_num); + if (scrolled) + return _midori_panel_child_for_scrolled (panel, scrolled); + return NULL; +} + +/** + * midori_panel_get_n_pages: + * @panel: a #MidoriPanel + * + * Retrieves the number of pages contained in the panel. + * + * Return value: the number of pages + **/ +guint +midori_panel_get_n_pages (MidoriPanel* panel) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), 0); + + MidoriPanelPrivate* priv = panel->priv; + + return gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)); +} + +static GtkWidget* +_midori_panel_scrolled_for_child (MidoriPanel* panel, + GtkWidget* child) +{ + GtkWidget* scrolled = gtk_widget_get_parent (GTK_WIDGET (child)); + if (GTK_IS_VIEWPORT (scrolled)) + scrolled = gtk_widget_get_parent (scrolled); + return scrolled; +} + +/** + * midori_panel_page_num: + * @panel: a #MidoriPanel + * + * Retrieves the index of the page associated to @widget. + * + * If @panel has no children, -1 is returned. + * + * Return value: the index of page associated to @widget, or -1 + **/ +gint +midori_panel_page_num (MidoriPanel* panel, + GtkWidget* child) +{ + g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); + + MidoriPanelPrivate* priv = panel->priv; + + GtkWidget* scrolled = _midori_panel_scrolled_for_child (panel, child); + return gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); +} + +/** + * midori_panel_set_current_page: + * @panel: a #MidoriPanel + * @n: index of the page to switch to, or -1 to mean the last page + * + * Switches to the page with the given index. + * + * The child must be visible, otherwise the underlying GtkNotebook will + * silently ignore the attempt to switch the page. + **/ +void +midori_panel_set_current_page (MidoriPanel* panel, + gint n) +{ + g_return_if_fail (MIDORI_IS_PANEL (panel)); + + MidoriPanelPrivate* priv = panel->priv; + + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->toolbook), n); + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); + GtkWidget* child = midori_panel_get_nth_page (panel, n); + if (child) + { + const gchar* label = g_object_get_data (G_OBJECT (child), "label"); + g_object_set (priv->toolbar_label, "label", label, NULL); + } +} diff --git a/midori/midori-panel.h b/midori/midori-panel.h new file mode 100644 index 00000000..eb3908bc --- /dev/null +++ b/midori/midori-panel.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_PANEL_H__ +#define __MIDORI_PANEL_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_PANEL \ + (midori_panel_get_type ()) +#define MIDORI_PANEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PANEL, MidoriPanel)) +#define MIDORI_PANEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_PANEL, MidoriPanelClass)) +#define MIDORI_IS_PANEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PANEL)) +#define MIDORI_IS_PANEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PANEL)) +#define MIDORI_PANEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PANEL, MidoriPanelClass)) + +typedef struct _MidoriPanel MidoriPanel; +typedef struct _MidoriPanelPrivate MidoriPanelPrivate; +typedef struct _MidoriPanelClass MidoriPanelClass; + +struct _MidoriPanel +{ + GtkHBox parent_instance; + + MidoriPanelPrivate* priv; +}; + +struct _MidoriPanelClass +{ + GtkHBoxClass parent_class; + + /* Signals */ + gboolean + (*close) (MidoriPanel* panel); + + void + (*switch_page) (MidoriPanel* panel, + gint page); +}; + +GType +midori_panel_get_type (void); + +GtkWidget* +midori_panel_new (void); + +gint +midori_panel_append_page (MidoriPanel* panel, + GtkWidget* child, + GtkWidget* toolbar, + const gchar* icon, + const gchar* label); + +gint +midori_panel_get_current_page (MidoriPanel* panel); + +GtkWidget* +midori_panel_get_nth_page (MidoriPanel* panel, + guint page_num); + +guint +midori_panel_get_n_pages (MidoriPanel* panel); + +gint +midori_panel_page_num (MidoriPanel* panel, + GtkWidget* child); + +void +midori_panel_set_current_page (MidoriPanel* panel, + gint n); + +G_END_DECLS + +#endif /* __MIDORI_PANEL_H__ */ diff --git a/midori/midori-preferences.c b/midori/midori-preferences.c new file mode 100644 index 00000000..b3ddc9e7 --- /dev/null +++ b/midori/midori-preferences.c @@ -0,0 +1,395 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + 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 "midori-preferences.h" + +#include "sokoke.h" + +#include + +G_DEFINE_TYPE (MidoriPreferences, midori_preferences, GTK_TYPE_DIALOG) + +struct _MidoriPreferencesPrivate +{ + GtkWidget* notebook; +}; + +#define MIDORI_PREFERENCES_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_PREFERENCES, MidoriPreferencesPrivate)) + +enum +{ + PROP_0, + + PROP_SETTINGS +}; + +static void +midori_preferences_finalize (GObject* object); + +static void +midori_preferences_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_preferences_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static void +midori_preferences_class_init (MidoriPreferencesClass* class) +{ + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_preferences_finalize; + gobject_class->set_property = midori_preferences_set_property; + gobject_class->get_property = midori_preferences_get_property; + + g_object_class_install_property (gobject_class, + PROP_SETTINGS, + g_param_spec_object ( + "settings", + "Settings", + _("Settings instance to provide properties"), + MIDORI_TYPE_WEB_SETTINGS, + G_PARAM_WRITABLE)); + + g_type_class_add_private (class, sizeof (MidoriPreferencesPrivate)); +} + +static void +clear_button_clicked_cb (GtkWidget* button, GtkWidget* file_chooser) +{ + gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (file_chooser), ""); + // Emit "file-set" manually for Gtk doesn't emit it otherwise + g_signal_emit_by_name (file_chooser, "file-set"); +} + +static void +midori_preferences_init (MidoriPreferences* preferences) +{ + preferences->priv = MIDORI_PREFERENCES_GET_PRIVATE (preferences); + MidoriPreferencesPrivate* priv = preferences->priv; + + priv->notebook = NULL; + + gchar* dialog_title = g_strdup_printf (_("%s Preferences"), + g_get_application_name ()); + g_object_set (preferences, + "icon-name", GTK_STOCK_PREFERENCES, + "title", dialog_title, + "has-separator", FALSE, + NULL); + gtk_dialog_add_buttons (GTK_DIALOG (preferences), + GTK_STOCK_HELP, GTK_RESPONSE_HELP, + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, + NULL); + // TODO: Implement some kind of help function + gtk_dialog_set_response_sensitive (GTK_DIALOG (preferences), + GTK_RESPONSE_HELP, FALSE); //... + g_signal_connect (preferences, "response", + G_CALLBACK (gtk_widget_destroy), preferences); + + // TODO: Do we want tooltips for explainations or can we omit that? + g_free (dialog_title); +} + +static void +midori_preferences_finalize (GObject* object) +{ + G_OBJECT_CLASS (midori_preferences_parent_class)->finalize (object); +} + +static void +midori_preferences_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriPreferences* preferences = MIDORI_PREFERENCES (object); + + switch (prop_id) + { + case PROP_SETTINGS: + { + GtkWidget* xfce_heading; + GtkWindow* parent; + g_object_get (object, "transient-for", &parent, NULL); + if ((xfce_heading = sokoke_xfce_header_new ( + gtk_window_get_icon_name (parent), + gtk_window_get_title (GTK_WINDOW (object))))) + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox), + xfce_heading, FALSE, FALSE, 0); + midori_preferences_set_settings (preferences, + g_value_get_object (value)); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_preferences_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_preferences_new: + * @parent: the parent window + * @settings: the settings + * + * Creates a new preferences dialog. + * + * Return value: a new #MidoriPreferences + **/ +GtkWidget* +midori_preferences_new (GtkWindow* parent, + MidoriWebSettings* settings) +{ + g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL); + g_return_val_if_fail (MIDORI_IS_WEB_SETTINGS (settings), NULL); + + MidoriPreferences* preferences = g_object_new (MIDORI_TYPE_PREFERENCES, + "transient-for", parent, + "settings", settings, + NULL); + + return GTK_WIDGET (preferences); +} + +/** + * midori_preferences_set_settings: + * @settings: the settings + * + * Assigns a settings instance to a preferences dialog. + * + * Note: This must not be called more than once. + **/ +void +midori_preferences_set_settings (MidoriPreferences* preferences, + MidoriWebSettings* settings) +{ + g_return_if_fail (MIDORI_IS_PREFERENCES (preferences)); + g_return_if_fail (MIDORI_IS_WEB_SETTINGS (settings)); + + MidoriPreferencesPrivate* priv = preferences->priv; + + g_return_if_fail (!priv->notebook); + + priv->notebook = gtk_notebook_new (); + gtk_container_set_border_width (GTK_CONTAINER (priv->notebook), 6); + GtkSizeGroup* sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + GtkWidget* page; GtkWidget* frame; GtkWidget* table; GtkWidget* align; + GtkWidget* label; GtkWidget* button; + GtkWidget* entry; GtkWidget* hbox; + #define PAGE_NEW(__label) page = gtk_vbox_new (FALSE, 0); \ + gtk_container_set_border_width (GTK_CONTAINER (page), 5); \ + gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), page, \ + gtk_label_new (__label)) + #define FRAME_NEW(__label) frame = sokoke_hig_frame_new (__label); \ + gtk_container_set_border_width (GTK_CONTAINER (frame), 5); \ + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + #define TABLE_NEW(__rows, __cols) table = gtk_table_new ( \ + __rows, __cols, FALSE); \ + gtk_container_set_border_width (GTK_CONTAINER (table), 5); \ + gtk_container_add (GTK_CONTAINER (frame), table); + #define WIDGET_ADD(__widget, __left, __right, __top, __bottom) \ + gtk_table_attach (GTK_TABLE (table), __widget \ + , __left, __right, __top, __bottom \ + , GTK_FILL, GTK_FILL, 8, 2) + #define FILLED_ADD(__widget, __left, __right, __top, __bottom) \ + gtk_table_attach (GTK_TABLE (table), __widget \ + , __left, __right, __top, __bottom\ + , GTK_EXPAND | GTK_FILL, GTK_FILL, 8, 2) + #define INDENTED_ADD(__widget, __left, __right, __top, __bottom) \ + align = gtk_alignment_new (0, 0.5, 0, 0); \ + gtk_container_add (GTK_CONTAINER (align), __widget); \ + gtk_size_group_add_widget (sizegroup, align); \ + WIDGET_ADD (align, __left, __right, __top, __bottom) + #define SPANNED_ADD(__widget, __left, __right, __top, __bottom) \ + align = gtk_alignment_new (0, 0.5, 0, 0); \ + gtk_container_add (GTK_CONTAINER (align), __widget); \ + FILLED_ADD (align, __left, __right, __top, __bottom) + // Page "General" + PAGE_NEW (_("General")); + FRAME_NEW (_("Startup")); + TABLE_NEW (2, 2); + label = katze_property_label (settings, "load-on-startup"); + INDENTED_ADD (label, 0, 1, 0, 1); + button = katze_property_proxy (settings, "load-on-startup", NULL); + FILLED_ADD (button, 1, 2, 0, 1); + label = katze_property_label (settings, "homepage"); + INDENTED_ADD (label, 0, 1, 1, 2); + entry = katze_property_proxy (settings, "homepage", NULL); + FILLED_ADD (entry, 1, 2, 1, 2); + // TODO: We need something like "use current website" + FRAME_NEW (_("Transfers")); + TABLE_NEW (1, 2); + label = katze_property_label (settings, "download-folder"); + INDENTED_ADD (label, 0, 1, 0, 1); + button = katze_property_proxy (settings, "download-folder", "folder"); + FILLED_ADD (button, 1, 2, 0, 1); + button = katze_property_proxy (settings, "show-download-notification", "blurb"); + SPANNED_ADD (button, 0, 2, 1, 2); + + // Page "Appearance" + PAGE_NEW (_("Appearance")); + FRAME_NEW (_("Font settings")); + TABLE_NEW (5, 2); + label = katze_property_label (settings, "default-font-family"); + INDENTED_ADD (label, 0, 1, 0, 1); + hbox = gtk_hbox_new (FALSE, 4); + button = katze_property_proxy (settings, "default-font-family", "font"); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); + entry = katze_property_proxy (settings, "default-font-size", NULL); + gtk_box_pack_end (GTK_BOX (hbox), entry, FALSE, FALSE, 4); + FILLED_ADD (hbox, 1, 2, 0, 1); + label = katze_property_label (settings, "minimum-font-size"); + INDENTED_ADD (label, 0, 1, 1, 2); + hbox = gtk_hbox_new (FALSE, 4); + entry = katze_property_proxy (settings, "minimum-font-size", NULL); + INDENTED_ADD (entry, 1, 2, 1, 2); + label = katze_property_label (settings, "preferred-encoding"); + INDENTED_ADD (label, 0, 1, 2, 3); + button = katze_property_proxy (settings, "preferred-encoding", NULL); + FILLED_ADD (button, 1, 2, 2, 3); + + // Page "Behavior" + PAGE_NEW (_("Behavior")); + FRAME_NEW (_("Features")); + TABLE_NEW (5, 2); + button = katze_property_proxy (settings, "auto-load-images", NULL); + INDENTED_ADD (button, 0, 1, 0, 1); + button = katze_property_proxy (settings, "auto-shrink-images", NULL); + SPANNED_ADD (button, 1, 2, 0, 1); + button = katze_property_proxy (settings, "print-backgrounds", NULL); + INDENTED_ADD (button, 0, 1, 1, 2); + button = katze_property_proxy (settings, "resizable-text-areas", NULL); + SPANNED_ADD (button, 1, 2, 1, 2); + button = katze_property_proxy (settings, "enable-scripts", NULL); + INDENTED_ADD (button, 0, 1, 2, 3); + button = katze_property_proxy (settings, "enable-plugins", NULL); + SPANNED_ADD(button, 1, 2, 2, 3); + label = katze_property_label (settings, "user-stylesheet-uri"); + INDENTED_ADD (label, 0, 1, 3, 4); + hbox = gtk_hbox_new (FALSE, 4); + entry = katze_property_proxy (settings, "user-stylesheet-uri", "uri"); + gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); + button = gtk_button_new (); + gtk_container_add (GTK_CONTAINER (button), + gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU)); + g_signal_connect (button, "clicked", + G_CALLBACK (clear_button_clicked_cb), entry); + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 4); + FILLED_ADD (hbox, 1, 2, 3, 4); + label = katze_property_label (settings, "location-entry-search"); + INDENTED_ADD (label, 0, 1, 4, 5); + entry = katze_property_proxy (settings, "location-entry-search", NULL); + FILLED_ADD (entry, 1, 2, 4, 5); + + // Page "Interface" + PAGE_NEW (_("Interface")); + FRAME_NEW (_("Navigationbar")); + TABLE_NEW (3, 2); + INDENTED_ADD (katze_property_label (settings, "toolbar-style"), 0, 1, 0, 1); + button = katze_property_proxy (settings, "toolbar-style", NULL); + FILLED_ADD(button, 1, 2, 0, 1); + button = katze_property_proxy (settings, "show-new-tab", NULL); + INDENTED_ADD (button, 0, 1, 1, 2); + button = katze_property_proxy (settings, "show-web-search", NULL); + SPANNED_ADD (button, 1, 2, 1, 2); + button = katze_property_proxy (settings, "show-homepage", NULL); + INDENTED_ADD (button, 0, 1, 2, 3); + button = katze_property_proxy (settings, "show-trash", NULL); + SPANNED_ADD (button, 1, 2, 2, 3); + FRAME_NEW(_("Browsing")); + TABLE_NEW (3, 2); + label = katze_property_label (settings, "open-new-pages-in"); + INDENTED_ADD (label, 0, 1, 0, 1); + button = katze_property_proxy (settings, "open-new-pages-in", NULL); + FILLED_ADD (button, 1, 2, 0, 1); + button = katze_property_proxy (settings, "middle-click-opens-selection", NULL); + INDENTED_ADD (button, 0, 1, 1, 2); + button = katze_property_proxy (settings, "open-tabs-in-the-background", NULL); + SPANNED_ADD (button, 1, 2, 1, 2); + button = katze_property_proxy (settings, "open-popups-in-tabs", NULL); + SPANNED_ADD (button, 0, 1, 2, 3); + button = katze_property_proxy (settings, "close-buttons-on-tabs", NULL); + SPANNED_ADD (button, 1, 2, 2, 3); + + // Page "Network" + PAGE_NEW (_("Network")); + FRAME_NEW (_("Network")); + TABLE_NEW (2, 2); + label = katze_property_label (settings, "http-proxy"); + INDENTED_ADD (label, 0, 1, 0, 1); + button = katze_property_proxy (settings, "http-proxy", NULL); + FILLED_ADD (button, 1, 2, 0, 1); + label = katze_property_label (settings, "cache-size"); + INDENTED_ADD (label, 0, 1, 1, 2); + hbox = gtk_hbox_new (FALSE, 4); + entry = katze_property_proxy (settings, "cache-size", NULL); + gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("MB")), + FALSE, FALSE, 0); + FILLED_ADD (hbox, 1, 2, 1, 2); + + // Page "Privacy" + PAGE_NEW (_("Privacy")); + FRAME_NEW (_("Web Cookies")); + TABLE_NEW (3, 2); + label = katze_property_label (settings, "accept-cookies"); + INDENTED_ADD (label, 0, 1, 0, 1); + button = katze_property_proxy (settings, "accept-cookies", NULL); + FILLED_ADD (button, 1, 2, 0, 1); + button = katze_property_proxy (settings, "original-cookies-only", "blurb"); + SPANNED_ADD (button, 0, 2, 1, 2); + label = katze_property_label (settings, "maximum-cookie-age"); + INDENTED_ADD (label, 0, 1, 2, 3); + hbox = gtk_hbox_new (FALSE, 4); + entry = katze_property_proxy (settings, "maximum-cookie-age", NULL); + gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("days")), + FALSE, FALSE, 0); + FILLED_ADD (hbox, 1, 2, 2, 3); + FRAME_NEW (_("History")); + TABLE_NEW (3, 2); + button = katze_property_proxy (settings, "remember-last-visited-pages", NULL); + SPANNED_ADD (button, 0, 1, 0, 1); + hbox = gtk_hbox_new (FALSE, 4); + button = katze_property_proxy (settings, "maximum-history-age", NULL); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("days")), + FALSE, FALSE, 0); + SPANNED_ADD (hbox, 1, 2, 0, 1); + button = katze_property_proxy (settings, "remember-last-form-inputs", NULL); + SPANNED_ADD (button, 0, 2, 1, 2); + button = katze_property_proxy (settings, "remember-last-downloaded-files", NULL); + SPANNED_ADD (button, 0, 2, 2, 3); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox), + priv->notebook, FALSE, FALSE, 4); + gtk_widget_show_all (GTK_DIALOG (preferences)->vbox); +} diff --git a/midori/midori-preferences.h b/midori/midori-preferences.h new file mode 100644 index 00000000..e47d843c --- /dev/null +++ b/midori/midori-preferences.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_PREFERENCES_H__ +#define __MIDORI_PREFERENCES_H__ + +#include "midori-websettings.h" + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_PREFERENCES \ + (midori_preferences_get_type ()) +#define MIDORI_PREFERENCES(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PREFERENCES, MidoriPreferences)) +#define MIDORI_PREFERENCES_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_PREFERENCES, MidoriPreferencesClass)) +#define MIDORI_IS_PREFERENCES(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PREFERENCES)) +#define MIDORI_IS_PREFERENCES_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PREFERENCES)) +#define MIDORI_PREFERENCES_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PREFERENCES, MidoriPreferencesClass)) + +typedef struct _MidoriPreferences MidoriPreferences; +typedef struct _MidoriPreferencesPrivate MidoriPreferencesPrivate; +typedef struct _MidoriPreferencesClass MidoriPreferencesClass; + +struct _MidoriPreferences +{ + GtkDialog parent_instance; + + MidoriPreferencesPrivate* priv; +}; + +struct _MidoriPreferencesClass +{ + GtkDialogClass parent_class; +}; + +GType +midori_preferences_get_type (void); + +GtkWidget* +midori_preferences_new (GtkWindow* parent, + MidoriWebSettings* settings); + +void +midori_preferences_set_settings (MidoriPreferences* preferences, + MidoriWebSettings* settings); + +G_END_DECLS + +#endif /* __MIDORI_PREFERENCES_H__ */ diff --git a/midori/midori-trash.c b/midori/midori-trash.c new file mode 100644 index 00000000..10dce2c8 --- /dev/null +++ b/midori/midori-trash.c @@ -0,0 +1,328 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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 "midori-trash.h" + +#include "sokoke.h" +#include + +G_DEFINE_TYPE (MidoriTrash, midori_trash, G_TYPE_OBJECT) + +struct _MidoriTrashPrivate +{ + guint limit; + KatzeXbelItem* xbel_folder; +}; + +#define MIDORI_TRASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_TRASH, MidoriTrashPrivate)) + +enum +{ + PROP_0, + + PROP_LIMIT +}; + +enum { + INSERTED, + REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_trash_finalize (GObject* object); + +static void +midori_trash_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_trash_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static void +midori_trash_class_init (MidoriTrashClass* class) +{ + signals[INSERTED] = g_signal_new ( + "inserted", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriTrashClass, inserted), + 0, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[REMOVED] = g_signal_new ( + "removed", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriTrashClass, removed), + 0, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_trash_finalize; + gobject_class->set_property = midori_trash_set_property; + gobject_class->get_property = midori_trash_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_LIMIT, + g_param_spec_uint ( + "limit", + "Limit", + _("The maximum number of items"), + 0, G_MAXUINT, 10, + flags)); + + g_type_class_add_private (class, sizeof (MidoriTrashPrivate)); +} + + + +static void +midori_trash_init (MidoriTrash* trash) +{ + trash->priv = MIDORI_TRASH_GET_PRIVATE (trash); + + MidoriTrashPrivate* priv = trash->priv; + + priv->xbel_folder = katze_xbel_folder_new (); +} + +static void +midori_trash_finalize (GObject* object) +{ + MidoriTrash* trash = MIDORI_TRASH (object); + MidoriTrashPrivate* priv = trash->priv; + + katze_xbel_item_unref (priv->xbel_folder); + + G_OBJECT_CLASS (midori_trash_parent_class)->finalize (object); +} + +static void +midori_trash_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriTrash* trash = MIDORI_TRASH (object); + MidoriTrashPrivate* priv = trash->priv; + + switch (prop_id) + { + case PROP_LIMIT: + priv->limit = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_trash_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriTrash* trash = MIDORI_TRASH (object); + MidoriTrashPrivate* priv = trash->priv; + + switch (prop_id) + { + case PROP_LIMIT: + g_value_set_uint (value, priv->limit); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_trash_new: + * @limit: the maximum number of items + * + * Creates a new #MidoriTrash that can contain a specified number of items, + * meaning that each additional item will replace the oldest existing item. + * + * The value 0 for @limit actually means that there is no limit. + * + * You will typically want to assign this to a #MidoriBrowser. + * + * Return value: a new #MidoriTrash + **/ +MidoriTrash* +midori_trash_new (guint limit) +{ + MidoriTrash* trash = g_object_new (MIDORI_TYPE_TRASH, + "limit", limit, + NULL); + + return trash; +} + +/** + * midori_trash_is_empty: + * @trash: a #MidoriTrash + * + * Determines whether the @trash contains no items. + * + * Return value: %TRUE if there are no items, %FALSE otherwise + **/ +gboolean +midori_trash_is_empty (MidoriTrash* trash) +{ + g_return_val_if_fail (MIDORI_IS_TRASH (trash), FALSE); + + MidoriTrashPrivate* priv = trash->priv; + + return katze_xbel_folder_is_empty (priv->xbel_folder); +} + +/** + * midori_trash_get_n_items: + * @trash: a #MidoriTrash + * + * Determines the number of items in @trash. + * + * Return value: the current number of items + **/ +guint +midori_trash_get_n_items (MidoriTrash* trash) +{ + g_return_val_if_fail (MIDORI_IS_TRASH (trash), 0); + + MidoriTrashPrivate* priv = trash->priv; + + return katze_xbel_folder_get_n_items (priv->xbel_folder); +} + +/** + * midori_trash_get_nth_xbel_item: + * @trash: a #MidoriTrash + * @n: the index of an item + * + * Retrieve an item contained in @trash by its index. + * + * Note that you mustn't unref this item. + * + * Return value: the index at the given index or %NULL + **/ +KatzeXbelItem* +midori_trash_get_nth_xbel_item (MidoriTrash* trash, + guint n) +{ + g_return_val_if_fail (MIDORI_IS_TRASH (trash), 0); + + MidoriTrashPrivate* priv = trash->priv; + + return katze_xbel_folder_get_nth_item (priv->xbel_folder, n); +} + +/** + * midori_trash_prepend_xbel_item: + * @trash: a #MidoriTrash + * @xbel_item: a #KatzeXbelItem + * + * Prepends a #KatzeXbelItem to @trash. + * + * The item is copied. If there is a limit set, the oldest item is + * removed automatically. + * + * Return value: %TRUE if there are no items, %FALSE otherwise + **/ +void +midori_trash_prepend_xbel_item (MidoriTrash* trash, + KatzeXbelItem* xbel_item) +{ + g_return_if_fail (MIDORI_IS_TRASH (trash)); + + MidoriTrashPrivate* priv = trash->priv; + + KatzeXbelItem* copy = katze_xbel_item_copy (xbel_item); + katze_xbel_folder_prepend_item (priv->xbel_folder, copy); + g_signal_emit (trash, signals[INSERTED], 0, 0); + guint n = katze_xbel_folder_get_n_items (priv->xbel_folder); + if (n > 10) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, + n - 1); + g_signal_emit (trash, signals[REMOVED], 0, n - 1); + katze_xbel_item_unref (item); + } +} + +/** + * midori_trash_remove_nth_item: + * @trash: a #MidoriTrash + * @n: the index of an item + * + * Removes the item at the specified position from @trash. + * + * Nothing happens if the function fails. + **/ +void +midori_trash_remove_nth_item (MidoriTrash* trash, + guint n) +{ + g_return_if_fail (MIDORI_IS_TRASH (trash)); + + MidoriTrashPrivate* priv = trash->priv; + + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, n); + if (!n) + return; + katze_xbel_folder_remove_item (priv->xbel_folder, item); + g_signal_emit (trash, signals[REMOVED], 0, n); + katze_xbel_item_unref (item); +} + +/** + * midori_trash_empty: + * @trash: a #MidoriTrash + * + * Deletes all items currently contained in @trash. + **/ +void +midori_trash_empty (MidoriTrash* trash) +{ + g_return_if_fail (MIDORI_IS_TRASH (trash)); + + MidoriTrashPrivate* priv = trash->priv; + + guint n = katze_xbel_folder_get_n_items (priv->xbel_folder); + guint i; + for (i = 0; i < n; i++) + { + KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, + i); + g_signal_emit (trash, signals[REMOVED], 0, i); + katze_xbel_item_unref (item); + } +} diff --git a/midori/midori-trash.h b/midori/midori-trash.h new file mode 100644 index 00000000..bc711792 --- /dev/null +++ b/midori/midori-trash.h @@ -0,0 +1,85 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_TRASH_H__ +#define __MIDORI_TRASH_H__ + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_TRASH \ + (midori_trash_get_type ()) +#define MIDORI_TRASH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_TRASH, MidoriTrash)) +#define MIDORI_TRASH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_TRASH, MidoriTrashClass)) +#define MIDORI_IS_TRASH(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_TRASH)) +#define MIDORI_IS_TRASH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_TRASH)) +#define MIDORI_TRASH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_TRASH, MidoriTrashClass)) + +typedef struct _MidoriTrash MidoriTrash; +typedef struct _MidoriTrashPrivate MidoriTrashPrivate; +typedef struct _MidoriTrashClass MidoriTrashClass; + +struct _MidoriTrash +{ + GObject parent_instance; + + MidoriTrashPrivate* priv; +}; + +struct _MidoriTrashClass +{ + GObjectClass parent_class; + + /* Signals */ + void + (*inserted) (MidoriTrash* trash, + guint n); + void + (*removed) (MidoriTrash* trash, + guint n); +}; + +GType +midori_trash_get_type (void); + +MidoriTrash* +midori_trash_new (guint limit); + +gboolean +midori_trash_is_empty (MidoriTrash* trash); + +guint +midori_trash_get_n_items (MidoriTrash* trash); + +KatzeXbelItem* +midori_trash_get_nth_xbel_item (MidoriTrash* trash, + guint n); + +void +midori_trash_prepend_xbel_item (MidoriTrash* trash, + KatzeXbelItem* xbel_item); + +void +midori_trash_remove_nth_item (MidoriTrash* trash, + guint n); + +void +midori_trash_empty (MidoriTrash* trash); + +G_END_DECLS + +#endif /* __MIDORI_TRASH_H__ */ diff --git a/midori/midori-websettings.c b/midori/midori-websettings.c new file mode 100644 index 00000000..20bbcc01 --- /dev/null +++ b/midori/midori-websettings.c @@ -0,0 +1,1021 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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 "midori-websettings.h" + +#include "sokoke.h" + +#include +#include + +G_DEFINE_TYPE (MidoriWebSettings, midori_web_settings, WEBKIT_TYPE_WEB_SETTINGS) + +struct _MidoriWebSettingsPrivate +{ + gboolean remember_last_window_size; + gint last_window_width; + gint last_window_height; + gint last_panel_position; + gint last_panel_page; + gint last_web_search; + gchar* last_pageholder_uri; + + gboolean show_navigationbar; + gboolean show_bookmarkbar; + gboolean show_panel; + gboolean show_statusbar; + + MidoriToolbarStyle toolbar_style; + gboolean small_toolbar; + gboolean show_new_tab; + gboolean show_homepage; + gboolean show_web_search; + gboolean show_trash; + + MidoriStartup load_on_startup; + gchar* homepage; + gchar* download_folder; + gboolean show_download_notification; + gchar* location_entry_search; + MidoriPreferredEncoding preferred_encoding; + + gint tab_label_size; + gboolean close_buttons_on_tabs; + MidoriNewPage open_new_pages_in; + gboolean middle_click_opens_selection; + gboolean open_tabs_in_the_background; + gboolean open_popups_in_tabs; + + MidoriAcceptCookies accept_cookies; + gboolean original_cookies_only; + gint maximum_cookie_age; + + gboolean remember_last_visited_pages; + gint maximum_history_age; + gboolean remember_last_form_inputs; + gboolean remember_last_downloaded_files; + + gchar* http_proxy; + gint cache_size; +}; + +#define MIDORI_WEB_SETTINGS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsPrivate)) + +enum +{ + PROP_0, + + PROP_REMEMBER_LAST_WINDOW_SIZE, + PROP_LAST_WINDOW_WIDTH, + PROP_LAST_WINDOW_HEIGHT, + PROP_LAST_PANEL_POSITION, + PROP_LAST_PANEL_PAGE, + PROP_LAST_WEB_SEARCH, + PROP_LAST_PAGEHOLDER_URI, + + PROP_SHOW_NAVIGATIONBAR, + PROP_SHOW_BOOKMARKBAR, + PROP_SHOW_PANEL, + PROP_SHOW_STATUSBAR, + + PROP_TOOLBAR_STYLE, + PROP_SMALL_TOOLBAR, + PROP_SHOW_NEW_TAB, + PROP_SHOW_HOMEPAGE, + PROP_SHOW_WEB_SEARCH, + PROP_SHOW_TRASH, + + PROP_LOAD_ON_STARTUP, + PROP_HOMEPAGE, + PROP_DOWNLOAD_FOLDER, + PROP_SHOW_DOWNLOAD_NOTIFICATION, + PROP_LOCATION_ENTRY_SEARCH, + PROP_PREFERRED_ENCODING, + + PROP_TAB_LABEL_SIZE, + PROP_CLOSE_BUTTONS_ON_TABS, + PROP_OPEN_NEW_PAGES_IN, + PROP_MIDDLE_CLICK_OPENS_SELECTION, + PROP_OPEN_TABS_IN_THE_BACKGROUND, + PROP_OPEN_POPUPS_IN_TABS, + + PROP_ACCEPT_COOKIES, + PROP_ORIGINAL_COOKIES_ONLY, + PROP_MAXIMUM_COOKIE_AGE, + + PROP_REMEMBER_LAST_VISITED_PAGES, + PROP_MAXIMUM_HISTORY_AGE, + PROP_REMEMBER_LAST_FORM_INPUTS, + PROP_REMEMBER_LAST_DOWNLOADED_FILES, + + PROP_HTTP_PROXY, + PROP_CACHE_SIZE +}; + +GType +midori_startup_get_type (void) +{ + static GType type = 0; + if (!type) + { + static const GEnumValue values[] = { + { MIDORI_STARTUP_BLANK_PAGE, "MIDORI_STARTUP_BLANK_PAGE", N_("Blank page") }, + { MIDORI_STARTUP_HOMEPAGE, "MIDORI_STARTUP_HOMEPAGE", N_("Homepage") }, + { MIDORI_STARTUP_LAST_OPEN_PAGES, "MIDORI_STARTUP_LAST_OPEN_PAGES", N_("Last open pages") }, + { 0, NULL, NULL } + }; + type = g_enum_register_static ("MidoriStartup", values); + } + return type; +} + +GType +midori_preferred_encoding_get_type (void) +{ + static GType type = 0; + if (!type) + { + static const GEnumValue values[] = { + { MIDORI_ENCODING_CHINESE, "MIDORI_ENCODING_CHINESE", N_("Chinese (BIG5)") }, + { MIDORI_ENCODING_JAPANESE, "MIDORI_ENCODING_JAPANESE", N_("Japanese (SHIFT_JIS)") }, + { MIDORI_ENCODING_RUSSIAN, "MIDORI_ENCODING_RUSSIAN", N_("Russian (KOI8-R)") }, + { MIDORI_ENCODING_UNICODE, "MIDORI_ENCODING_UNICODE", N_("Unicode (UTF-8)") }, + { MIDORI_ENCODING_WESTERN, "MIDORI_ENCODING_WESTERN", N_("Western (ISO-8859-1)") }, + { MIDORI_ENCODING_WESTERN, "MIDORI_ENCODING_CUSTOM", N_("Custom...") }, + { 0, NULL, NULL } + }; + type = g_enum_register_static ("MidoriPreferredEncoding", values); + } + return type; +} + +GType +midori_new_page_get_type (void) +{ + static GType type = 0; + if (!type) + { + static const GEnumValue values[] = { + { MIDORI_NEW_PAGE_TAB, "MIDORI_NEW_PAGE_TAB", N_("New tab") }, + { MIDORI_NEW_PAGE_WINDOW, "MIDORI_NEW_PAGE_WINDOW", N_("New window") }, + { MIDORI_NEW_PAGE_CURRENT, "MIDORI_NEW_PAGE_CURRENT", N_("Current tab") }, + { 0, NULL, NULL } + }; + type = g_enum_register_static ("MidoriNewPage", values); + } + return type; +} + +GType +midori_toolbar_style_get_type (void) +{ + static GType type = 0; + if (!type) + { + static const GEnumValue values[] = { + { MIDORI_TOOLBAR_DEFAULT, "MIDORI_TOOLBAR_DEFAULT", N_("Default") }, + { MIDORI_TOOLBAR_ICONS, "MIDORI_TOOLBAR_ICONS", N_("Icons") }, + { MIDORI_TOOLBAR_TEXT, "MIDORI_TOOLBAR_TEXT", N_("Text") }, + { MIDORI_TOOLBAR_BOTH, "MIDORI_TOOLBAR_BOTH", N_("Both") }, + { MIDORI_TOOLBAR_BOTH_HORIZ, "MIDORI_TOOLBAR_BOTH_HORIZ", N_("Both horizontal") }, + { 0, NULL, NULL } + }; + type = g_enum_register_static ("MidoriToolbarStyle", values); + } + return type; +} + +GType +midori_accept_cookies_get_type (void) +{ + static GType type = 0; + if (!type) + { + static const GEnumValue values[] = { + { MIDORI_ACCEPT_COOKIES_ALL, "MIDORI_ACCEPT_COOKIES_ALL", N_("All cookies") }, + { MIDORI_ACCEPT_COOKIES_SESSION, "MIDORI_ACCEPT_COOKIES_SESSION", N_("Session cookies") }, + { MIDORI_ACCEPT_COOKIES_NONE, "MIDORI_ACCEPT_COOKIES_NONE", N_("None") }, + { 0, NULL, NULL } + }; + type = g_enum_register_static ("MidoriAcceptCookies", values); + } + return type; +} + +static void +midori_web_settings_finalize (GObject* object); + +static void +midori_web_settings_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_web_settings_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static void +midori_web_settings_notify (GObject* object, + GParamSpec* pspec); + +static void +midori_web_settings_class_init (MidoriWebSettingsClass* class) +{ + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_web_settings_finalize; + gobject_class->set_property = midori_web_settings_set_property; + gobject_class->get_property = midori_web_settings_get_property; + gobject_class->notify = midori_web_settings_notify; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_REMEMBER_LAST_WINDOW_SIZE, + g_param_spec_boolean ( + "remember-last-window-size", + _("Remember last window size"), + _("Whether to save the last window size"), + TRUE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_LAST_WINDOW_WIDTH, + g_param_spec_int ( + "last-window-width", + _("Last window width"), + _("The last saved window width"), + 0, G_MAXINT, 0, + flags)); + + g_object_class_install_property (gobject_class, + PROP_LAST_WINDOW_HEIGHT, + g_param_spec_int ( + "last-window-height", + _("Last window height"), + _("The last saved window height"), + 0, G_MAXINT, 0, + flags)); + + g_object_class_install_property (gobject_class, + PROP_LAST_PANEL_POSITION, + g_param_spec_int ( + "last-panel-position", + _("Last panel position"), + _("The last saved panel position"), + 0, G_MAXINT, 0, + flags)); + + g_object_class_install_property (gobject_class, + PROP_LAST_PANEL_PAGE, + g_param_spec_int ( + "last-panel-page", + _("Last panel page"), + _("The last saved panel page"), + 0, G_MAXINT, 0, + flags)); + + g_object_class_install_property (gobject_class, + PROP_LAST_WEB_SEARCH, + g_param_spec_int ( + "last-web-search", + _("Last Web search"), + _("The last saved Web search"), + 0, G_MAXINT, 0, + flags)); + + g_object_class_install_property (gobject_class, + PROP_LAST_PAGEHOLDER_URI, + g_param_spec_string ( + "last-pageholder-uri", + _("Last pageholder URI"), + _("The URI last opened in the pageholder"), + "", + flags)); + + + + g_object_class_install_property (gobject_class, + PROP_SHOW_NAVIGATIONBAR, + g_param_spec_boolean ( + "show-navigationbar", + _("Show Navigationbar"), + _("Whether to show the navigationbar"), + TRUE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_BOOKMARKBAR, + g_param_spec_boolean ( + "show-bookmarkbar", + _("Show Bookmarkbar"), + _("Whether to show the bookmarkbar"), + FALSE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_PANEL, + g_param_spec_boolean ( + "show-panel", + _("Show Panel"), + _("Whether to show the panel"), + FALSE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_STATUSBAR, + g_param_spec_boolean ( + "show-statusbar", + _("Show Statusbar"), + _("Whether to show the statusbar"), + TRUE, + flags)); + + + g_object_class_install_property (gobject_class, + PROP_TOOLBAR_STYLE, + g_param_spec_enum ( + "toolbar-style", + _("Toolbar Style"), + _("The style of the toolbar"), + MIDORI_TYPE_TOOLBAR_STYLE, + MIDORI_TOOLBAR_DEFAULT, + flags)); + + g_object_class_install_property (gobject_class, + PROP_SMALL_TOOLBAR, + g_param_spec_boolean ( + "small-toolbar", + _("Small toolbar"), + _("Use small toolbar icons"), + FALSE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_NEW_TAB, + g_param_spec_boolean ( + "show-new-tab", + _("Show New Tab"), + _("Show the New Tab button in the toolbar"), + TRUE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_HOMEPAGE, + g_param_spec_boolean ( + "show-homepage", + _("Show Homepage"), + _("Show the Homepage button in the toolbar"), + TRUE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_WEB_SEARCH, + g_param_spec_boolean ( + "show-web-search", + _("Show Web search"), + _("Show the Web search entry in the toolbar"), + TRUE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_TRASH, + g_param_spec_boolean ( + "show-trash", + _("Show Trash"), + _("Show the Trash button in the toolbar"), + TRUE, + flags)); + + + + g_object_class_install_property (gobject_class, + PROP_LOAD_ON_STARTUP, + g_param_spec_enum ( + "load-on-startup", + _("Load on Startup"), + _("What to load on startup"), + MIDORI_TYPE_STARTUP, + MIDORI_STARTUP_HOMEPAGE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_HOMEPAGE, + g_param_spec_string ( + "homepage", + _("Homepage"), + _("The homepage"), + "http://www.google.com", + flags)); + + g_object_class_install_property (gobject_class, + PROP_DOWNLOAD_FOLDER, + g_param_spec_string ( + "download-folder", + _("Download Folder"), + _("The folder downloaded files are saved to"), + g_get_home_dir (), + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_DOWNLOAD_NOTIFICATION, + g_param_spec_boolean ( + "show-download-notification", + _("Show Download Notification"), + _("Show a notification window for finished downloads"), + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_LOCATION_ENTRY_SEARCH, + g_param_spec_string ( + "location-entry-search", + _("Location entry Search"), + _("The search to perform inside the location entry"), + "http://www.google.com/search?q=%s", + flags)); + + g_object_class_install_property (gobject_class, + PROP_PREFERRED_ENCODING, + g_param_spec_enum ( + "preferred-encoding", + _("Preferred Encoding"), + _("The preferred character encoding"), + MIDORI_TYPE_PREFERRED_ENCODING, + MIDORI_ENCODING_WESTERN, + flags)); + + + + g_object_class_install_property (gobject_class, + PROP_TAB_LABEL_SIZE, + g_param_spec_int ( + "tab-label-size", + _("Tab Label Size"), + _("The desired tab label size"), + 0, G_MAXINT, 10, + flags)); + + g_object_class_install_property (gobject_class, + PROP_CLOSE_BUTTONS_ON_TABS, + g_param_spec_boolean ( + "close-buttons-on-tabs", + _("Close Buttons on Tabs"), + _("Whether tabs have close buttons"), + TRUE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_OPEN_NEW_PAGES_IN, + g_param_spec_enum ( + "open-new-pages-in", + _("Open new pages in"), + _("Where to open new pages"), + MIDORI_TYPE_NEW_PAGE, + MIDORI_NEW_PAGE_TAB, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_MIDDLE_CLICK_OPENS_SELECTION, + g_param_spec_boolean ( + "middle-click-opens-selection", + _("Middle click opens Selection"), + _("Load an URL from the selection via middle click"), + FALSE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_OPEN_TABS_IN_THE_BACKGROUND, + g_param_spec_boolean ( + "open-tabs-in-the-background", + _("Open tabs in the background"), + _("Whether to open new tabs in the background"), + FALSE, + flags)); + + g_object_class_install_property (gobject_class, + PROP_OPEN_POPUPS_IN_TABS, + g_param_spec_boolean ( + "open-popups-in-tabs", + _("Open popups in tabs"), + _("Whether to open popup windows in tabs"), + TRUE, + flags)); + + + + g_object_class_install_property (gobject_class, + PROP_ACCEPT_COOKIES, + g_param_spec_enum ( + "accept-cookies", + _("Accept cookies"), + _("What type of cookies to accept"), + MIDORI_TYPE_ACCEPT_COOKIES, + MIDORI_ACCEPT_COOKIES_ALL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_ORIGINAL_COOKIES_ONLY, + g_param_spec_boolean ( + "original-cookies-only", + _("Original cookies only"), + _("Accept cookies from the original website only"), + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_MAXIMUM_COOKIE_AGE, + g_param_spec_int ( + "maximum-cookie-age", + _("Maximum cookie age"), + _("The maximum number of days to save cookies for"), + 0, G_MAXINT, 30, + G_PARAM_READABLE)); + + + + g_object_class_install_property (gobject_class, + PROP_REMEMBER_LAST_VISITED_PAGES, + g_param_spec_boolean ( + "remember-last-visited-pages", + _("Remember last visited pages"), + _("Whether the last visited pages are saved"), + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_MAXIMUM_HISTORY_AGE, + g_param_spec_int ( + "maximum-history-age", + _("Maximum history age"), + _("The maximum number of days to save the history for"), + 0, G_MAXINT, 30, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_REMEMBER_LAST_FORM_INPUTS, + g_param_spec_boolean ( + "remember-last-form-inputs", + _("Remember last form inputs"), + _("Whether the last form inputs are saved"), + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_REMEMBER_LAST_DOWNLOADED_FILES, + g_param_spec_boolean ( + "remember-last-downloaded-files", + _("Remember last downloaded files"), + _("Whether the last downloaded files are saved"), + TRUE, + G_PARAM_READABLE)); + + + + g_object_class_install_property (gobject_class, + PROP_HTTP_PROXY, + g_param_spec_string ( + "http-proxy", + _("HTTP Proxy"), + _("The proxy used for HTTP connections"), + g_getenv ("http_proxy"), + flags)); + + g_object_class_install_property (gobject_class, + PROP_CACHE_SIZE, + g_param_spec_int ( + "cache-size", + _("Cache size"), + _("The allowed size of the cache"), + 0, G_MAXINT, 100, + G_PARAM_READABLE)); + + g_type_class_add_private (class, sizeof (MidoriWebSettingsPrivate)); +} + +static void +notify_default_encoding_cb (GObject* object, GParamSpec* pspec) +{ + MidoriWebSettings* web_settings = MIDORI_WEB_SETTINGS (object); + MidoriWebSettingsPrivate* priv = web_settings->priv; + + const gchar* string; + g_object_get (object, "default-encoding", &string, NULL); + const gchar* encoding = string ? string : ""; + if (!strcmp (encoding, "BIG5")) + priv->preferred_encoding = MIDORI_ENCODING_CHINESE; + else if (!strcmp (encoding, "SHIFT_JIS")) + priv->preferred_encoding = MIDORI_ENCODING_JAPANESE; + else if (!strcmp (encoding, "KOI8-R")) + priv->preferred_encoding = MIDORI_ENCODING_RUSSIAN; + else if (!strcmp (encoding, "UTF-8")) + priv->preferred_encoding = MIDORI_ENCODING_UNICODE; + else if (!strcmp (encoding, "ISO-8859-1")) + priv->preferred_encoding = MIDORI_ENCODING_WESTERN; + else + priv->preferred_encoding = MIDORI_ENCODING_CUSTOM; + g_object_notify (object, "preferred-encoding"); +} + +static void +midori_web_settings_init (MidoriWebSettings* web_settings) +{ + web_settings->priv = MIDORI_WEB_SETTINGS_GET_PRIVATE (web_settings); + + g_signal_connect (web_settings, "notify::default-encoding", + G_CALLBACK (notify_default_encoding_cb), NULL); +} + +static void +midori_web_settings_finalize (GObject* object) +{ + G_OBJECT_CLASS (midori_web_settings_parent_class)->finalize (object); +} + +static void +midori_web_settings_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriWebSettings* web_settings = MIDORI_WEB_SETTINGS (object); + MidoriWebSettingsPrivate* priv = web_settings->priv; + + switch (prop_id) + { + case PROP_REMEMBER_LAST_WINDOW_SIZE: + priv->remember_last_window_size = g_value_get_boolean (value); + break; + case PROP_LAST_WINDOW_WIDTH: + priv->last_window_width = g_value_get_int (value); + break; + case PROP_LAST_WINDOW_HEIGHT: + priv->last_window_height = g_value_get_int (value); + break; + case PROP_LAST_PANEL_POSITION: + priv->last_panel_position = g_value_get_int (value); + break; + case PROP_LAST_PANEL_PAGE: + priv->last_panel_page = g_value_get_int (value); + break; + case PROP_LAST_WEB_SEARCH: + priv->last_web_search = g_value_get_int (value); + break; + case PROP_LAST_PAGEHOLDER_URI: + katze_assign (priv->last_pageholder_uri, g_value_dup_string (value)); + break; + + case PROP_SHOW_NAVIGATIONBAR: + priv->show_navigationbar = g_value_get_boolean (value); + break; + case PROP_SHOW_BOOKMARKBAR: + priv->show_bookmarkbar = g_value_get_boolean (value); + break; + case PROP_SHOW_PANEL: + priv->show_panel = g_value_get_boolean (value); + break; + case PROP_SHOW_STATUSBAR: + priv->show_statusbar = g_value_get_boolean (value); + break; + + case PROP_TOOLBAR_STYLE: + priv->toolbar_style = g_value_get_enum (value); + break; + case PROP_SMALL_TOOLBAR: + priv->small_toolbar = g_value_get_boolean (value); + break; + case PROP_SHOW_NEW_TAB: + priv->show_new_tab = g_value_get_boolean (value); + break; + case PROP_SHOW_HOMEPAGE: + priv->show_homepage = g_value_get_boolean (value); + break; + case PROP_SHOW_WEB_SEARCH: + priv->show_web_search = g_value_get_boolean (value); + break; + case PROP_SHOW_TRASH: + priv->show_trash = g_value_get_boolean (value); + break; + + case PROP_LOAD_ON_STARTUP: + priv->load_on_startup = g_value_get_enum (value); + break; + case PROP_HOMEPAGE: + katze_assign (priv->homepage, g_value_dup_string (value)); + break; + case PROP_DOWNLOAD_FOLDER: + katze_assign (priv->download_folder, g_value_dup_string (value)); + break; + case PROP_SHOW_DOWNLOAD_NOTIFICATION: + priv->show_download_notification = g_value_get_boolean (value); + break; + case PROP_LOCATION_ENTRY_SEARCH: + katze_assign (priv->location_entry_search, g_value_dup_string (value)); + break; + case PROP_PREFERRED_ENCODING: + priv->preferred_encoding = g_value_get_enum (value); + switch (priv->preferred_encoding) + { + case MIDORI_ENCODING_CHINESE: + g_object_set (object, "default-encoding", "BIG5", NULL); + break; + case MIDORI_ENCODING_JAPANESE: + g_object_set (object, "default-encoding", "SHIFT_JIS", NULL); + break; + case MIDORI_ENCODING_RUSSIAN: + g_object_set (object, "default-encoding", "KOI8-R", NULL); + break; + case MIDORI_ENCODING_UNICODE: + g_object_set (object, "default-encoding", "UTF-8", NULL); + break; + case MIDORI_ENCODING_WESTERN: + g_object_set (object, "default-encoding", "ISO-8859-1", NULL); + break; + case MIDORI_ENCODING_CUSTOM: + g_object_set (object, "default-encoding", "", NULL); + } + break; + + case PROP_TAB_LABEL_SIZE: + priv->tab_label_size = g_value_get_int (value); + break; + case PROP_CLOSE_BUTTONS_ON_TABS: + priv->close_buttons_on_tabs = g_value_get_boolean (value); + break; + case PROP_OPEN_NEW_PAGES_IN: + priv->open_new_pages_in = g_value_get_enum (value); + break; + case PROP_MIDDLE_CLICK_OPENS_SELECTION: + priv->middle_click_opens_selection = g_value_get_boolean (value); + break; + case PROP_OPEN_TABS_IN_THE_BACKGROUND: + priv->open_tabs_in_the_background = g_value_get_boolean (value); + break; + case PROP_OPEN_POPUPS_IN_TABS: + priv->open_popups_in_tabs = g_value_get_boolean (value); + break; + + case PROP_ACCEPT_COOKIES: + priv->accept_cookies = g_value_get_enum (value); + break; + case PROP_ORIGINAL_COOKIES_ONLY: + priv->original_cookies_only = g_value_get_boolean (value); + break; + case PROP_MAXIMUM_COOKIE_AGE: + priv->maximum_cookie_age = g_value_get_int (value); + break; + + case PROP_REMEMBER_LAST_VISITED_PAGES: + priv->remember_last_visited_pages = g_value_get_boolean (value); + break; + case PROP_MAXIMUM_HISTORY_AGE: + priv->maximum_history_age = g_value_get_int (value); + break; + case PROP_REMEMBER_LAST_FORM_INPUTS: + priv->remember_last_form_inputs = g_value_get_boolean (value); + break; + case PROP_REMEMBER_LAST_DOWNLOADED_FILES: + priv->remember_last_downloaded_files = g_value_get_boolean (value); + break; + + case PROP_HTTP_PROXY: + katze_assign (priv->http_proxy, g_value_dup_string (value)); + g_setenv ("http_proxy", priv->http_proxy ? priv->http_proxy : "", TRUE); + break; + case PROP_CACHE_SIZE: + priv->cache_size = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_web_settings_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriWebSettings* web_settings = MIDORI_WEB_SETTINGS (object); + MidoriWebSettingsPrivate* priv = web_settings->priv; + + switch (prop_id) + { + case PROP_REMEMBER_LAST_WINDOW_SIZE: + g_value_set_boolean (value, priv->remember_last_window_size); + break; + case PROP_LAST_WINDOW_WIDTH: + g_value_set_int (value, priv->last_window_width); + break; + case PROP_LAST_WINDOW_HEIGHT: + g_value_set_int (value, priv->last_window_height); + break; + case PROP_LAST_PANEL_POSITION: + g_value_set_int (value, priv->last_panel_position); + break; + case PROP_LAST_PANEL_PAGE: + g_value_set_int (value, priv->last_panel_page); + break; + case PROP_LAST_WEB_SEARCH: + g_value_set_int (value, priv->last_web_search); + break; + case PROP_LAST_PAGEHOLDER_URI: + g_value_set_string (value, priv->last_pageholder_uri); + break; + + case PROP_SHOW_NAVIGATIONBAR: + g_value_set_boolean (value, priv->show_navigationbar); + break; + case PROP_SHOW_BOOKMARKBAR: + g_value_set_boolean (value, priv->show_bookmarkbar); + break; + case PROP_SHOW_PANEL: + g_value_set_boolean (value, priv->show_panel); + break; + case PROP_SHOW_STATUSBAR: + g_value_set_boolean (value, priv->show_statusbar); + break; + + case PROP_TOOLBAR_STYLE: + g_value_set_enum (value, priv->toolbar_style); + break; + case PROP_SMALL_TOOLBAR: + g_value_set_boolean (value, priv->small_toolbar); + break; + case PROP_SHOW_NEW_TAB: + g_value_set_boolean (value, priv->show_new_tab); + break; + case PROP_SHOW_HOMEPAGE: + g_value_set_boolean (value, priv->show_homepage); + break; + case PROP_SHOW_WEB_SEARCH: + g_value_set_boolean (value, priv->show_web_search); + break; + case PROP_SHOW_TRASH: + g_value_set_boolean (value, priv->show_trash); + break; + + case PROP_LOAD_ON_STARTUP: + g_value_set_enum (value, priv->load_on_startup); + break; + case PROP_HOMEPAGE: + g_value_set_string (value, priv->homepage); + break; + case PROP_DOWNLOAD_FOLDER: + g_value_set_string (value, priv->download_folder); + break; + case PROP_SHOW_DOWNLOAD_NOTIFICATION: + g_value_set_boolean (value, priv->show_download_notification); + break; + case PROP_LOCATION_ENTRY_SEARCH: + g_value_set_string (value, priv->location_entry_search); + break; + case PROP_PREFERRED_ENCODING: + g_value_set_enum (value, priv->preferred_encoding); + break; + + case PROP_TAB_LABEL_SIZE: + g_value_set_int (value, priv->tab_label_size); + break; + case PROP_CLOSE_BUTTONS_ON_TABS: + g_value_set_boolean (value, priv->close_buttons_on_tabs); + break; + case PROP_OPEN_NEW_PAGES_IN: + g_value_set_enum (value, priv->open_new_pages_in); + break; + case PROP_MIDDLE_CLICK_OPENS_SELECTION: + g_value_set_boolean (value, priv->middle_click_opens_selection); + break; + case PROP_OPEN_TABS_IN_THE_BACKGROUND: + g_value_set_boolean (value, priv->open_tabs_in_the_background); + break; + case PROP_OPEN_POPUPS_IN_TABS: + g_value_set_boolean (value, priv->open_popups_in_tabs); + break; + + case PROP_ACCEPT_COOKIES: + g_value_set_enum (value, priv->accept_cookies); + break; + case PROP_ORIGINAL_COOKIES_ONLY: + g_value_set_boolean (value, priv->original_cookies_only); + break; + case PROP_MAXIMUM_COOKIE_AGE: + g_value_set_int (value, priv->maximum_cookie_age); + break; + + case PROP_REMEMBER_LAST_VISITED_PAGES: + g_value_set_boolean (value, priv->remember_last_visited_pages); + break; + case PROP_MAXIMUM_HISTORY_AGE: + g_value_set_int (value, priv->maximum_history_age); + break; + case PROP_REMEMBER_LAST_FORM_INPUTS: + g_value_set_boolean (value, priv->remember_last_form_inputs); + break; + case PROP_REMEMBER_LAST_DOWNLOADED_FILES: + g_value_set_boolean (value, priv->remember_last_downloaded_files); + break; + + case PROP_HTTP_PROXY: + g_value_set_string (value, priv->http_proxy); + break; + case PROP_CACHE_SIZE: + g_value_set_int (value, priv->cache_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_web_settings_notify (GObject* object, + GParamSpec* pspec) +{ + +} + +/** + * midori_web_settings_new: + * + * Creates a new #MidoriWebSettings instance with default values. + * + * You will typically want to assign this to a #MidoriWebView or #MidoriBrowser. + * + * Return value: a new #MidoriWebSettings + **/ +MidoriWebSettings* +midori_web_settings_new (void) +{ + MidoriWebSettings* web_settings = g_object_new (MIDORI_TYPE_WEB_SETTINGS, + NULL); + + return web_settings; +} + +/** + * midori_web_settings_copy: + * + * Copies an existing #MidoriWebSettings instance. + * + * Return value: a new #MidoriWebSettings + **/ +MidoriWebSettings* +midori_web_settings_copy (MidoriWebSettings* web_settings) +{ + g_return_val_if_fail (MIDORI_IS_WEB_SETTINGS (web_settings), NULL); + + MidoriWebSettingsPrivate* priv = web_settings->priv; + + MidoriWebSettings* copy; + copy = MIDORI_WEB_SETTINGS (webkit_web_settings_copy ( + WEBKIT_WEB_SETTINGS (web_settings))); + g_object_set (copy, + "load-on-startup", priv->load_on_startup, + "homepage", priv->homepage, + "download-folder", priv->download_folder, + "show-download-notification", priv->show_download_notification, + "location-entry-search", priv->location_entry_search, + "preferred-encoding", priv->preferred_encoding, + + "toolbar-style", priv->toolbar_style, + "small-toolbar", priv->small_toolbar, + "show-web-search", priv->show_web_search, + "show-new-tab", priv->show_new_tab, + "show-trash", priv->show_trash, + + "tab-label-size", priv->tab_label_size, + "close-buttons-on-tabs", priv->close_buttons_on_tabs, + "open-new-pages-in", priv->open_new_pages_in, + "middle-click-opens-selection", priv->middle_click_opens_selection, + "open-tabs-in-the-background", priv->open_tabs_in_the_background, + "open-popups-in-tabs", priv->open_popups_in_tabs, + + "accept-cookies", priv->accept_cookies, + "original-cookies-only", priv->original_cookies_only, + "maximum-cookie-age", priv->maximum_cookie_age, + + "remember-last-visited-pages", priv->remember_last_visited_pages, + "maximum-history-age", priv->maximum_history_age, + "remember-last-form-inputs", priv->remember_last_form_inputs, + "remember-last-downloaded-files", priv->remember_last_downloaded_files, + + "http-proxy", priv->http_proxy, + "cache-size", priv->cache_size, + NULL); + + return copy; +} diff --git a/midori/midori-websettings.h b/midori/midori-websettings.h new file mode 100644 index 00000000..ceb8c380 --- /dev/null +++ b/midori/midori-websettings.h @@ -0,0 +1,135 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_WEB_SETTINGS_H__ +#define __MIDORI_WEB_SETTINGS_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_WEB_SETTINGS \ + (midori_web_settings_get_type ()) +#define MIDORI_WEB_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettings)) +#define MIDORI_WEB_SETTINGS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsClass)) +#define MIDORI_IS_WEB_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_SETTINGS)) +#define MIDORI_IS_WEB_SETTINGS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_SETTINGS)) +#define MIDORI_WEB_SETTINGS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsClass)) + +typedef struct _MidoriWebSettings MidoriWebSettings; +typedef struct _MidoriWebSettingsPrivate MidoriWebSettingsPrivate; +typedef struct _MidoriWebSettingsClass MidoriWebSettingsClass; + +struct _MidoriWebSettings +{ + WebKitWebSettings parent_instance; + + MidoriWebSettingsPrivate* priv; +}; + +typedef enum +{ + MIDORI_STARTUP_BLANK_PAGE, + MIDORI_STARTUP_HOMEPAGE, + MIDORI_STARTUP_LAST_OPEN_PAGES +} MidoriStartup; + +GType +midori_startup_get_type (void) G_GNUC_CONST; + +#define MIDORI_TYPE_STARTUP \ + (midori_startup_get_type ()) + +typedef enum +{ + MIDORI_ENCODING_CHINESE, + MIDORI_ENCODING_JAPANESE, + MIDORI_ENCODING_RUSSIAN, + MIDORI_ENCODING_UNICODE, + MIDORI_ENCODING_WESTERN, + MIDORI_ENCODING_CUSTOM +} MidoriPreferredEncoding; + +GType +midori_preferred_encoding_get_type (void) G_GNUC_CONST; + +#define MIDORI_TYPE_PREFERRED_ENCODING \ + (midori_preferred_encoding_get_type ()) + +typedef enum +{ + MIDORI_NEW_PAGE_TAB, + MIDORI_NEW_PAGE_WINDOW, + MIDORI_NEW_PAGE_CURRENT +} MidoriNewPage; + +GType +midori_new_page_get_type (void) G_GNUC_CONST; + +#define MIDORI_TYPE_NEW_PAGE \ + (midori_new_page_get_type ()) + +typedef enum +{ + MIDORI_TOOLBAR_DEFAULT, + MIDORI_TOOLBAR_ICONS, + MIDORI_TOOLBAR_TEXT, + MIDORI_TOOLBAR_BOTH, + MIDORI_TOOLBAR_BOTH_HORIZ +} MidoriToolbarStyle; + +GType +midori_toolbar_style_get_type (void) G_GNUC_CONST; + +#define MIDORI_TYPE_TOOLBAR_STYLE \ + (midori_toolbar_style_get_type ()) + +typedef enum +{ + MIDORI_ACCEPT_COOKIES_ALL, + MIDORI_ACCEPT_COOKIES_SESSION, + MIDORI_ACCEPT_COOKIES_NONE +} MidoriAcceptCookies; + +GType +midori_accept_cookies_get_type (void) G_GNUC_CONST; + +#define MIDORI_TYPE_ACCEPT_COOKIES \ + (midori_accept_cookies_get_type ()) + +struct _MidoriWebSettingsClass +{ + WebKitWebSettingsClass parent_class; + + /* Signals */ + void + (*dummy) (MidoriWebSettings* web_settings); +}; + +GType +midori_web_settings_get_type (void); + +MidoriWebSettings* +midori_web_settings_new (void); + +MidoriWebSettings* +midori_web_settings_copy (MidoriWebSettings* web_settings); + +G_END_DECLS + +#endif /* __MIDORI_WEB_SETTINGS_H__ */ diff --git a/midori/midori-webview.c b/midori/midori-webview.c new file mode 100644 index 00000000..b5e0f080 --- /dev/null +++ b/midori/midori-webview.c @@ -0,0 +1,1122 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + 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 "midori-webview.h" + +#include "main.h" +#include "sokoke.h" + +#include +#include + +// This is unstable API, so we need to declare it +gchar* +webkit_web_view_get_selected_text (WebKitWebView* web_view); + +G_DEFINE_TYPE (MidoriWebView, midori_web_view, WEBKIT_TYPE_WEB_VIEW) + +struct _MidoriWebViewPrivate +{ + GtkWidget* tab_icon; + GtkWidget* tab_label; + GtkWidget* tab_close; + GdkPixbuf* icon; + gchar* uri; + gchar* title; + gboolean is_loading; + gint progress; + gchar* statusbar_text; + gchar* link_uri; + + gint tab_label_size; + gboolean close_button; + gboolean middle_click_opens_selection; + MidoriWebSettings* settings; + + GtkWidget* proxy_menu_item; + GtkWidget* proxy_tab_label; + KatzeXbelItem* proxy_xbel_item; +}; + +#define MIDORI_WEB_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + MIDORI_TYPE_WEB_VIEW, MidoriWebViewPrivate)) + +enum +{ + PROP_0, + + PROP_ICON, + PROP_URI, + PROP_TITLE, + PROP_STATUSBAR_TEXT, + PROP_SETTINGS +}; + +enum { + LOAD_STARTED, + PROGRESS_STARTED, + PROGRESS_CHANGED, + PROGRESS_DONE, + LOAD_DONE, + ELEMENT_MOTION, + CLOSE, + NEW_TAB, + NEW_WINDOW, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_web_view_finalize (GObject* object); + +static void +midori_web_view_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_web_view_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +/*static WebKitWebView* +midori_web_view_create_web_view (WebKitWebView* web_view) +{ + MidoriWebView* new_web_view = NULL; + g_signal_emit (web_view, signals[NEW_WINDOW], 0, &new_web_view); + if (new_web_view) + return WEBKIT_WEB_VIEW (new_web_view); + return WEBKIT_WEB_VIEW (midori_web_view_new ()); +}*/ + +static void +midori_web_view_class_init (MidoriWebViewClass* class) +{ + signals[PROGRESS_STARTED] = g_signal_new ( + "progress-started", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriWebViewClass, progress_started), + 0, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + signals[PROGRESS_CHANGED] = g_signal_new ( + "progress-changed", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriWebViewClass, progress_changed), + 0, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + signals[PROGRESS_DONE] = g_signal_new ( + "progress-done", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriWebViewClass, progress_done), + 0, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + signals[LOAD_DONE] = g_signal_new ( + "load-done", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriWebViewClass, load_done), + 0, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + WEBKIT_TYPE_WEB_FRAME); + + signals[ELEMENT_MOTION] = g_signal_new( + "element-motion", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriWebViewClass, element_motion), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[CLOSE] = g_signal_new( + "close", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, close), + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[NEW_TAB] = g_signal_new( + "new-tab", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET (MidoriWebViewClass, new_tab), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[NEW_WINDOW] = g_signal_new( + "new-window", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST), + G_STRUCT_OFFSET (MidoriWebViewClass, new_window), + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + /*WEBKIT_WEB_VIEW_CLASS (class)->create_web_view = g_signal_new ("create-web-view", + G_TYPE_FROM_CLASS(class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET(MidoriWebViewClass, create_web_view), + 0, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + MIDORI_TYPE_WEB_VIEW);*/ + + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_web_view_finalize; + gobject_class->set_property = midori_web_view_set_property; + gobject_class->get_property = midori_web_view_get_property; + + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_ICON, + g_param_spec_object ( + "icon", + "Icon", + _("The icon of the currently loaded page"), + GDK_TYPE_PIXBUF, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_URI, + g_param_spec_string ( + "uri", + "Uri", + _("The URI of the currently loaded page"), + "", + flags)); + + g_object_class_install_property (gobject_class, + PROP_TITLE, + g_param_spec_string ( + "title", + "Title", + _("The title of the currently loaded page"), + NULL, + flags)); + + g_object_class_install_property (gobject_class, + PROP_STATUSBAR_TEXT, + g_param_spec_string ( + "statusbar-text", + "Statusbar Text", + _("The text that is displayed in the statusbar"), + "", + flags)); + + g_object_class_override_property (gobject_class, + PROP_SETTINGS, + "settings"); + + g_type_class_add_private (class, sizeof (MidoriWebViewPrivate)); +} + +/*static void +webkit_web_view_load_started (MidoriWebView* web_view, + WebKitWebFrame* web_frame) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->is_loading = TRUE; + priv->progress = -1; + katze_throbber_set_animated(KATZE_THROBBER(priv->tab_icon), TRUE); +}*/ + +static void +_midori_web_view_set_uri (MidoriWebView* web_view, + const gchar* uri) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + katze_assign (priv->uri, g_strdup (uri)); + if (priv->proxy_xbel_item) + { + const gchar* uri = midori_web_view_get_display_uri (web_view); + katze_xbel_bookmark_set_href (priv->proxy_xbel_item, uri); + } + g_object_set (web_view, "title", NULL, NULL); +} + +static void +webkit_web_view_load_committed (MidoriWebView* web_view, + WebKitWebFrame* web_frame) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->progress = 0; + const gchar* uri = webkit_web_frame_get_uri (web_frame); + _midori_web_view_set_uri (web_view, uri); +} + +static void +webkit_web_view_load_started (MidoriWebView* web_view, + WebKitWebFrame* web_frame) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + // FIXME: This is a hack, until signals are fixed upstream + priv->is_loading = TRUE; + if (priv->tab_icon) + katze_throbber_set_animated (KATZE_THROBBER (priv->tab_icon), TRUE); + + priv->progress = 0; + g_signal_emit (web_view, signals[PROGRESS_STARTED], 0, priv->progress); +} + +static void +webkit_web_view_progress_changed (MidoriWebView* web_view, gint progress) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->progress = progress; + g_signal_emit (web_view, signals[PROGRESS_CHANGED], 0, priv->progress); +} + +static void +webkit_web_view_load_finished (MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->progress = 100; + g_signal_emit (web_view, signals[PROGRESS_DONE], 0, priv->progress); +} + +static void +webkit_web_frame_load_done (WebKitWebFrame* web_frame, gboolean success, + MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + priv->is_loading = FALSE; + priv->progress = -1; + if (priv->tab_icon) + katze_throbber_set_animated (KATZE_THROBBER (priv->tab_icon), FALSE); + g_signal_emit (web_view, signals[LOAD_DONE], 0, web_frame); +} + +static void +webkit_web_view_title_changed (MidoriWebView* web_view, + WebKitWebFrame* web_frame, const gchar* title) +{ + g_object_set (web_view, "title", title, NULL); +} + +static void +webkit_web_view_statusbar_text_changed (MidoriWebView* web_view, + const gchar* text) +{ + g_object_set (web_view, "statusbar-text", text, NULL); +} + +static void +webkit_web_view_hovering_over_link (MidoriWebView* web_view, + const gchar* tooltip, + const gchar* link_uri) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + katze_assign (priv->link_uri, g_strdup (link_uri)); + g_signal_emit (web_view, signals[ELEMENT_MOTION], 0, link_uri); +} + +static gboolean +gtk_widget_button_press_event (MidoriWebView* web_view, + GdkEventButton* event) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + GdkModifierType state = (GdkModifierType)0; + gint x, y; + gdk_window_get_pointer (NULL, &x, &y, &state); + switch (event->button) + { + case 1: + if (!priv->link_uri) + return FALSE; + if (state & GDK_SHIFT_MASK) + { + // Open link in new window + g_signal_emit (web_view, signals[NEW_WINDOW], 0, priv->link_uri); + return TRUE; + } + else if(state & GDK_MOD1_MASK) + { + // Open link in new tab + g_signal_emit (web_view, signals[NEW_TAB], 0, priv->link_uri); + return TRUE; + } + break; + case 2: + if (state & GDK_CONTROL_MASK) + { + // FIXME: Reset font multiplier or zoom level + return FALSE; // Allow Ctrl + Middle click + } + else + { + if (!priv->link_uri) + return FALSE; + // Open link in new tab + g_signal_emit (web_view, signals[NEW_TAB], 0, priv->link_uri); + return TRUE; + } + break; + case 3: + return FALSE; + } + return FALSE; +} + +static gboolean +gtk_widget_button_press_event_after (MidoriWebView* web_view, + GdkEventButton* event) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + if (event->button == 2 && priv->middle_click_opens_selection) + { + GdkModifierType state = (GdkModifierType) event->state; + GtkClipboard* clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); + gchar* uri = gtk_clipboard_wait_for_text (clipboard); + if (uri && strchr (uri, '.') && !strchr (uri, ' ')) + { + if (state & GDK_CONTROL_MASK) + g_signal_emit (web_view, signals[NEW_TAB], 0, uri); + else + g_object_set (web_view, "uri", uri, NULL); + g_free (uri); + return TRUE; + } + } + return FALSE; +} + +static gboolean +gtk_widget_scroll_event (MidoriWebView* web_view, + GdkEventScroll* event) +{ + GdkModifierType state = (GdkModifierType)0; + gint x, y; + gdk_window_get_pointer (NULL, &x, &y, &state); + if (state & GDK_CONTROL_MASK) + { + // FIXME: Increase or decrease the font multiplier or zoom level + if (event->direction == GDK_SCROLL_DOWN) + ; + else if(event->direction == GDK_SCROLL_UP) + ; + return TRUE; + } + else + return FALSE; +} + +static void +midori_web_view_menu_new_tab_activate_cb (GtkWidget* widget, + MidoriWebView* web_view) +{ + const gchar* uri = g_object_get_data (G_OBJECT (widget), "uri"); + g_signal_emit (web_view, signals[NEW_TAB], 0, uri); +} + +static void +webkit_web_view_populate_popup_cb (GtkWidget* web_view, + GtkWidget* menu) +{ + const gchar* uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); + if (uri) + { + GtkWidget* menuitem = gtk_image_menu_item_new_with_mnemonic ( + _("Open Link in New _Tab")); + GdkScreen* screen = gtk_widget_get_screen (web_view); + GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen); + if (gtk_icon_theme_has_icon (icon_theme, STOCK_TAB_NEW)) + { + GtkWidget* icon = gtk_image_new_from_stock (STOCK_TAB_NEW, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); + } + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 1); + g_object_set_data (G_OBJECT (menuitem), "uri", (gchar*)uri); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), web_view); + gtk_widget_show (menuitem); + } + + if (!uri && webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) + { + gchar* text = webkit_web_view_get_selected_text ( + WEBKIT_WEB_VIEW (web_view)); + if (text && strchr (text, '.') && !strchr (text, ' ')) + { + GtkWidget* menuitem = gtk_image_menu_item_new_with_mnemonic ( + _("Open URL in New _Tab")); + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1); + g_object_set_data (G_OBJECT (menuitem), "uri", text); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), web_view); + gtk_widget_show (menuitem); + } + // FIXME: We are leaking 'text' which is not const but should be. + } +} + +static void +_midori_web_view_update_tab_label_size (MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + if (priv->tab_label) + { + if (priv->tab_label_size > -1) + { + gint width, height; + sokoke_widget_get_text_size (priv->tab_label, "M", + &width, &height); + gtk_widget_set_size_request (priv->tab_label, + width * priv->tab_label_size, -1); + gtk_label_set_ellipsize (GTK_LABEL (priv->tab_label), + PANGO_ELLIPSIZE_END); + } + else + { + gtk_widget_set_size_request (priv->tab_label, -1, -1); + gtk_label_set_ellipsize (GTK_LABEL (priv->tab_label), + PANGO_ELLIPSIZE_NONE); + } + } +} + +static void +_midori_web_view_update_settings (MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + g_object_get (G_OBJECT (priv->settings), + "tab-label-size", &priv->tab_label_size, + "close-buttons-on-tabs", &priv->close_button, + "middle-click-opens-selection", &priv->middle_click_opens_selection, + NULL); +} + +static void +midori_web_view_settings_notify (MidoriWebSettings* web_settings, + GParamSpec* pspec, + MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + const gchar* name = g_intern_string (pspec->name); + GValue value = {0, }; + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (priv->settings), name, &value); + + if (name == g_intern_string ("tab-label-size")) + { + priv->tab_label_size = g_value_get_int (&value); + _midori_web_view_update_tab_label_size (web_view); + } + else if (name == g_intern_string ("close-buttons-on-tabs")) + { + priv->close_button = g_value_get_boolean (&value); + if (priv->tab_close) + sokoke_widget_set_visible (priv->tab_close, priv->close_button); + } + else if (name == g_intern_string ("middle-click-opens-selection")) + priv->middle_click_opens_selection = g_value_get_boolean (&value); + else if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_settings), + name)) + g_warning (_("Unexpected setting '%s'"), name); + g_value_unset (&value); +} + +static void +midori_web_view_init (MidoriWebView* web_view) +{ + web_view->priv = MIDORI_WEB_VIEW_GET_PRIVATE (web_view); + + MidoriWebViewPrivate* priv = web_view->priv; + priv->is_loading = FALSE; + priv->progress = -1; + + priv->settings = midori_web_settings_new (); + _midori_web_view_update_settings (web_view); + g_object_set (web_view, "WebKitWebView::settings", priv->settings, NULL); + g_signal_connect (priv->settings, "notify", + G_CALLBACK (midori_web_view_settings_notify), web_view); + + WebKitWebFrame* web_frame; + web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view)); + + g_object_connect (web_view, + //"signal::load-started", + //webkit_web_view_load_started, NULL, + "signal::load-committed", + webkit_web_view_load_committed, NULL, + "signal::load-started", + webkit_web_view_load_started, NULL, + "signal::load-progress-changed", + webkit_web_view_progress_changed, NULL, + "signal::load-finished", + webkit_web_view_load_finished, NULL, + //"signal::load-done", + //webkit_web_view_load_done, NULL, + "signal::title-changed", + webkit_web_view_title_changed, NULL, + "signal::status-bar-text-changed", + webkit_web_view_statusbar_text_changed, NULL, + "signal::hovering-over-link", + webkit_web_view_hovering_over_link, NULL, + "signal::button-press-event", + gtk_widget_button_press_event, NULL, + "signal_after::button-press-event", + gtk_widget_button_press_event_after, NULL, + "signal::scroll-event", + gtk_widget_scroll_event, NULL, + "signal::populate-popup", + webkit_web_view_populate_popup_cb, NULL, + NULL); + g_object_connect (web_frame, + "signal::load-done", + webkit_web_frame_load_done, web_view, + NULL); +} + +static void +midori_web_view_finalize (GObject* object) +{ + MidoriWebView* web_view = MIDORI_WEB_VIEW (object); + MidoriWebViewPrivate* priv = web_view->priv; + + if (priv->icon) + g_object_unref (priv->icon); + g_free (priv->uri); + g_free (priv->title); + g_free (priv->statusbar_text); + g_free (priv->link_uri); + + if (priv->proxy_menu_item) + gtk_widget_destroy (priv->proxy_menu_item); + if (priv->proxy_xbel_item) + katze_xbel_item_unref (priv->proxy_xbel_item); + + if (priv->settings) + g_object_unref (priv->settings); + + G_OBJECT_CLASS (midori_web_view_parent_class)->finalize (object); +} + +static void +midori_web_view_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriWebView* web_view = MIDORI_WEB_VIEW (object); + MidoriWebViewPrivate* priv = web_view->priv; + + switch (prop_id) + { + case PROP_ICON: + katze_object_assign (priv->icon, g_value_get_object (value)); + g_object_ref (priv->icon); + if (priv->tab_icon) + katze_throbber_set_static_pixbuf (KATZE_THROBBER (priv->tab_icon), + priv->icon); + break; + case PROP_URI: + { + const gchar* uri = g_value_get_string (value); + if (uri && *uri) + { + // FIXME: Autocomplete the uri + webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), uri); + } + break; + } + case PROP_TITLE: + katze_assign (priv->title, g_value_dup_string (value)); + const gchar* title = midori_web_view_get_display_title (web_view); + if (priv->tab_label) + { + gtk_label_set_text (GTK_LABEL (priv->tab_label), title); + sokoke_widget_set_tooltip_text (priv->tab_label, title); + } + if (priv->proxy_menu_item) + gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN ( + priv->proxy_menu_item))), title); + if (priv->proxy_xbel_item) + katze_xbel_item_set_title (priv->proxy_xbel_item, title); + break; + case PROP_STATUSBAR_TEXT: + katze_assign (priv->statusbar_text, g_value_dup_string (value)); + break; + case PROP_SETTINGS: + g_signal_handlers_disconnect_by_func (priv->settings, + midori_web_view_settings_notify, + web_view); + katze_object_assign (priv->settings, g_value_get_object (value)); + g_object_ref (priv->settings); + _midori_web_view_update_settings (web_view); + g_object_set (object, "WebKitWebView::settings", priv->settings, NULL); + g_signal_connect (priv->settings, "notify", + G_CALLBACK (midori_web_view_settings_notify), web_view); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_web_view_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriWebView* web_view = MIDORI_WEB_VIEW (object); + MidoriWebViewPrivate* priv = web_view->priv; + + switch (prop_id) + { + case PROP_ICON: + g_value_set_object (value, priv->icon); + break; + case PROP_URI: + g_value_set_string (value, priv->uri); + break; + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + case PROP_STATUSBAR_TEXT: + g_value_set_string (value, priv->statusbar_text); + break; + case PROP_SETTINGS: + g_value_set_object (value, priv->settings); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_web_view_new: + * + * Creates a new web view widget. + * + * Return value: a new #MidoriWebView + **/ +GtkWidget* +midori_web_view_new (void) +{ + MidoriWebView* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, + NULL); + + return GTK_WIDGET (web_view); +} + +/** + * midori_web_view_set_settings: + * @web_view: a #MidoriWebView + * @web_settings: a #MidoriWebSettings + * + * Assigns a settings instance to the web view. + **/ +void +midori_web_view_set_settings (MidoriWebView* web_view, + MidoriWebSettings* web_settings) +{ + g_object_set (web_view, "settings", web_settings, NULL); +} + +/** + * midori_web_view_get_proxy_menu_item: + * @web_view: a #MidoriWebView + * + * Retrieves a proxy menu item that is typically added to a Window menu + * and which on activation switches to the right window/ tab. + * + * The item is created on the first call and will be updated to reflect + * changes to the icon and title automatically. + * + * Note: The item is only valid as the web view is embedded in a #GtkNotebook. + * + * Return value: the proxy #GtkMenuItem or %NULL + **/ +GtkWidget* +midori_web_view_get_proxy_menu_item (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), FALSE); + + MidoriWebViewPrivate* priv = web_view->priv; + + if (!priv->proxy_menu_item) + { + const gchar* title = midori_web_view_get_display_title (web_view); + GtkWidget* menu_item = gtk_image_menu_item_new_with_label (title); + GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), icon); + + priv->proxy_menu_item = menu_item; + } + return priv->proxy_menu_item; +} + +/** + * midori_web_view_get_proxy_tab_icon: + * @web_view: a #MidoriWebView + * + * Retrieves a proxy tab icon that is typically used in a tab label. + * + * The icon is created on the first call and will be updated to reflect + * loading progress and changes of the actual icon. + * + * Note: If a proxy tab label has been created before, this represents + * the existing icon used in the label. + * + * Return value: the proxy #GtkImage + **/ +GtkWidget* +midori_web_view_get_proxy_tab_icon (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + MidoriWebViewPrivate* priv = web_view->priv; + + if (!priv->tab_icon) + { + priv->tab_icon = katze_throbber_new (); + if (priv->icon) + katze_throbber_set_static_pixbuf (KATZE_THROBBER(priv->tab_icon), + priv->icon); + else + katze_throbber_set_static_stock_id (KATZE_THROBBER(priv->tab_icon), + GTK_STOCK_FILE); + } + return priv->tab_icon; +} + +static gboolean +midori_web_view_tab_label_button_release_event (GtkWidget* tab_label, + GdkEventButton* event, + MidoriWebView* web_view) +{ + MidoriWebViewPrivate* priv = web_view->priv; + + if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) + { + // Toggle the label visibility on double click + GtkWidget* child = gtk_bin_get_child (GTK_BIN (tab_label)); + GList* children = gtk_container_get_children (GTK_CONTAINER (child)); + child = (GtkWidget*)g_list_nth_data (children, 1); + gboolean visible = gtk_widget_get_child_visible (GTK_WIDGET (child)); + gtk_widget_set_child_visible (GTK_WIDGET (child), !visible); + gint width, height; + sokoke_widget_get_text_size(tab_label, "M", &width, &height); + gtk_widget_set_size_request (child, !visible + ? width * priv->tab_label_size : 0, !visible ? -1 : 0); + g_list_free (children); + return TRUE; + } + else if (event->button == 2) + { + // Close the web view on middle click + g_signal_emit (web_view, signals[CLOSE], 0); + return TRUE; + } + + return FALSE; +} + +static void +midori_web_view_tab_close_style_set (GtkWidget* tab_close, + GtkStyle* previous_style, + MidoriWebView* web_view) +{ + GtkSettings* gtk_settings = gtk_widget_get_settings (tab_close); + gint width, height; + gtk_icon_size_lookup_for_settings (gtk_settings, GTK_ICON_SIZE_BUTTON, + &width, &height); + gtk_widget_set_size_request (tab_close, width + 2, height + 2); +} + +static void +midori_web_view_tab_close_clicked (GtkWidget* tab_close, + MidoriWebView* web_view) +{ + g_signal_emit (web_view, signals[CLOSE], 0); +} + +/** + * midori_web_view_get_proxy_tab_label: + * @web_view: a #MidoriWebView + * + * Retrieves a proxy tab label that is typically used as the label of + * a #GtkNotebook page. + * + * The label is created on the first call and will be updated to reflect + * changes to the icon and title automatically. + * + * The icon embedded in the label will reflect the loading status of the + * web view. + * + * Note: This fails if a proxy tab icon has been created already. + * + * Return value: the proxy #GtkEventBox + **/ +GtkWidget* +midori_web_view_get_proxy_tab_label (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + MidoriWebViewPrivate* priv = web_view->priv; + + GtkWidget* proxy_tab_icon = priv->tab_icon; + g_return_val_if_fail (!proxy_tab_icon, NULL); + + if (!priv->proxy_tab_label) + { + priv->tab_icon = midori_web_view_get_proxy_tab_icon (web_view); + + GtkWidget* event_box = gtk_event_box_new (); + gtk_event_box_set_visible_window(GTK_EVENT_BOX (event_box), FALSE); + GtkWidget* hbox = gtk_hbox_new (FALSE, 1); + gtk_container_add (GTK_CONTAINER (event_box), GTK_WIDGET (hbox)); + gtk_box_pack_start (GTK_BOX (hbox), priv->tab_icon, FALSE, FALSE, 0); + const gchar* title = midori_web_view_get_display_title (web_view); + priv->tab_label = gtk_label_new (title); + gtk_misc_set_alignment (GTK_MISC (priv->tab_label), 0.0, 0.5); + // TODO: make the tab initially look "unvisited" until it's focused + gtk_box_pack_start (GTK_BOX (hbox), priv->tab_label, FALSE, TRUE, 0); + priv->proxy_tab_label = event_box; + _midori_web_view_update_tab_label_size (web_view); + + GtkWidget* close_button = gtk_button_new (); + gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE); + gtk_button_set_focus_on_click (GTK_BUTTON (close_button), FALSE); + GtkRcStyle* rcstyle = gtk_rc_style_new (); + rcstyle->xthickness = rcstyle->ythickness = 0; + gtk_widget_modify_style(close_button, rcstyle); + GtkWidget* image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, + GTK_ICON_SIZE_MENU); + gtk_button_set_image (GTK_BUTTON(close_button), image); + gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0); + gtk_widget_show_all (GTK_WIDGET (event_box)); + if (!priv->close_button) + gtk_widget_hide (close_button); + priv->tab_close = close_button; + + g_signal_connect(priv->proxy_tab_label, "button-release-event", + G_CALLBACK(midori_web_view_tab_label_button_release_event), + web_view); + g_signal_connect(priv->tab_close, "style-set", + G_CALLBACK(midori_web_view_tab_close_style_set), + web_view); + g_signal_connect(priv->tab_close, "clicked", + G_CALLBACK(midori_web_view_tab_close_clicked), + web_view); + } + return priv->proxy_tab_label; +} + +/** + * midori_web_view_get_proxy_xbel_item: + * @web_view: a #MidoriWebView + * + * Retrieves a proxy xbel item that can be used for bookmark storage as + * well as session management. + * + * The item is created on the first call and will be updated to reflect + * changes to the title and href automatically. + * + * Note: Currently the item is always a bookmark, but this might change + * in the future. + * + * Return value: the proxy #KatzeXbelItem + **/ +KatzeXbelItem* +midori_web_view_get_proxy_xbel_item (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + MidoriWebViewPrivate* priv = web_view->priv; + + if (!priv->proxy_xbel_item) + { + priv->proxy_xbel_item = katze_xbel_bookmark_new (); + const gchar* uri = midori_web_view_get_display_uri (web_view); + katze_xbel_bookmark_set_href (priv->proxy_xbel_item, uri); + const gchar* title = midori_web_view_get_display_title (web_view); + katze_xbel_item_set_title (priv->proxy_xbel_item, title); + } + return priv->proxy_xbel_item; +} + +/** + * midori_web_view_is_loading: + * @web_view: a #MidoriWebView + * + * Determines whether currently a page is being loaded or not. + * + * Return value: %TRUE if a page is being loaded, %FALSE otherwise + **/ +gint +midori_web_view_is_loading (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), -1); + + MidoriWebViewPrivate* priv = web_view->priv; + return priv->is_loading; +} + +/** + * midori_web_view_get_progress: + * @web_view: a #MidoriWebView + * + * Retrieves the current loading progress in percent or -1 if no data + * has been loaded so far. + * + * The value is undefined if no loading is in progress. + * + * Return value: the current loading progress or -1 + **/ +gint +midori_web_view_get_progress (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), -1); + + MidoriWebViewPrivate* priv = web_view->priv; + return priv->progress; +} + +/** + * midori_web_view_get_display_uri: + * @web_view: a #MidoriWebView + * + * Retrieves a string that is suitable for displaying, particularly an + * empty URI is represented as "". + * + * You can assume that the string is not %NULL. + * + * Return value: an URI string + **/ +const gchar* +midori_web_view_get_display_uri (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), ""); + + MidoriWebViewPrivate* priv = web_view->priv; + return priv->uri ? priv->uri : ""; +} + +/** + * midori_web_view_get_display_title: + * @web_view: a #MidoriWebView + * + * Retrieves a string that is suitable for displaying as a title. Most of the + * time this will be the title or the current URI. + * + * You can assume that the string is not %NULL. + * + * Return value: a title string + **/ +const gchar* +midori_web_view_get_display_title (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), "about:blank"); + + MidoriWebViewPrivate* priv = web_view->priv; + + if (priv->title) + return priv->title; + if (priv->uri) + return priv->uri; + return "about:blank"; +} + +/** + * midori_web_view_get_link_uri: + * @web_view: a #MidoriWebView + * + * Retrieves the uri of the currently focused link, particularly while the + * mouse hovers a link or a context menu is being opened. + * + * Return value: an URI string, or %NULL if there is no link focussed + **/ +const gchar* +midori_web_view_get_link_uri (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + MidoriWebViewPrivate* priv = web_view->priv; + return priv->link_uri; +} + +/** + * midori_web_view_get_zoom_level: + * @web_view: a #MidoriWebView + * + * Retrieves the current zoom level. + * + * Return value: the zoom level, always 1 if not supported + **/ +gfloat +midori_web_view_get_zoom_level (MidoriWebView* web_view) +{ + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), 1); + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (web_view), + "zoom-level")) + { + gfloat zoom_level; + g_object_get (web_view, "zoom-level", &zoom_level, NULL); + return zoom_level; + } + return 1; +} diff --git a/midori/midori-webview.h b/midori/midori-webview.h new file mode 100644 index 00000000..71cab23f --- /dev/null +++ b/midori/midori-webview.h @@ -0,0 +1,121 @@ +/* + Copyright (C) 2008 Christian Dywan + + 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. +*/ + +#ifndef __MIDORI_WEB_VIEW_H__ +#define __MIDORI_WEB_VIEW_H__ + +#include + +#include +#include "midori-websettings.h" + +G_BEGIN_DECLS + +#define MIDORI_TYPE_WEB_VIEW \ + (midori_web_view_get_type ()) +#define MIDORI_WEB_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_VIEW, MidoriWebView)) +#define MIDORI_WEB_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_VIEW, MidoriWebViewClass)) +#define MIDORI_IS_WEB_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_VIEW)) +#define MIDORI_IS_WEB_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_VIEW)) +#define MIDORI_WEB_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_VIEW, MidoriWebViewClass)) + +typedef struct _MidoriWebView MidoriWebView; +typedef struct _MidoriWebViewPrivate MidoriWebViewPrivate; +typedef struct _MidoriWebViewClass MidoriWebViewClass; + +struct _MidoriWebView +{ + WebKitWebView parent_instance; + + MidoriWebViewPrivate* priv; +}; + +struct _MidoriWebViewClass +{ + WebKitWebViewClass parent_class; + + /* Signals */ + void + (*progress_started) (MidoriWebView* web_view, + guint progress); + void + (*progress_changed) (MidoriWebView* web_view, + guint progress); + void + (*progress_done) (MidoriWebView* web_view, + guint progress); + void + (*load_done) (MidoriWebView* web_view, + WebKitWebFrame* frame); + void + (*statusbar_text_changed) (MidoriWebView* web_view, + const gchar* text); + void + (*element_motion) (MidoriWebView* web_view, + const gchar* link_uri); + void + (*close) (MidoriWebView* web_view); + void + (*new_tab) (MidoriWebView* web_view, + const gchar* uri); + void + (*new_window) (MidoriWebView* web_view, + const gchar* uri); + void + (*create_web_view) (MidoriWebView* web_view, + MidoriWebView* new_web_view); +}; + +GType +midori_web_view_get_type (void); + +GtkWidget* +midori_web_view_new (void); + +void +midori_web_view_set_settings (MidoriWebView* web_view, + MidoriWebSettings* web_settings); + +GtkWidget* +midori_web_view_get_proxy_menu_item (MidoriWebView* web_view); + +GtkWidget* +midori_web_view_get_proxy_tab_label (MidoriWebView* web_view); + +KatzeXbelItem* +midori_web_view_get_proxy_xbel_item (MidoriWebView* web_view); + +gboolean +midori_web_view_is_loading (MidoriWebView* web_view); + +gint +midori_web_view_get_progress (MidoriWebView* web_view); + +const gchar* +midori_web_view_get_display_uri (MidoriWebView* web_view); + +const gchar* +midori_web_view_get_display_title (MidoriWebView* web_view); + +const gchar* +midori_web_view_get_link_uri (MidoriWebView* web_view); + +gfloat +midori_web_view_get_zoom_level (MidoriWebView* web_view); + +G_END_DECLS + +#endif /* __MIDORI_WEB_VIEW_H__ */ diff --git a/midori/search.c b/midori/search.c new file mode 100644 index 00000000..26afcb5e --- /dev/null +++ b/midori/search.c @@ -0,0 +1,199 @@ +/* + Copyright (C) 2007 Christian Dywan + + 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 "search.h" + +#include "sokoke.h" +#include + +#include +#include + +GList* search_engines_new(void) +{ + return NULL; +} + +void search_engines_free(GList* searchEngines) +{ + g_list_foreach(searchEngines, (GFunc)search_engine_free, NULL); + g_list_free(searchEngines); +} + +gboolean search_engines_from_file(GList** searchEngines, const gchar* filename + , GError** error) +{ + g_return_val_if_fail(!g_list_nth(*searchEngines, 0), FALSE); + GKeyFile* keyFile = g_key_file_new(); + g_key_file_load_from_file(keyFile, filename, G_KEY_FILE_KEEP_COMMENTS, error); + /*g_key_file_load_from_data_dirs(keyFile, sFilename, NULL + , G_KEY_FILE_KEEP_COMMENTS, error);*/ + gchar** engines = g_key_file_get_groups(keyFile, NULL); + guint i; + for(i = 0; engines[i] != NULL; i++) + { + SearchEngine* engine = search_engine_new(); + search_engine_set_short_name(engine, engines[i]); + engine->description = g_key_file_get_string(keyFile, engines[i], "description", NULL); + engine->url = g_key_file_get_string(keyFile, engines[i], "url", NULL); + engine->inputEncoding = g_key_file_get_string(keyFile, engines[i], "input-encoding", NULL); + engine->icon = g_key_file_get_string(keyFile, engines[i], "icon", NULL); + engine->keyword = g_key_file_get_string(keyFile, engines[i], "keyword", NULL); + *searchEngines = g_list_prepend(*searchEngines, engine); + } + *searchEngines = g_list_reverse(*searchEngines); + g_strfreev(engines); + g_key_file_free(keyFile); + return !(error && *error); +} + +static void key_file_set_string(GKeyFile* keyFile, const gchar* group + , const gchar* key, const gchar* string) +{ + g_return_if_fail(group); + if(string) + g_key_file_set_string(keyFile, group, key, string); +} + +gboolean search_engines_to_file(GList* searchEngines, const gchar* filename + , GError** error) +{ + GKeyFile* keyFile = g_key_file_new(); + guint n = g_list_length(searchEngines); + guint i; + for(i = 0; i < n; i++) + { + SearchEngine* engine = (SearchEngine*)g_list_nth_data(searchEngines, i); + const gchar* name = search_engine_get_short_name(engine); + key_file_set_string(keyFile, name, "description", engine->description); + key_file_set_string(keyFile, name, "url", engine->url); + key_file_set_string(keyFile, name, "input-encoding", engine->inputEncoding); + key_file_set_string(keyFile, name, "icon", engine->icon); + key_file_set_string(keyFile, name, "keyword", engine->keyword); + } + gboolean bSaved = sokoke_key_file_save_to_file(keyFile, filename, error); + g_key_file_free(keyFile); + + return bSaved; +} + +SearchEngine* search_engine_new() +{ + SearchEngine* engine = g_new0(SearchEngine, 1); + engine->shortName = g_strdup(""); + return engine; +} + +void search_engine_free(SearchEngine* engine) +{ + g_return_if_fail(engine); + g_free(engine->shortName); + g_free(engine->description); + g_free(engine->url); + g_free(engine->inputEncoding); + g_free(engine->icon); + g_free(engine->keyword); + g_free(engine); +} + +SearchEngine* search_engine_copy(SearchEngine* engine) +{ + g_return_val_if_fail(engine, NULL); + SearchEngine* copy = search_engine_new(); + search_engine_set_short_name(copy, engine->shortName); + search_engine_set_description(copy, engine->description); + search_engine_set_url(copy, engine->url); + search_engine_set_input_encoding(copy, engine->inputEncoding); + search_engine_set_icon(copy, engine->icon); + search_engine_set_keyword(copy, engine->keyword); + return engine; +} + +GType search_engine_get_type() +{ + static GType type = 0; + if(!type) + type = g_pointer_type_register_static("search_engine"); + return type; +} + +G_CONST_RETURN gchar* search_engine_get_short_name(SearchEngine* engine) +{ + g_return_val_if_fail(engine, NULL); + return engine->shortName; +} + +G_CONST_RETURN gchar* search_engine_get_description(SearchEngine* engine) +{ + g_return_val_if_fail(engine, NULL); + return engine->description; +} + +G_CONST_RETURN gchar* search_engine_get_url(SearchEngine* engine) +{ + g_return_val_if_fail(engine, NULL); + return engine->url; +} + +G_CONST_RETURN gchar* search_engine_get_input_encoding(SearchEngine* engine) +{ + g_return_val_if_fail(engine, NULL); + return engine->inputEncoding; +} + +G_CONST_RETURN gchar* search_engine_get_icon(SearchEngine* engine) +{ + g_return_val_if_fail(engine, NULL); + return engine->icon; +} + +G_CONST_RETURN gchar* search_engine_get_keyword(SearchEngine* engine) +{ + g_return_val_if_fail(engine, NULL); + return engine->keyword; +} + +void search_engine_set_short_name(SearchEngine* engine, const gchar* shortName) +{ + g_return_if_fail(engine); + g_return_if_fail(shortName); + katze_assign(engine->shortName, g_strdup(shortName)); +} + +void search_engine_set_description(SearchEngine* engine, const gchar* description) +{ + g_return_if_fail(engine); + katze_assign(engine->description, g_strdup(description)); +} + +void search_engine_set_url(SearchEngine* engine, const gchar* url) +{ + g_return_if_fail(engine); + katze_assign(engine->url, g_strdup(url)); +} + +void search_engine_set_input_encoding(SearchEngine* engine, const gchar* inputEncoding) +{ + g_return_if_fail(engine); + katze_assign(engine->inputEncoding, g_strdup(inputEncoding)); +} + +void search_engine_set_icon(SearchEngine* engine, const gchar* icon) +{ + g_return_if_fail(engine); + katze_assign(engine->icon, g_strdup(icon)); +} + +void search_engine_set_keyword(SearchEngine* engine, const gchar* keyword) +{ + g_return_if_fail(engine); + katze_assign(engine->keyword, g_strdup(keyword)); +} diff --git a/midori/search.h b/midori/search.h new file mode 100644 index 00000000..c8aa7093 --- /dev/null +++ b/midori/search.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2007 Christian Dywan + + 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. +*/ + +#ifndef __SEARCH_H__ +#define __SEARCH_H__ 1 + +#include +#include + +// Note: This structure is entirely private. +typedef struct +{ + gchar* shortName; + gchar* description; + gchar* url; + gchar* inputEncoding; + gchar* icon; + gchar* keyword; +} SearchEngine; + +GList* +search_engines_new(void); + +void +search_engines_free(GList*); + +gboolean +search_engines_from_file(GList**, const gchar*, GError**); + +gboolean +search_engines_to_file(GList*, const gchar*, GError**); + +SearchEngine* +search_engine_new(void); + +void +search_engine_free(SearchEngine*); + +SearchEngine* +search_engine_copy(SearchEngine*); + +GType +search_engine_get_type(); + +#define G_TYPE_SEARCH_ENGINE search_engine_get_type() + +G_CONST_RETURN gchar* +search_engine_get_short_name(SearchEngine*); + +G_CONST_RETURN gchar* +search_engine_get_description(SearchEngine*); + +G_CONST_RETURN gchar* +search_engine_get_url(SearchEngine*); + +G_CONST_RETURN gchar* +search_engine_get_input_encoding(SearchEngine*); + +G_CONST_RETURN gchar* +search_engine_get_icon(SearchEngine*); + +G_CONST_RETURN gchar* +search_engine_get_keyword(SearchEngine*); + +void +search_engine_set_short_name(SearchEngine*, const gchar*); + +void +search_engine_set_description(SearchEngine*, const gchar*); + +void +search_engine_set_url(SearchEngine*, const gchar*); + +void +search_engine_set_input_encoding(SearchEngine*, const gchar*); + +void +search_engine_set_icon(SearchEngine*, const gchar*); + +void +search_engine_set_keyword(SearchEngine*, const gchar*); + +#endif /* !__SEARCH_H__ */ diff --git a/midori/sokoke.c b/midori/sokoke.c new file mode 100644 index 00000000..157252d5 --- /dev/null +++ b/midori/sokoke.c @@ -0,0 +1,498 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + 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 "sokoke.h" + +#include "search.h" + +#include "config.h" +#include "main.h" + +#ifdef HAVE_UNISTD_H + #include +#endif +#include +#include +#include +#include + +gchar* +sokoke_magic_uri (const gchar* uri, const gchar* default_search_uri) +{ + // Add file:// if we have a local path + if (g_path_is_absolute (uri)) + return g_strconcat ("file://", uri, NULL); + // Construct an absolute path if the file is relative + if (g_file_test (uri, G_FILE_TEST_EXISTS) && g_file_test (uri, G_FILE_TEST_IS_REGULAR)) + { + gchar* current_dir = g_get_current_dir (); + gchar* result = g_strconcat ("file://", current_dir, G_DIR_SEPARATOR_S, uri, NULL); + g_free (current_dir); + return result; + } + // Do we need to add a protocol? + if (!strstr (uri, "://")) + { + // Do we have a domain, ip address or localhost? + if (strchr (uri, '.') != NULL || !strcmp (uri, "localhost")) + return g_strconcat ("http://", uri, NULL); + // We don't want to search? So return early. + if (!default_search_uri) + return g_strdup (uri); + gchar* search; + const gchar* search_uri = NULL; + // Do we have a keyword and a string? + gchar** parts = g_strsplit (uri, " ", 2); + if (parts[0] && parts[1]) + { + guint n = g_list_length (searchEngines); + guint i; + for (i = 0; i < n; i++) + { + SearchEngine* search_engine = (SearchEngine*)g_list_nth_data ( + searchEngines, i); + if (!strcmp (search_engine_get_keyword (search_engine), + parts[0])) + search_uri = search_engine->url; + } + if (search_uri) + search = g_strdup_printf (search_uri, parts[1]); + } + // We only have a word or there is no matching keyword, so search for it + if (!search_uri) + search = g_strdup_printf (default_search_uri, uri); + return search; + } + return g_strdup (uri); +} + +void +sokoke_entry_setup_completion (GtkEntry* entry) +{ + /* TODO: The current behavior works only with the beginning of strings + But we want to match "localhost" with "loc" and "hos" */ + GtkEntryCompletion* completion = gtk_entry_completion_new (); + gtk_entry_completion_set_model (completion, + GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING))); + gtk_entry_completion_set_text_column (completion, 0); + gtk_entry_completion_set_minimum_key_length (completion, 3); + gtk_entry_set_completion (entry, completion); + gtk_entry_completion_set_popup_completion (completion, FALSE); //... +} + +void +sokoke_entry_append_completion (GtkEntry* entry, const gchar* text) +{ + GtkEntryCompletion* completion = gtk_entry_get_completion (entry); + GtkTreeModel* completion_store = gtk_entry_completion_get_model (completion); + GtkTreeIter iter; + gtk_list_store_insert (GTK_LIST_STORE (completion_store), &iter, 0); + gtk_list_store_set (GTK_LIST_STORE (completion_store), &iter, 0, text, -1); +} + +void +sokoke_combo_box_add_strings (GtkComboBox* combobox, + const gchar* label_first, ...) +{ + // Add a number of strings to a combobox, terminated with NULL + // This works only for text comboboxes + va_list args; + va_start (args, label_first); + + const gchar* label; + for (label = label_first; label; label = va_arg (args, const gchar*)) + gtk_combo_box_append_text (combobox, label); + + va_end (args); +} + +void sokoke_widget_set_visible (GtkWidget* widget, gboolean visible) +{ + // Show or hide the widget + if (visible) + gtk_widget_show (widget); + else + gtk_widget_hide (widget); +} + +void +sokoke_container_show_children (GtkContainer* container) +{ + // Show every child but not the container itself + gtk_container_foreach (container, (GtkCallback)(gtk_widget_show_all), NULL); +} + +void +sokoke_widget_set_tooltip_text (GtkWidget* widget, const gchar* text) +{ + #if GTK_CHECK_VERSION(2, 12, 0) + gtk_widget_set_tooltip_text (widget, text); + #else + static GtkTooltips* tooltips; + if (!tooltips) + tooltips = gtk_tooltips_new (); + gtk_tooltips_set_tip (tooltips, widget, text, NULL); + #endif +} + +void +sokoke_tool_item_set_tooltip_text (GtkToolItem* toolitem, const gchar* text) +{ + if (text && *text) + { + #if GTK_CHECK_VERSION(2, 12, 0) + gtk_tool_item_set_tooltip_text (toolitem, text); + #else + static GtkTooltips* tooltips = NULL; + if (G_UNLIKELY (!tooltips)) + tooltips = gtk_tooltips_new(); + + gtk_tool_item_set_tooltip (toolitem, tooltips, text, NULL); + #endif + } +} + +typedef struct +{ + GtkWidget* widget; + SokokeMenuPos position; +} SokokePopupInfo; + +static void +sokoke_widget_popup_position_menu (GtkMenu* menu, + gint* x, + gint* y, + gboolean* push_in, + gpointer user_data) +{ + gint wx, wy; + gint menu_width; + GtkRequisition menu_req; + GtkRequisition widget_req; + SokokePopupInfo* info = user_data; + GtkWidget* widget = info->widget; + + // Retrieve size and position of both widget and menu + if (GTK_WIDGET_NO_WINDOW (widget)) + { + gdk_window_get_position (widget->window, &wx, &wy); + wx += widget->allocation.x; + wy += widget->allocation.y; + } + else + gdk_window_get_origin (widget->window, &wx, &wy); + gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); + gtk_widget_size_request (widget, &widget_req); + menu_width = menu_req.width; + gint widget_height = widget_req.height; // Better than allocation.height + + // Calculate menu position + if (info->position == SOKOKE_MENU_POSITION_CURSOR) + ; // Do nothing? + else if (info->position == SOKOKE_MENU_POSITION_RIGHT) + { + *x = wx + widget->allocation.width - menu_width; + *y = wy + widget_height; + } else if (info->position == SOKOKE_MENU_POSITION_LEFT) + { + *x = wx; + *y = wy + widget_height; + } + + *push_in = TRUE; +} + + +void +sokoke_widget_popup (GtkWidget* widget, + GtkMenu* menu, + GdkEventButton* event, + SokokeMenuPos pos) +{ + int button, event_time; + if (event) + { + button = event->button; + event_time = event->time; + } + else + { + button = 0; + event_time = gtk_get_current_event_time (); + } + + if (!gtk_menu_get_attach_widget(menu)) + gtk_menu_attach_to_widget (menu, widget, NULL); + + if (widget) + { + SokokePopupInfo info = { widget, pos }; + gtk_menu_popup (menu, NULL, NULL, + sokoke_widget_popup_position_menu, &info, + button, event_time); + } + else + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, event_time); +} + +typedef enum +{ + SOKOKE_DESKTOP_UNTESTED, + SOKOKE_DESKTOP_XFCE, + SOKOKE_DESKTOP_UNKNOWN +} SokokeDesktop; + +static SokokeDesktop +sokoke_get_desktop (void) +{ + static SokokeDesktop desktop = SOKOKE_DESKTOP_UNTESTED; + if (G_UNLIKELY (desktop == SOKOKE_DESKTOP_UNTESTED)) + { + // Are we running in Xfce? + gint result; gchar* out; gchar* err; + gboolean success = g_spawn_command_line_sync ( + "xprop -root _DT_SAVE_MODE | grep -q xfce4", + &out, &err, &result, NULL); + if (success && !result) + desktop = SOKOKE_DESKTOP_XFCE; + else + desktop = SOKOKE_DESKTOP_UNKNOWN; + } + + return desktop; +} + +GtkWidget* +sokoke_xfce_header_new (const gchar* icon, + const gchar* title) +{ + // Create an xfce header with icon and title + // This returns NULL if the desktop is not xfce + if (sokoke_get_desktop () == SOKOKE_DESKTOP_XFCE) + { + GtkWidget* entry = gtk_entry_new (); + gchar* markup; + GtkWidget* xfce_heading = gtk_event_box_new (); + gtk_widget_modify_bg (xfce_heading, GTK_STATE_NORMAL, + &entry->style->base[GTK_STATE_NORMAL]); + GtkWidget* hbox = gtk_hbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); + GtkWidget* image = gtk_image_new_from_icon_name (icon, + GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); + GtkWidget* label = gtk_label_new (NULL); + gtk_widget_modify_fg (label, GTK_STATE_NORMAL + , &entry->style->text[GTK_STATE_NORMAL]); + markup = g_strdup_printf ("%s", + title); + gtk_label_set_markup (GTK_LABEL (label), markup); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_container_add (GTK_CONTAINER (xfce_heading), hbox); + g_free (markup); + return xfce_heading; + } + return NULL; +} + +GtkWidget* +sokoke_superuser_warning_new (void) +{ + // Create a horizontal bar with a security warning + // This returns NULL if the user is no superuser + #ifdef HAVE_UNISTD_H + if (G_UNLIKELY (!geteuid ())) // effective superuser? + { + GtkWidget* hbox = gtk_event_box_new (); + gtk_widget_modify_bg (hbox, GTK_STATE_NORMAL, + &hbox->style->bg[GTK_STATE_SELECTED]); + GtkWidget* label = gtk_label_new ( + _("Warning: You are using a superuser account!")); + gtk_misc_set_padding (GTK_MISC (label), 0, 2); + gtk_widget_modify_fg (GTK_WIDGET (label), GTK_STATE_NORMAL, + >K_WIDGET (label)->style->fg[GTK_STATE_SELECTED]); + gtk_widget_show (label); + gtk_container_add (GTK_CONTAINER(hbox), GTK_WIDGET (label)); + gtk_widget_show (hbox); + return hbox; + } + #endif + return NULL; +} + +GtkWidget* +sokoke_hig_frame_new (const gchar* title) +{ + // Create a frame with no actual frame but a bold label and indentation + GtkWidget* frame = gtk_frame_new (NULL); + gchar* title_bold = g_strdup_printf ("%s", title); + GtkWidget* label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), title_bold); + g_free (title_bold); + gtk_frame_set_label_widget (GTK_FRAME (frame), label); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE); + return frame; +} + +void +sokoke_widget_set_pango_font_style (GtkWidget* widget, + PangoStyle style) +{ + // Conveniently change the pango font style + // For some reason we need to reset if we actually want the normal style + if (style == PANGO_STYLE_NORMAL) + gtk_widget_modify_font (widget, NULL); + else + { + PangoFontDescription* font_description = pango_font_description_new (); + pango_font_description_set_style (font_description, PANGO_STYLE_ITALIC); + gtk_widget_modify_font (widget, font_description); + pango_font_description_free (font_description); + } +} + +static gboolean +sokoke_on_entry_focus_in_event (GtkEntry* entry, + GdkEventFocus* event, + gpointer userdata) +{ + gint default_text = GPOINTER_TO_INT ( + g_object_get_data (G_OBJECT (entry), "sokoke_has_default")); + if (default_text) + { + gtk_entry_set_text (entry, ""); + g_object_set_data (G_OBJECT(entry), "sokoke_has_default", + GINT_TO_POINTER (0)); + sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), + PANGO_STYLE_NORMAL); + } + return FALSE; +} + +static gboolean +sokoke_on_entry_focus_out_event (GtkEntry* entry, + GdkEventFocus* event, + gpointer userdata) +{ + const gchar* text = gtk_entry_get_text (entry); + if (text && !*text) + { + const gchar* defaultText = (const gchar*)g_object_get_data ( + G_OBJECT (entry), "sokoke_default_text"); + gtk_entry_set_text (entry, defaultText); + g_object_set_data (G_OBJECT(entry), + "sokoke_has_default", GINT_TO_POINTER (1)); + sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), + PANGO_STYLE_ITALIC); + } + return FALSE; +} + +void +sokoke_entry_set_default_text (GtkEntry* entry, + const gchar* default_text) +{ + // Note: The default text initially overwrites any previous text + gchar* old_value = g_object_get_data (G_OBJECT (entry), + "sokoke_default_text"); + if (!old_value) + { + g_object_set_data (G_OBJECT (entry), "sokoke_has_default", + GINT_TO_POINTER (1)); + sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), + PANGO_STYLE_ITALIC); + gtk_entry_set_text (entry, default_text); + } + g_object_set_data (G_OBJECT (entry), "sokoke_default_text", + (gpointer)default_text); + g_signal_connect (entry, "focus-in-event", + G_CALLBACK (sokoke_on_entry_focus_in_event), NULL); + g_signal_connect (entry, "focus-out-event", + G_CALLBACK (sokoke_on_entry_focus_out_event), NULL); +} + +gchar* +sokoke_key_file_get_string_default (GKeyFile* key_file, + const gchar* group, + const gchar* key, + const gchar* default_value, + GError** error) +{ + gchar* value = g_key_file_get_string (key_file, group, key, error); + return value == NULL ? g_strdup (default_value) : value; +} + +gint +sokoke_key_file_get_integer_default (GKeyFile* key_file, + const gchar* group, + const gchar* key, + const gint default_value, + GError** error) +{ + if (!g_key_file_has_key (key_file, group, key, NULL)) + return default_value; + return g_key_file_get_integer (key_file, group, key, error); +} + +gdouble +sokoke_key_file_get_double_default (GKeyFile* key_file, + const gchar* group, + const gchar* key, + const gdouble default_value, + GError** error) +{ + if (!g_key_file_has_key (key_file, group, key, NULL)) + return default_value; + return g_key_file_get_double (key_file, group, key, error); +} + +gboolean +sokoke_key_file_get_boolean_default (GKeyFile* key_file, + const gchar* group, + const gchar* key, + const gboolean default_value, + GError** error) +{ + if (!g_key_file_has_key (key_file, group, key, NULL)) + return default_value; + return g_key_file_get_boolean (key_file, group, key, error); +} + +gboolean +sokoke_key_file_save_to_file (GKeyFile* key_file, + const gchar* filename, + GError** error) +{ + gchar* data = g_key_file_to_data (key_file, NULL, error); + if (!data) + return FALSE; + FILE* fp; + if (!(fp = fopen (filename, "w"))) + { + *error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_ACCES, + _("Writing failed.")); + return FALSE; + } + fputs (data, fp); + fclose (fp); + g_free (data); + return TRUE; +} + +void +sokoke_widget_get_text_size (GtkWidget* widget, + const gchar* text, + gint* width, + gint* height) +{ + PangoLayout* layout = gtk_widget_create_pango_layout (widget, text); + pango_layout_get_pixel_size (layout, width, height); + g_object_unref (layout); +} diff --git a/midori/sokoke.h b/midori/sokoke.h new file mode 100644 index 00000000..89e3ba2e --- /dev/null +++ b/midori/sokoke.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + 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. +*/ + +#ifndef __SOKOKE_H__ +#define __SOKOKE_H__ 1 + +#include + +// Many themes need this hack for small toolbars to work +#define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON + +gchar* +sokoke_magic_uri (const gchar* uri, + const gchar* search); + +void +sokoke_entry_setup_completion (GtkEntry* entry); + +void +sokoke_entry_append_completion (GtkEntry* entry, + const gchar* text); + +typedef enum { + SOKOKE_MENU_POSITION_CURSOR = 0, + SOKOKE_MENU_POSITION_LEFT, + SOKOKE_MENU_POSITION_RIGHT +} SokokeMenuPos; + +void +sokoke_combo_box_add_strings (GtkComboBox* combobox, + const gchar* label_first, ...); + +void +sokoke_widget_set_visible (GtkWidget* widget, + gboolean visible); + +void +sokoke_container_show_children (GtkContainer* container); + +void +sokoke_widget_set_tooltip_text (GtkWidget* widget, + const gchar* text); + +void +sokoke_tool_item_set_tooltip_text (GtkToolItem* toolitem, + const gchar* text); + +void +sokoke_widget_popup (GtkWidget* widget, + GtkMenu* menu, + GdkEventButton* event, + SokokeMenuPos pos); + +GtkWidget* +sokoke_xfce_header_new (const gchar* icon, + const gchar* title); + +GtkWidget* +sokoke_superuser_warning_new (void); + +GtkWidget* +sokoke_hig_frame_new (const gchar* title); + +void +sokoke_widget_set_pango_font_style (GtkWidget* widget, + PangoStyle style); + +void +sokoke_entry_set_default_text(GtkEntry*, const gchar*); + +gchar* +sokoke_key_file_get_string_default (GKeyFile* key_file, + const gchar* group, + const gchar* key, + const gchar* default_value, + GError** error); + +gint +sokoke_key_file_get_integer_default (GKeyFile* key_file, + const gchar* group, + const gchar* key, + const gint default_value, + GError** error); + +gdouble +sokoke_key_file_get_double_default (GKeyFile* key_file, + const gchar* group, + const gchar* key, + gdouble default_value, + GError** error); + +gboolean +sokoke_key_file_get_boolean_default (GKeyFile* key_file, + const gchar* group, + const gchar* key, + gboolean default_value, + GError** error); + +gboolean +sokoke_key_file_save_to_file (GKeyFile* key_file, + const gchar* filename, + GError** error); + +void +sokoke_widget_get_text_size (GtkWidget* widget, + const gchar* text, + gint* width, + gint* height); + +#endif /* !__SOKOKE_H__ */ diff --git a/midori/webSearch.c b/midori/webSearch.c new file mode 100644 index 00000000..000c66ed --- /dev/null +++ b/midori/webSearch.c @@ -0,0 +1,477 @@ +/* + Copyright (C) 2007 Christian Dywan + + 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 "webSearch.h" + +#include "search.h" + +#include "main.h" +#include "sokoke.h" + +#include +#include +#include + +static GdkPixbuf* +load_web_icon (const gchar* icon, GtkIconSize size, GtkWidget* widget) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + GdkPixbuf* pixbuf = NULL; + if (icon && *icon) + { + // TODO: We want to allow http as well, maybe also base64? + const gchar* icon_ready = g_str_has_prefix (icon, "file://") + ? &icon[7] : icon; + GtkStockItem stock_id; + if (gtk_stock_lookup (icon, &stock_id)) + pixbuf = gtk_widget_render_icon (widget, icon_ready, size, NULL); + else + { + gint width, height; + gtk_icon_size_lookup (size, &width, &height); + if (gtk_widget_has_screen (widget)) + { + GdkScreen* screen = gtk_widget_get_screen (widget); + pixbuf = gtk_icon_theme_load_icon ( + gtk_icon_theme_get_for_screen (screen), icon, + MAX (width, height), GTK_ICON_LOOKUP_USE_BUILTIN, NULL); + } + } + if (!pixbuf) + pixbuf = gdk_pixbuf_new_from_file_at_size (icon_ready, 16, 16, NULL); + } + if (!pixbuf) + pixbuf = gtk_widget_render_icon (widget, GTK_STOCK_FIND, size, NULL); + return pixbuf; +} + +void update_searchEngine(guint index, GtkWidget* search) +{ + guint n = g_list_length(searchEngines); + // Display a default icon in case we have no engines + if(!n) + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(search), SEXY_ICON_ENTRY_PRIMARY + , GTK_IMAGE(gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU))); + // Change the icon and default text according to the chosen engine + else + { + // Reset in case the index is out of range + if(index >= n) + index = 0; + SearchEngine* engine = (SearchEngine*)g_list_nth_data(searchEngines, index); + GdkPixbuf* pixbuf = load_web_icon(search_engine_get_icon(engine) + , GTK_ICON_SIZE_MENU, search); + sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(search) + , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(gtk_image_new_from_pixbuf(pixbuf))); + g_object_unref(pixbuf); + sokoke_entry_set_default_text(GTK_ENTRY(search) + , search_engine_get_short_name(engine)); + // config->searchEngine = index; + } +} + +void on_webSearch_engine_activate(GtkWidget* widget, MidoriBrowser* browser) +{ + guint index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(widget), "engine")); + update_searchEngine(index, widget); +} + +void on_webSearch_icon_released(GtkWidget* widget, SexyIconEntryPosition* pos + , gint button, MidoriBrowser* browser) +{ + GtkWidget* menu = gtk_menu_new(); + guint n = g_list_length(searchEngines); + GtkWidget* menuitem; + if(n) + { + guint i; + for(i = 0; i < n; i++) + { + SearchEngine* engine = (SearchEngine*)g_list_nth_data(searchEngines, i); + menuitem = gtk_image_menu_item_new_with_label( + search_engine_get_short_name(engine)); + GdkPixbuf* pixbuf = load_web_icon(search_engine_get_icon(engine) + , GTK_ICON_SIZE_MENU, menuitem); + GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), icon); + g_object_unref(pixbuf); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + g_object_set_data(G_OBJECT(menuitem), "engine", GUINT_TO_POINTER(i)); + g_signal_connect(menuitem, "activate" + , G_CALLBACK(on_webSearch_engine_activate), browser); + gtk_widget_show(menuitem); + } + } + else + { + menuitem = gtk_image_menu_item_new_with_label(_("Empty")); + gtk_widget_set_sensitive(menuitem, FALSE); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + gtk_widget_show(menuitem); + } + + /*menuitem = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + gtk_widget_show(menuitem); + GtkAction* action = gtk_action_group_get_action( + browser->actiongroup, "ManageSearchEngines"); + menuitem = gtk_action_create_menu_item(action); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + gtk_widget_show(menuitem);*/ + sokoke_widget_popup(widget, GTK_MENU(menu), + NULL, SOKOKE_MENU_POSITION_LEFT); +} + +static void on_webSearch_engines_render_icon(GtkTreeViewColumn* column + , GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter + , GtkWidget* treeview) +{ + SearchEngine* searchEngine; + gtk_tree_model_get(model, iter, ENGINES_COL_ENGINE, &searchEngine, -1); + + // TODO: Would it be better to not do this on every redraw? + const gchar* icon = search_engine_get_icon(searchEngine); + if(icon) + { + GdkPixbuf* pixbuf = load_web_icon(icon, GTK_ICON_SIZE_DND, treeview); + g_object_set(renderer, "pixbuf", pixbuf, NULL); + if(pixbuf) + g_object_unref(pixbuf); + } + else + g_object_set(renderer, "pixbuf", NULL, NULL); +} + +static void on_webSearch_engines_render_text(GtkTreeViewColumn* column + , GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter + , GtkWidget* treeview) +{ + SearchEngine* searchEngine; + gtk_tree_model_get(model, iter, ENGINES_COL_ENGINE, &searchEngine, -1); + const gchar* name = search_engine_get_short_name(searchEngine); + const gchar* description = search_engine_get_description(searchEngine); + gchar* markup = g_markup_printf_escaped("%s\n%s", name, description); + g_object_set(renderer, "markup", markup, NULL); + g_free(markup); +} + +static void webSearch_toggle_edit_buttons(gboolean sensitive, CWebSearch* webSearch) +{ + gtk_widget_set_sensitive(webSearch->edit, sensitive); + gtk_widget_set_sensitive(webSearch->remove, sensitive); +} + +static void on_webSearch_shortName_changed(GtkWidget* widget, GtkWidget* dialog) +{ + const gchar* text = gtk_entry_get_text(GTK_ENTRY(widget)); + gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog) + , GTK_RESPONSE_ACCEPT, text && *text); +} + +const gchar* STR_NON_NULL(const gchar* string) +{ + return string ? string : ""; +} + +static void webSearch_editEngine_dialog_new(gboolean newEngine, CWebSearch* webSearch) +{ + GtkWidget* dialog = gtk_dialog_new_with_buttons( + newEngine ? _("Add search engine") : _("Edit search engine") + , GTK_WINDOW(webSearch->window) + , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR + , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL + , newEngine ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT + , NULL); + gtk_window_set_icon_name(GTK_WINDOW(dialog) + , newEngine ? GTK_STOCK_ADD : GTK_STOCK_REMOVE); + gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); + gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 5); + GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + + SearchEngine* searchEngine; + GtkTreeModel* liststore; + GtkTreeIter iter; + if(newEngine) + { + searchEngine = search_engine_new(); + gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog) + , GTK_RESPONSE_ACCEPT, FALSE); + } + else + { + GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(webSearch->treeview)); + gtk_tree_selection_get_selected(selection, &liststore, &iter); + gtk_tree_model_get(liststore, &iter, ENGINES_COL_ENGINE, &searchEngine, -1); + } + + GtkWidget* hbox = gtk_hbox_new(FALSE, 8); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + GtkWidget* label = gtk_label_new_with_mnemonic(_("_Name:")); + gtk_size_group_add_widget(sizegroup, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_shortName = gtk_entry_new(); + g_signal_connect(entry_shortName, "changed" + , G_CALLBACK(on_webSearch_shortName_changed), dialog); + gtk_entry_set_activates_default(GTK_ENTRY(entry_shortName), TRUE); + if(!newEngine) + gtk_entry_set_text(GTK_ENTRY(entry_shortName) + , search_engine_get_short_name(searchEngine)); + gtk_box_pack_start(GTK_BOX(hbox), entry_shortName, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_widget_show_all(hbox); + + hbox = gtk_hbox_new(FALSE, 8); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + label = gtk_label_new_with_mnemonic(_("_Description:")); + gtk_size_group_add_widget(sizegroup, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_description = gtk_entry_new(); + gtk_entry_set_activates_default(GTK_ENTRY(entry_description), TRUE); + if(!newEngine) + gtk_entry_set_text(GTK_ENTRY(entry_description) + , STR_NON_NULL(search_engine_get_description(searchEngine))); + gtk_box_pack_start(GTK_BOX(hbox), entry_description, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_widget_show_all(hbox); + + hbox = gtk_hbox_new(FALSE, 8); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + label = gtk_label_new_with_mnemonic(_("_URL:")); + gtk_size_group_add_widget(sizegroup, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_url = gtk_entry_new(); + gtk_entry_set_activates_default(GTK_ENTRY(entry_url), TRUE); + if(!newEngine) + gtk_entry_set_text(GTK_ENTRY(entry_url) + , STR_NON_NULL(search_engine_get_url(searchEngine))); + gtk_box_pack_start(GTK_BOX(hbox), entry_url, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_widget_show_all(hbox); + + hbox = gtk_hbox_new(FALSE, 8); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + label = gtk_label_new_with_mnemonic(_("_Icon (name or file):")); + gtk_size_group_add_widget(sizegroup, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_icon = gtk_entry_new(); + gtk_entry_set_activates_default(GTK_ENTRY(entry_icon), TRUE); + if(!newEngine) + gtk_entry_set_text(GTK_ENTRY(entry_icon) + , STR_NON_NULL(search_engine_get_icon(searchEngine))); + gtk_box_pack_start(GTK_BOX(hbox), entry_icon, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_widget_show_all(hbox); + + hbox = gtk_hbox_new(FALSE, 8); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + label = gtk_label_new_with_mnemonic(_("_Keyword:")); + gtk_size_group_add_widget(sizegroup, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + GtkWidget* entry_keyword = gtk_entry_new(); + gtk_entry_set_activates_default(GTK_ENTRY(entry_keyword), TRUE); + if(!newEngine) + gtk_entry_set_text(GTK_ENTRY(entry_keyword) + , STR_NON_NULL(search_engine_get_keyword(searchEngine))); + gtk_box_pack_start(GTK_BOX(hbox), entry_keyword, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_widget_show_all(hbox); + + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + search_engine_set_short_name(searchEngine + , gtk_entry_get_text(GTK_ENTRY(entry_shortName))); + search_engine_set_description(searchEngine + , gtk_entry_get_text(GTK_ENTRY(entry_description))); + search_engine_set_url(searchEngine + , gtk_entry_get_text(GTK_ENTRY(entry_url))); + /*search_engine_set_input_encoding(searchEngine + , gtk_entry_get_text(GTK_ENTRY(entry_inputEncoding)));*/ + search_engine_set_icon(searchEngine + , gtk_entry_get_text(GTK_ENTRY(entry_icon))); + search_engine_set_keyword(searchEngine + , gtk_entry_get_text(GTK_ENTRY(entry_keyword))); + + if(newEngine) + { + searchEngines = g_list_append(searchEngines, searchEngine); + liststore = gtk_tree_view_get_model(GTK_TREE_VIEW(webSearch->treeview)); + gtk_list_store_append(GTK_LIST_STORE(liststore), &iter); + } + gtk_list_store_set(GTK_LIST_STORE(liststore), &iter + , ENGINES_COL_ENGINE, searchEngine, -1); + webSearch_toggle_edit_buttons(TRUE, webSearch); + } + gtk_widget_destroy(dialog); +} + +static void on_webSearch_add(GtkWidget* widget, CWebSearch* webSearch) +{ + webSearch_editEngine_dialog_new(TRUE, webSearch); +} + +static void on_webSearch_edit(GtkWidget* widget, CWebSearch* webSearch) +{ + webSearch_editEngine_dialog_new(FALSE, webSearch); +} + +static void on_webSearch_remove(GtkWidget* widget, CWebSearch* webSearch) +{ + GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(webSearch->treeview)); + GtkTreeModel* liststore; + GtkTreeIter iter; + gtk_tree_selection_get_selected(selection, &liststore, &iter); + SearchEngine* searchEngine; + gtk_tree_model_get(liststore, &iter, ENGINES_COL_ENGINE, &searchEngine, -1); + gtk_list_store_remove(GTK_LIST_STORE(liststore), &iter); + search_engine_free(searchEngine); + searchEngines = g_list_remove(searchEngines, searchEngine); + //update_searchEngine(config->searchEngine, webSearch->browser); + webSearch_toggle_edit_buttons(g_list_nth(searchEngines, 0) != NULL, webSearch); + // FIXME: we want to allow undo of some kind +} + +GtkWidget* webSearch_manageSearchEngines_dialog_new(MidoriBrowser* browser) +{ + const gchar* dialogTitle = _("Manage search engines"); + GtkWidget* dialog = gtk_dialog_new_with_buttons(dialogTitle + , GTK_WINDOW(browser) + , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR + , GTK_STOCK_HELP + , GTK_RESPONSE_HELP + , GTK_STOCK_CLOSE + , GTK_RESPONSE_CLOSE + , NULL); + gtk_window_set_icon_name(GTK_WINDOW(dialog), GTK_STOCK_PROPERTIES); + // TODO: Implement some kind of help function + gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog) + , GTK_RESPONSE_HELP, FALSE); //... + gint iWidth, iHeight; + sokoke_widget_get_text_size(dialog, "M", &iWidth, &iHeight); + gtk_window_set_default_size(GTK_WINDOW(dialog), iWidth * 45, -1); + g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog); + // TODO: Do we want tooltips for explainations or can we omit that? + // TODO: We need mnemonics + // TODO: Take multiple windows into account when applying changes + GtkWidget* xfce_heading; + if((xfce_heading = sokoke_xfce_header_new( + gtk_window_get_icon_name(GTK_WINDOW(dialog)), dialogTitle))) + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), xfce_heading, FALSE, FALSE, 0); + GtkWidget* hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 12); + GtkTreeViewColumn* column; + GtkCellRenderer* renderer_text; GtkCellRenderer* renderer_pixbuf; + GtkListStore* liststore = gtk_list_store_new(ENGINES_COL_N + , G_TYPE_SEARCH_ENGINE); + GtkWidget* treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); + column = gtk_tree_view_column_new(); + renderer_pixbuf = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(column, renderer_pixbuf, FALSE); + gtk_tree_view_column_set_cell_data_func(column, renderer_pixbuf + , (GtkTreeCellDataFunc)on_webSearch_engines_render_icon, treeview, NULL); + renderer_text = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(column, renderer_text, TRUE); + gtk_tree_view_column_set_cell_data_func(column, renderer_text + , (GtkTreeCellDataFunc)on_webSearch_engines_render_text, treeview, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled) + , GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(scrolled), treeview); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); + gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 5); + guint n = g_list_length(searchEngines); + guint i; + for(i = 0; i < n; i++) + { + SearchEngine* searchEngine = (SearchEngine*)g_list_nth_data(searchEngines, i); + gtk_list_store_insert_with_values(GTK_LIST_STORE(liststore), NULL, i + , ENGINES_COL_ENGINE, searchEngine, -1); + } + g_object_unref(liststore); + CWebSearch* webSearch = g_new0(CWebSearch, 1); + webSearch->browser = browser; + webSearch->window = dialog; + webSearch->treeview = treeview; + g_signal_connect(dialog, "response", G_CALLBACK(g_free), webSearch); + GtkWidget* vbox = gtk_vbox_new(FALSE, 4); + gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); + GtkWidget* button = gtk_button_new_from_stock(GTK_STOCK_ADD); + g_signal_connect(button, "clicked", G_CALLBACK(on_webSearch_add), webSearch); + gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); + button = gtk_button_new_from_stock(GTK_STOCK_EDIT); + g_signal_connect(button, "clicked", G_CALLBACK(on_webSearch_edit), webSearch); + gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); + webSearch->edit = button; + button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + g_signal_connect(button, "clicked", G_CALLBACK(on_webSearch_remove), webSearch); + gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); + webSearch->remove = button; + button = gtk_label_new(""); // This is an invisible separator + gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 12); + button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); + gtk_widget_set_sensitive(button, FALSE); //... + gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0); + button = gtk_button_new_from_stock(GTK_STOCK_GO_UP); + gtk_widget_set_sensitive(button, FALSE); //... + gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0); + webSearch_toggle_edit_buttons(n > 0, webSearch); + gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); + return dialog; +} + +gboolean on_webSearch_key_down(GtkWidget* widget, GdkEventKey* event, MidoriBrowser* browser) +{ + GdkModifierType state = (GdkModifierType)0; + gint x, y; gdk_window_get_pointer(NULL, &x, &y, &state); + if(!(state & GDK_CONTROL_MASK)) + return FALSE; + switch(event->keyval) + { + case GDK_Up: + //update_searchEngine(config->searchEngine - 1, browser); + return TRUE; + case GDK_Down: + //update_searchEngine(config->searchEngine + 1, browser); + return TRUE; + } + return FALSE; +} + +gboolean on_webSearch_scroll(GtkWidget* webView, GdkEventScroll* event, MidoriBrowser* browser) +{ + if(event->direction == GDK_SCROLL_DOWN) + ;//update_searchEngine(config->searchEngine + 1, browser); + else if(event->direction == GDK_SCROLL_UP) + ;//update_searchEngine(config->searchEngine - 1, browser); + return TRUE; +} + +void on_webSearch_activate(GtkWidget* widget, MidoriBrowser* browser) +{ + const gchar* keywords = gtk_entry_get_text(GTK_ENTRY(widget)); + gchar* url; + SearchEngine* searchEngine = (SearchEngine*)g_list_nth_data(searchEngines, 0/*config->searchEngine*/); + if(searchEngine) + url = searchEngine->url; + else // The location search is our fallback + url = "";//config->locationSearch; + gchar* search; + if(strstr(url, "%s")) + search = g_strdup_printf(url, keywords); + else + search = g_strconcat(url, " ", keywords, NULL); + sokoke_entry_append_completion(GTK_ENTRY(widget), keywords); + GtkWidget* webView = midori_browser_get_current_web_view(browser); + webkit_web_view_open(WEBKIT_WEB_VIEW(webView), search); + g_free(search); +} diff --git a/midori/webSearch.h b/midori/webSearch.h new file mode 100644 index 00000000..cefa89be --- /dev/null +++ b/midori/webSearch.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2007 Christian Dywan + + 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. +*/ + +#ifndef __WEBSEARCH_H__ +#define __WEBSEARCH_H__ 1 + +#include "midori-browser.h" + +#include +#include +#include + +// -- Types + +typedef struct +{ + MidoriBrowser* browser; + GtkWidget* window; + GtkWidget* treeview; + GtkWidget* edit; + GtkWidget* remove; +} CWebSearch; + +enum +{ + ENGINES_COL_ENGINE, + ENGINES_COL_N +}; + +// -- Declarations + +void +update_searchEngine(guint, GtkWidget*); + +void +on_webSearch_icon_released(GtkWidget*, SexyIconEntryPosition*, gint, MidoriBrowser*); + +void +on_webSearch_engine_activate(GtkWidget*, MidoriBrowser*); + +void +on_webSearch_activate(GtkWidget*, MidoriBrowser*); + +GtkWidget* +webSearch_manageSearchEngines_dialog_new(MidoriBrowser*); + +gboolean +on_webSearch_key_down(GtkWidget*, GdkEventKey*, MidoriBrowser*); + +gboolean +on_webSearch_scroll(GtkWidget*, GdkEventScroll*, MidoriBrowser*); + +#endif /* !__WEBSEARCH_H__ */ diff --git a/midori/wscript_build b/midori/wscript_build new file mode 100644 index 00000000..df741850 --- /dev/null +++ b/midori/wscript_build @@ -0,0 +1,9 @@ +#! /usr/bin/env python +# WAF build script for midori + +obj = bld.create_obj ('cc', 'program') +obj.target = 'midori' +obj.includes = '.. ../katze' +obj.find_sources_in_dirs ('.') +obj.uselib = 'GTK WEBKIT LIBXML LIBSEXY' +obj.uselib_local = 'katze' diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index bda06d22..00000000 --- a/src/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -INCLUDES = \ - $(GTK_CFLAGS) \ - $(WEBKIT_CFLAGS) \ - $(LIBSEXY_CFLAGS) \ - -I../katze - -AM_CFLAGS = -DMIDORI_LOCALEDIR=\""$(localedir)"\" - -LDADD = \ - $(GTK_LIBS) \ - $(WEBKIT_LIBS) \ - $(LIBSEXY_LIBS) \ - $(INTLLIBS) \ - ../katze/libkatze.la - -bin_PROGRAMS = \ - midori - -midori_SOURCES = \ - main.c main.h \ - midori-app.c midori-app.h \ - midori-browser.c midori-browser.h \ - midori-panel.c midori-panel.h \ - midori-addons.c midori-addons.h \ - midori-console.c midori-console.h \ - midori-trash.c midori-trash.h \ - midori-webview.c midori-webview.h \ - midori-websettings.c midori-websettings.h \ - midori-preferences.c midori-preferences.h \ - webSearch.c webSearch.h \ - gjs.c gjs.h \ - sokoke.c sokoke.h \ - search.c search.h diff --git a/src/gjs.c b/src/gjs.c deleted file mode 100644 index 29148bbd..00000000 --- a/src/gjs.c +++ /dev/null @@ -1,591 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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 "gjs.h" - -#include -#include - -#define G_OBJECT_NAME(object) G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object)) - -// FIXME: Return a GValue -JSValueRef -gjs_script_eval (JSContextRef js_context, - const gchar* script, - gchar** exception) -{ - g_return_val_if_fail (js_context, FALSE); - g_return_val_if_fail (script, FALSE); - - JSStringRef js_script = JSStringCreateWithUTF8CString (script); - JSValueRef js_exception = NULL; - JSValueRef js_value = JSEvaluateScript (js_context, js_script, - JSContextGetGlobalObject (js_context), NULL, 0, &js_exception); - if (!js_value && exception) - { - JSStringRef js_message = JSValueToStringCopy (js_context, - js_exception, NULL); - *exception = gjs_string_utf8 (js_message); - JSStringRelease (js_message); - js_value = JSValueMakeNull (js_context); - } - JSStringRelease (js_script); - return js_value; -} - -gboolean -gjs_script_check_syntax (JSContextRef js_context, - const gchar* script, - gchar** exception) -{ - g_return_val_if_fail (js_context, FALSE); - g_return_val_if_fail (script, FALSE); - - JSStringRef js_script = JSStringCreateWithUTF8CString (script); - JSValueRef js_exception = NULL; - bool result = JSCheckScriptSyntax (js_context, js_script, NULL, - 0, &js_exception); - if (!result && exception) - { - JSStringRef js_message = JSValueToStringCopy (js_context, - js_exception, NULL); - *exception = gjs_string_utf8 (js_message); - JSStringRelease (js_message); - } - JSStringRelease (js_script); - return result ? TRUE : FALSE; -} - -gboolean -gjs_script_from_file (JSContextRef js_context, - const gchar* filename, - gchar** exception) -{ - g_return_val_if_fail (js_context, FALSE); - g_return_val_if_fail (filename, FALSE); - - gboolean result = FALSE; - gchar* script; - GError* error = NULL; - if (g_file_get_contents (filename, &script, NULL, &error)) - { - if (gjs_script_eval (js_context, script, exception)) - result = TRUE; - g_free (script); - } - else if (error) - { - *exception = g_strdup (error->message); - g_error_free (error); - } - else - *exception = g_strdup (_("An unknown error occured.")); - return result; -} - -gchar* -gjs_string_utf8 (JSStringRef js_string) -{ - size_t size_utf8 = JSStringGetMaximumUTF8CStringSize (js_string); - gchar* string_utf8 = g_new (gchar, size_utf8); - JSStringGetUTF8CString (js_string, string_utf8, size_utf8); - return string_utf8; -} - -static void -_js_class_get_property_names_cb (JSContextRef js_context, - JSObjectRef js_object, - JSPropertyNameAccumulatorRef js_properties) -{ - GObject* object = JSObjectGetPrivate (js_object); - if (object) - { - guint n; - GParamSpec** pspecs = g_object_class_list_properties ( - G_OBJECT_GET_CLASS (object), &n); - gint i; - for (i = 0; i < n; i++) - { - const gchar* property = g_param_spec_get_name (pspecs[i]); - JSStringRef js_property = JSStringCreateWithUTF8CString (property); - JSPropertyNameAccumulatorAddName (js_properties, js_property); - JSStringRelease (js_property); - } - GType type = G_OBJECT_TYPE (object); - do - { - guint* signals = g_signal_list_ids (type, &n); - for (i = 0; i < n; i++) - { - const gchar* signal = g_signal_name (signals[i]); - JSStringRef js_signal = JSStringCreateWithUTF8CString (signal); - JSPropertyNameAccumulatorAddName (js_properties, js_signal); - JSStringRelease (js_signal); - } - type = g_type_parent (type); - } - while (type); - } -} - -static bool -_js_class_has_property_cb (JSContextRef js_context, - JSObjectRef js_object, - JSStringRef js_property) -{ - bool result = false; - gchar* property = gjs_string_utf8 (js_property); - GObject* object = JSObjectGetPrivate (js_object); - if (object) - { - if (g_signal_lookup (property, G_OBJECT_TYPE (object)) || - g_object_class_find_property (G_OBJECT_GET_CLASS (object), property)) - result = true; - } - else if (js_object == JSContextGetGlobalObject (js_context)) - { - GType type = g_type_from_name (property); - result = type ? type : false; - } - g_free (property); - return result; -} - -static void -_js_object_set_property (JSContextRef js_context, - JSObjectRef js_object, - const gchar* name, - JSValueRef js_value) -{ - JSStringRef js_name = JSStringCreateWithUTF8CString (name); - JSObjectSetProperty(js_context, js_object, js_name, js_value, - kJSPropertyAttributeNone, NULL); - JSStringRelease (js_name); -} - -static JSValueRef -_js_object_call_as_function_cb (JSContextRef js_context, - JSObjectRef js_function, - JSObjectRef js_this, - size_t n_arguments, - const JSValueRef js_arguments[], - JSValueRef* js_exception) -{ - GObject* object = JSObjectGetPrivate (js_this); - const gchar* function = JSObjectGetPrivate (js_function); - - g_return_val_if_fail (G_IS_OBJECT (object), JSValueMakeNull (js_context)); - g_return_val_if_fail (function, JSValueMakeNull (js_context)); - - guint signal_id = g_signal_lookup (function, G_OBJECT_TYPE (object)); - GSignalQuery query; - g_signal_query (signal_id, &query); - GValue* values = g_new0 (GValue, n_arguments + 1); - g_value_init (&values[0], G_OBJECT_TYPE (object)); - g_value_set_instance (&values[0], object); - gint i; - for (i = 0; i < n_arguments; i++) - { - GValue value = {0, }; - GType gtype; - switch (JSValueGetType (js_context, js_arguments[i])) - { - case kJSTypeBoolean: - gtype = G_TYPE_BOOLEAN; - g_value_init (&value, gtype); - g_value_set_boolean (&value, - JSValueToBoolean (js_context, js_arguments[i]) ? TRUE : FALSE); - break; - case kJSTypeNumber: - gtype = G_TYPE_DOUBLE; - g_value_init (&value, gtype); - g_value_set_double (&value, - JSValueToNumber (js_context, js_arguments[i], NULL)); - break; - case kJSTypeString: - gtype = G_TYPE_STRING; - g_value_init (&value, gtype); - JSStringRef js_string = JSValueToStringCopy (js_context, - js_arguments[i], NULL); - gchar* string = gjs_string_utf8 (js_string); - g_value_set_string (&value, string); - g_free (string); - JSStringRelease (js_string); - break; - case kJSTypeObject: - gtype = G_TYPE_OBJECT; - g_value_init (&value, gtype); - JSObjectRef js_object = JSValueToObject (js_context, - js_arguments[i], NULL); - GObject* object_value = JSObjectGetPrivate (js_object); - g_value_set_object (&value, object_value); - break; - case kJSTypeUndefined: - case kJSTypeNull: - default: - gtype = G_TYPE_NONE; - g_value_init (&value, gtype); - } - g_value_init (&values[i + 1], gtype); - if (query.n_params >= i - && g_value_type_compatible (gtype, query.param_types[i])) - // && g_value_type_transformable (gtype, query.param_types[i]) - g_value_copy (&value, &values[i + 1]); - // g_value_transform (&value, &values[i + 1]); - else - { - gchar* value_type = g_strdup_value_contents (&value); - // FIXME: exception - printf ("wrong value, expected %s\n", value_type); - g_free (value_type); - } - g_value_unset (&value); - } - GValue return_value = {0, }; - if (query.return_type != G_TYPE_NONE) - g_value_init (&return_value, query.return_type); - g_signal_emitv (values, signal_id, 0, &return_value); - - for (i = 0; i < n_arguments; i++) - g_value_unset (&values[i]); - // FIXME: return value - return JSValueMakeUndefined (js_context); -} - -static void -_js_object_add_function (JSContextRef js_context, - JSObjectRef js_object, - const gchar* func) -{ - JSStringRef js_func = JSStringCreateWithUTF8CString (func); - JSObjectRef js_function = JSObjectMakeFunctionWithCallback ( - js_context, js_func, _js_object_call_as_function_cb); - JSStringRelease (js_func); - _js_object_set_property (js_context, js_object, func, js_function); -} - -static JSValueRef -_js_class_get_property_cb (JSContextRef js_context, - JSObjectRef js_object, - JSStringRef js_property, - JSValueRef* js_exception) -{ - GObject* object = JSObjectGetPrivate (js_object); - - g_return_val_if_fail (G_IS_OBJECT (object), JSValueMakeNull (js_context)); - - JSValueRef js_result = NULL; - gchar* property = gjs_string_utf8 (js_property); - guint signal_id; - GParamSpec* pspec; - if ((signal_id = g_signal_lookup (property, G_OBJECT_TYPE (object)))) - { - GSignalQuery query; - g_signal_query (signal_id, &query); - if (query.signal_flags & G_SIGNAL_ACTION) - { - // We can't use JSObjectMakeFunctionWithCallback - // because it doesn't allocate private data - JSClassDefinition js_class_def = kJSClassDefinitionEmpty; - js_class_def.className = g_strdup (property); - js_class_def.callAsFunction = _js_object_call_as_function_cb; - JSClassRef js_class = JSClassCreate (&js_class_def); - JSObjectRef js_function = JSObjectMake (js_context, js_class, property); - return js_function; - } - g_free (property); - return JSValueMakeUndefined (js_context); - } - else if (!(pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (object), property))) - { - gchar* message = g_strdup_printf (_("%s has no property '%s'"), - G_OBJECT_NAME (object), property); - JSStringRef js_message = JSStringCreateWithUTF8CString (message); - *js_exception = JSValueMakeString (js_context, js_message); - JSStringRelease (js_message); - g_free (message); - g_free (property); - return JSValueMakeNull (js_context); - } - if (!(pspec->flags & G_PARAM_READABLE)) - { - g_free (property); - return JSValueMakeUndefined (js_context); - } - GType type = G_PARAM_SPEC_TYPE (pspec); - if (type == G_TYPE_PARAM_STRING) - { - gchar* value; - g_object_get (object, property, &value, NULL); - if (value) - { - JSStringRef js_string = JSStringCreateWithUTF8CString (value); - js_result = JSValueMakeString (js_context, js_string); - } - } - else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT) - { - gint value; - g_object_get (object, property, &value, NULL); - js_result = JSValueMakeNumber (js_context, value); - } - else if (type == G_TYPE_PARAM_BOOLEAN) - { - gboolean value; - g_object_get (object, property, &value, NULL); - js_result = JSValueMakeBoolean (js_context, value ? true : false); - } - else if (type == G_TYPE_PARAM_OBJECT) - { - GObject* value; - g_object_get (object, property, &value, NULL); - if (value) - js_result = gjs_object_new (js_context, - G_OBJECT_NAME (value), value); - } - else if (type == G_TYPE_PARAM_ENUM) - { - gint value; - g_object_get (object, property, &value, NULL); - js_result = JSValueMakeNumber (js_context, value); - } - else - js_result = JSValueMakeUndefined (js_context); - g_free (property); - return js_result ? js_result : JSValueMakeNull (js_context); -} - -static bool -_js_class_set_property_cb (JSContextRef js_context, - JSObjectRef js_object, - JSStringRef js_property, - JSValueRef js_value, - JSValueRef* js_exception) -{ - GObject* object = JSObjectGetPrivate (js_object); - - g_return_val_if_fail (G_IS_OBJECT (object), false); - - bool result = false; - gchar* property = gjs_string_utf8 (js_property); - GParamSpec* pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (object), property); - if (!pspec) - { - gchar* message = g_strdup_printf (_("%s has no property '%s'"), - G_OBJECT_NAME (object), property); - JSStringRef js_message = JSStringCreateWithUTF8CString (message); - *js_exception = JSValueMakeString (js_context, js_message); - JSStringRelease (js_message); - g_free (message); - g_free (property); - return false; - } - if (!(pspec->flags & G_PARAM_WRITABLE)) - { - g_free (property); - return false; - } - GType type = G_PARAM_SPEC_TYPE (pspec); - if (type == G_TYPE_PARAM_STRING) - { - JSStringRef js_string_value = JSValueToStringCopy (js_context, - js_value, js_exception); - if (js_string_value) - { - gchar* string_value = gjs_string_utf8 (js_string_value); - g_object_set (object, property, string_value, NULL); - g_free (string_value); - } - } - else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT) - { - int value = JSValueToNumber (js_context, js_value, - js_exception); - g_object_set (object, property, value, NULL); - } - else if (type == G_TYPE_PARAM_BOOLEAN) - { - bool value = JSValueToBoolean (js_context, js_value); - g_object_set (object, property, value ? TRUE : FALSE, NULL); - } - else if (type == G_TYPE_PARAM_OBJECT) - { - JSObjectRef js_object_value = JSValueToObject ( - js_context, js_value, NULL); - GObject* object_value = JSObjectGetPrivate (js_object_value); - if (G_IS_OBJECT (object_value)) - g_object_set (object, property, object_value, NULL); - else - { - gchar* message = g_strdup_printf (_("%s cannot be assigned to %s.%s"), - "[object]", G_OBJECT_NAME (object), property); - JSStringRef js_message = JSStringCreateWithUTF8CString (message); - *js_exception = JSValueMakeString (js_context, js_message); - JSStringRelease (js_message); - g_free (message); - } - } - else - { - gchar* message = g_strdup_printf (_("%s.%s cannot be accessed"), - G_OBJECT_NAME (object), property); - JSStringRef js_message = JSStringCreateWithUTF8CString (message); - *js_exception = JSValueMakeString (js_context, js_message); - JSStringRelease (js_message); - g_free (message); - } - g_free (property); - return result; -} - -JSObjectRef -gjs_object_new (JSContextRef js_context, - const gchar* name, - gpointer instance) -{ - g_return_val_if_fail (js_context, NULL); - g_return_val_if_fail (name, NULL); - - JSClassDefinition js_class_def = kJSClassDefinitionEmpty; - js_class_def.className = g_strdup (name); - js_class_def.getPropertyNames = _js_class_get_property_names_cb; - js_class_def.hasProperty = _js_class_has_property_cb; - js_class_def.getProperty = _js_class_get_property_cb; - js_class_def.setProperty = _js_class_set_property_cb; - JSClassRef js_class = JSClassCreate (&js_class_def); - JSObjectRef js_object = JSObjectMake (js_context, js_class, instance); - return js_object; -} - -static JSObjectRef -_js_object_call_as_constructor_cb (JSContextRef js_context, - JSObjectRef js_object, - size_t n_arguments, - const JSValueRef js_arguments[], - JSValueRef* js_exception) -{ - const gchar* type_name = JSObjectGetPrivate (js_object); - - g_return_val_if_fail (type_name, NULL); - - GType type = g_type_from_name (type_name); - if (type) - return gjs_object_new (js_context, type_name, g_object_new (type, NULL)); - return NULL; -} - -static bool -_js_module_has_property_cb (JSContextRef js_context, - JSObjectRef js_object, - JSStringRef js_property) -{ - const gchar* namespace = JSObjectGetPrivate (js_object); - - g_return_val_if_fail (namespace, false); - - gchar* property = gjs_string_utf8 (js_property); - gchar* type_name = g_strdup_printf ("%s%s", namespace, property); - - GType type = g_type_from_name (type_name); - if (!type) - { - GModule* module = g_module_open (NULL, - G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - typedef GType (*gjs_get_type_func)(void); - // FIXME: Insert a space between each capital letter - gchar* type_func_name = g_strdup_printf ("%s_%s_get_type", - namespace, property); - gchar* type_func_name_small = g_utf8_strdown (type_func_name, -1); - gjs_get_type_func type_func; - if (g_module_symbol (module, - (const gchar*)type_func_name_small, &type_func)) - { - type = type_func (); - g_type_class_peek (type); - } - g_free (type_func_name_small); - g_free (type_func_name); - g_module_close (module); - } - bool result = type ? true : false; - g_free (type_name); - g_free (property); - return result; -} - -static JSValueRef -_js_module_get_property_cb (JSContextRef js_context, - JSObjectRef js_object, - JSStringRef js_property, - JSValueRef* js_exception) -{ - const gchar* namespace = JSObjectGetPrivate (js_object); - - g_return_val_if_fail (namespace, JSValueMakeNull (js_context)); - - gchar* property = gjs_string_utf8 (js_property); - gchar* type_name = g_strdup_printf ("%s%s", namespace, property); - GType type = g_type_from_name (type_name); - JSValueRef result; - if (type) - { - JSClassDefinition js_class_def = kJSClassDefinitionEmpty; - js_class_def.className = g_strdup (type_name); - js_class_def.callAsConstructor = _js_object_call_as_constructor_cb; - JSClassRef js_class = JSClassCreate (&js_class_def); - result = JSObjectMake (js_context, js_class, type_name); - } - else - { - result = JSValueMakeNull (js_context); - g_free (type_name); - } - g_free (property); - return result; -} - -JSObjectRef -gjs_module_new (JSContextRef js_context, - const gchar* namespace) -{ - g_return_val_if_fail (js_context, NULL); - g_return_val_if_fail (namespace, NULL); - - JSClassDefinition js_class_def = kJSClassDefinitionEmpty; - js_class_def.className = g_strdup (namespace); - js_class_def.hasProperty = _js_module_has_property_cb; - js_class_def.getProperty = _js_module_get_property_cb; - JSClassRef js_class = JSClassCreate (&js_class_def); - JSObjectRef js_module = JSObjectMake (js_context, js_class, (gpointer)namespace); - return js_module; -} - -JSGlobalContextRef -gjs_global_context_new (void) -{ - JSGlobalContextRef js_context = JSGlobalContextCreate (NULL); - JSObjectRef js_object = gjs_object_new (js_context, "GJS", NULL); - _js_object_set_property (js_context, JSContextGetGlobalObject (js_context), - "gjs", js_object); - - js_object = gjs_module_new (js_context, "Gtk"); - _js_object_set_property (js_context, JSContextGetGlobalObject (js_context), - "Gtk", js_object); - js_object = gjs_module_new (js_context, "WebKit"); - _js_object_set_property (js_context, JSContextGetGlobalObject (js_context), - "WebKit", js_object); - js_object = gjs_module_new (js_context, "Midori"); - _js_object_set_property (js_context, JSContextGetGlobalObject (js_context), - "Midori", js_object); - return js_context; -} diff --git a/src/gjs.h b/src/gjs.h deleted file mode 100644 index 47e9fced..00000000 --- a/src/gjs.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __GJS_H__ -#define __GJS_H__ - -#include -#include - -G_BEGIN_DECLS - -JSValueRef -gjs_script_eval (JSContextRef js_context, - const gchar* script, - gchar** exception); - -gboolean -gjs_script_check_syntax (JSContextRef js_context, - const gchar* script, - gchar** exception); - -gboolean -gjs_script_from_file (JSContextRef js_context, - const gchar* filename, - gchar** exception); - -gchar* -gjs_string_utf8 (JSStringRef js_string); - -JSObjectRef -gjs_object_new (JSContextRef context, - const gchar* name, - gpointer instance); - -JSGlobalContextRef -gjs_global_context_new (void); - -G_END_DECLS - -#endif /* __GJS_H__ */ diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 6d4f03e8..00000000 --- a/src/main.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - 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 "sokoke.h" -#include "search.h" - -#include "midori-app.h" -#include "midori-websettings.h" -#include "midori-trash.h" -#include "midori-browser.h" -#include "gjs.h" - -#include -#include -#include - -#include "config.h" - -#ifdef ENABLE_NLS - #include -#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_ADD, N_("_Add 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_LEAVE_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 void -locale_init (void) -{ -#ifdef ENABLE_NLS - 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) - { - gint 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_FLOAT) - { - gdouble number = sokoke_key_file_get_double_default (key_file, - "settings", property, - G_PARAM_SPEC_FLOAT (pspec)->default_value, NULL); - g_object_set (settings, property, number, 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); - if (enum_value) - g_object_set (settings, property, enum_value->value, NULL); - else - g_warning (_("Value '%s' is invalid for %s"), - string, property); - - g_free (string); - g_type_class_unref (enum_class); - } - else - g_warning (_("Unhandled settings value '%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_FLOAT) - { - gdouble number; - g_object_get (settings, property, &number, NULL); - g_key_file_set_double (key_file, "settings", property, number); - } - 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) -{ - MidoriStartup load_on_startup; - gchar* homepage; - - 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 }, - { 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; - } - - // Standalone gjs support - if (argc > 1 && argv[1] && g_str_has_suffix (argv[1], ".js")) - { - JSGlobalContextRef js_context = gjs_global_context_new (); - gchar* exception = NULL; - gjs_script_from_file (js_context, argv[1], &exception); - JSGlobalContextRelease (js_context); - if (!exception) - return 0; - printf ("%s - Exception: %s\n", argv[1], exception); - return 1; - } - - // 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); - 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 (); - g_object_get (settings, "load-on-startup", &load_on_startup, NULL); - if (load_on_startup == MIDORI_STARTUP_LAST_OPEN_PAGES) - { - 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) - { - 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* uri_ready = sokoke_magic_uri (uri, NULL); - katze_xbel_bookmark_set_href (item, uri_ready); - g_free (uri_ready); - 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 (load_on_startup == MIDORI_STARTUP_BLANK_PAGE) - katze_xbel_bookmark_set_href (item, ""); - else - { - g_object_get (settings, "homepage", &homepage, NULL); - katze_xbel_bookmark_set_href (item, homepage); - g_free (homepage); - } - katze_xbel_folder_prepend_item (_session, item); - } - g_free (config_path); - - stock_items_init (); - - MidoriApp* app = midori_app_new (); - g_object_set (app, "settings", settings, NULL); - - MidoriTrash* trash = midori_app_get_trash (app); - 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); - } - - MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER, - "settings", settings, - "trash", trash, - NULL); - g_signal_emit_by_name (app, "add-browser", 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_add_xbel_item (browser, item); - } - // FIXME: Switch to the last active page - KatzeXbelItem* item = katze_xbel_folder_get_nth_item (_session, 0); - if (!strcmp (katze_xbel_bookmark_get_href (item), "")) - midori_browser_activate_action (browser, "Location"); - katze_xbel_item_unref (_session); - - // Load extensions - JSGlobalContextRef js_context = gjs_global_context_new (); - // FIXME: We want to honor system installed addons as well - gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, - "extensions", NULL); - GDir* addon_dir = g_dir_open (addon_path, 0, NULL); - if (addon_dir) - { - const gchar* filename; - while ((filename = g_dir_read_name (addon_dir))) - { - gchar* fullname = g_build_filename (addon_path, filename, NULL); - gchar* exception = NULL; - gjs_script_from_file (js_context, fullname, &exception); - if (exception) - // FIXME: Do we want to print this somewhere else? - // FIXME Convert the filename to UTF8 - printf ("%s - Exception: %s\n", filename, exception); - g_free (fullname); - } - g_dir_close (addon_dir); - } - - gtk_main (); - - JSGlobalContextRelease (js_context); - - // 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); - g_object_get (settings, "load-on-startup", &load_on_startup, NULL); - if(load_on_startup == MIDORI_STARTUP_LAST_OPEN_PAGES) - { - 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); - } - 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; -} diff --git a/src/main.h b/src/main.h deleted file mode 100644 index 3eab9b70..00000000 --- a/src/main.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - 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. -*/ - -#ifndef __MAIN_H__ -#define __MAIN_H__ 1 - -#include - -#include -#include - -#include - -// FIXME: Remove these globals - -GList* searchEngines; // Items of type 'SearchEngine' -KatzeXbelItem* bookmarks; - -// Custom stock items - -// We should distribute these -// Names should match with epiphany and/ or xdg spec -/* NOTE: Those uncommented were replaced with remotely related icons - in order to reduce the amount of warnings :D */ - -#define STOCK_BOOKMARK GTK_STOCK_FILE // "stock_bookmark" "bookmark-web" -#define STOCK_FORM_FILL GTK_STOCK_JUSTIFY_FILL // "insert-text" "form-fill" -#define STOCK_NEWSFEED GTK_STOCK_INDEX - -// We assume that these legacy icon names are usually present - -#define STOCK_BOOKMARK_ADD "stock_add-bookmark" -#define STOCK_HOMEPAGE GTK_STOCK_HOME -#define STOCK_IMAGE "gnome-mime-image" -#define STOCK_LOCK_OPEN "stock_lock-open" -#define STOCK_LOCK_SECURE "stock_lock" -#define STOCK_LOCK_BROKEN "stock_lock-broken" -#define STOCK_NETWORK_OFFLINE "network-offline" -#define STOCK_SCRIPT "stock_script" -#define STOCK_SEND "stock_mail-send" -#define STOCK_TAB_NEW "stock_new-tab" -#define STOCK_THEME "gnome-settings-theme" -#define STOCK_USER_TRASH "gnome-stock-trash" -#define STOCK_WINDOW_NEW "stock_new-window" - -// For backwards compatibility - -#if !GTK_CHECK_VERSION(2, 10, 0) -#define GTK_STOCK_SELECT_ALL "gtk-select-all" -#endif -#if !GTK_CHECK_VERSION(2, 8, 0) -#define GTK_STOCK_FULLSCREEN "gtk-fullscreen" -#define GTK_STOCK_LEAVE_FULLSCREEN "gtk-leave-fullscreen" -#endif - -#endif /* !__MAIN_H__ */ diff --git a/src/midori-addons.c b/src/midori-addons.c deleted file mode 100644 index a5a2985b..00000000 --- a/src/midori-addons.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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 "config.h" - -#include "midori-addons.h" - -#include "sokoke.h" -#include "gjs.h" -#include -#include -#include - -G_DEFINE_TYPE (MidoriAddons, midori_addons, GTK_TYPE_VBOX) - -struct _MidoriAddonsPrivate -{ - MidoriAddonKind kind; - GtkWidget* toolbar; - GtkWidget* treeview; -}; - -#define MIDORI_ADDONS_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_ADDONS, MidoriAddonsPrivate)) - -GType -midori_addon_kind_get_type (void) -{ - static GType type = 0; - if (!type) - { - static const GEnumValue values[] = { - { MIDORI_ADDON_EXTENSIONS, "MIDORI_ADDON_EXTENSIONS", N_("Extensions") }, - { MIDORI_ADDON_USER_SCRIPTS, "MIDORI_USER_SCRIPTS", N_("Userscripts") }, - { MIDORI_ADDON_USER_STYLES, "MIDORI_USER_STYLES", N_("Userstyles") }, - { 0, NULL, NULL } - }; - type = g_enum_register_static ("MidoriAddonKind", values); - } - return type; -} - -static void -midori_addons_class_init (MidoriAddonsClass* class) -{ - g_type_class_add_private (class, sizeof (MidoriAddonsPrivate)); -} - -static const -gchar* _folder_for_kind (MidoriAddonKind kind) -{ - switch (kind) - { - case MIDORI_ADDON_EXTENSIONS: - return "extensions"; - case MIDORI_ADDON_USER_SCRIPTS: - return "scripts"; - case MIDORI_ADDON_USER_STYLES: - return "styles"; - default: - return NULL; - } -} - -static void -midori_addons_button_add_clicked_cb (GtkToolItem* toolitem, - MidoriAddons* addons) -{ - MidoriAddonsPrivate* priv = addons->priv; - - GtkWidget* dialog = gtk_message_dialog_new ( - GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (addons))), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, - "Put scripts in the folder ~/.local/share/midori/%s", - _folder_for_kind (priv->kind)); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); -} - -static void -midori_addons_treeview_render_icon_cb (GtkTreeViewColumn* column, - GtkCellRenderer* renderer, - GtkTreeModel* model, - GtkTreeIter* iter, - GtkWidget* treeview) -{ - // gchar* source_id; - // gtk_tree_model_get (model, iter, 2, &source_id, -1); - - g_object_set (renderer, "stock-id", GTK_STOCK_FILE, NULL); - - // g_free (source_id); -} - -static void -midori_addons_treeview_render_text_cb (GtkTreeViewColumn* column, - GtkCellRenderer* renderer, - GtkTreeModel* model, - GtkTreeIter* iter, - GtkWidget* treeview) -{ - gchar* filename; - gint a; - gchar* b; - gtk_tree_model_get (model, iter, 0, &filename, 1, &a, 2, &b, -1); - - // FIXME: Convert filename to UTF8 - gchar* text = g_strdup_printf ("%s", filename); - g_object_set (renderer, "text", text, NULL); - g_free (text); - - g_free (filename); - g_free (b); -} - -static void -midori_addons_treeview_row_activated_cb (GtkTreeView* treeview, - GtkTreePath* path, - GtkTreeViewColumn* column, - MidoriAddons* addons) -{ - /*GtkTreeModel* model = gtk_tree_view_get_model (treeview); - GtkTreeIter iter; - if (gtk_tree_model_get_iter (model, &iter, path)) - { - gchar* b; - gtk_tree_model_get (model, &iter, 2, &b, -1); - g_free (b); - }*/ -} - -static void -midori_addons_init (MidoriAddons* addons) -{ - addons->priv = MIDORI_ADDONS_GET_PRIVATE (addons); - - MidoriAddonsPrivate* priv = addons->priv; - - GtkTreeViewColumn* column; - GtkCellRenderer* renderer_text; - GtkCellRenderer* renderer_pixbuf; - priv->treeview = gtk_tree_view_new (); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE); - column = gtk_tree_view_column_new (); - renderer_pixbuf = gtk_cell_renderer_pixbuf_new (); - gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE); - gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf, - (GtkTreeCellDataFunc)midori_addons_treeview_render_icon_cb, - priv->treeview, NULL); - renderer_text = gtk_cell_renderer_text_new (); - gtk_tree_view_column_pack_start (column, renderer_text, FALSE); - gtk_tree_view_column_set_cell_data_func (column, renderer_text, - (GtkTreeCellDataFunc)midori_addons_treeview_render_text_cb, - priv->treeview, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column); - g_signal_connect (priv->treeview, "row-activated", - G_CALLBACK (midori_addons_treeview_row_activated_cb), - addons); - gtk_widget_show (priv->treeview); - gtk_box_pack_start (GTK_BOX (addons), priv->treeview, TRUE, TRUE, 0); -} - -static gboolean -_js_script_from_file (JSContextRef js_context, - const gchar* filename, - gchar** exception) -{ - gboolean result = FALSE; - gchar* script; - GError* error = NULL; - if (g_file_get_contents (filename, &script, NULL, &error)) - { - // Wrap the script to prevent global variables - gchar* wrapped_script = g_strdup_printf ( - "var wrapped = function () { %s }; wrapped ();", script); - if (gjs_script_eval (js_context, wrapped_script, exception)) - result = TRUE; - g_free (wrapped_script); - g_free (script); - } - else - { - *exception = g_strdup (error->message); - g_error_free (error); - } - return result; -} - -static void -midori_web_widget_window_object_cleared_cb (GtkWidget* web_widget, - WebKitWebFrame* web_frame, - JSGlobalContextRef js_context, - JSObjectRef js_window, - MidoriAddons* addons) -{ - MidoriAddonsPrivate* priv = addons->priv; - - // FIXME: We want to honor system installed addons as well - gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, - _folder_for_kind (priv->kind), NULL); - GDir* addon_dir = g_dir_open (addon_path, 0, NULL); - if (addon_dir) - { - const gchar* filename; - while ((filename = g_dir_read_name (addon_dir))) - { - gchar* fullname = g_build_filename (addon_path, filename, NULL); - gchar* exception; - if (!_js_script_from_file (js_context, fullname, &exception)) - { - gchar* message = g_strdup_printf ("console.error ('%s');", - exception); - gjs_script_eval (js_context, message, NULL); - g_free (message); - g_free (exception); - } - g_free (fullname); - } - g_dir_close (addon_dir); - } -} - -/** - * midori_addons_new: - * @web_widget: a web widget - * @kind: the kind of addon - * @extension: a file extension mask - * - * Creates a new addons widget. - * - * @web_widget can be one of the following: - * %MidoriBrowser, %MidoriWebView, %WebKitWebView - * - * Note: Currently @extension has no effect. - * - * Return value: a new #MidoriAddons - **/ -GtkWidget* -midori_addons_new (GtkWidget* web_widget, - MidoriAddonKind kind) -{ - g_return_val_if_fail (GTK_IS_WIDGET (web_widget), NULL); - - MidoriAddons* addons = g_object_new (MIDORI_TYPE_ADDONS, - // "kind", kind, - NULL); - - MidoriAddonsPrivate* priv = addons->priv; - priv->kind = kind; - - if (kind == MIDORI_ADDON_USER_SCRIPTS) - g_signal_connect (web_widget, "window-object-cleared", - G_CALLBACK (midori_web_widget_window_object_cleared_cb), addons); - - GtkListStore* liststore = gtk_list_store_new (3, G_TYPE_STRING, - G_TYPE_INT, - G_TYPE_STRING); - // FIXME: We want to honor system installed addons as well - gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, - _folder_for_kind (priv->kind), NULL); - GDir* addon_dir = g_dir_open (addon_path, 0, NULL); - if (addon_dir) - { - const gchar* filename; - while ((filename = g_dir_read_name (addon_dir))) - { - GtkTreeIter iter; - gtk_list_store_append (liststore, &iter); - gtk_list_store_set (liststore, &iter, - 0, filename, 1, 0, 2, "", -1); - } - g_dir_close (addon_dir); - } - gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), - GTK_TREE_MODEL (liststore)); - - return GTK_WIDGET (addons); -} - -/** - * midori_addons_get_toolbar: - * - * Retrieves the toolbar of the addons. A new widget is created on - * the first call of this function. - * - * Return value: a new #MidoriAddons - **/ -GtkWidget* -midori_addons_get_toolbar (MidoriAddons* addons) -{ - MidoriAddonsPrivate* priv = addons->priv; - - g_return_val_if_fail (MIDORI_IS_ADDONS (addons), NULL); - - if (!priv->toolbar) - { - GtkWidget* toolbar = gtk_toolbar_new (); - gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); - GtkToolItem* toolitem = gtk_tool_item_new (); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); - gtk_widget_show (GTK_WIDGET (toolitem)); - toolitem = gtk_separator_tool_item_new (); - gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), - FALSE); - gtk_tool_item_set_expand (toolitem, TRUE); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); - gtk_widget_show (GTK_WIDGET (toolitem)); - toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ADD); - gtk_tool_item_set_is_important (toolitem, TRUE); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (midori_addons_button_add_clicked_cb), addons); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); - gtk_widget_show (GTK_WIDGET (toolitem)); - priv->toolbar = toolbar; - } - - return priv->toolbar; -} diff --git a/src/midori-addons.h b/src/midori-addons.h deleted file mode 100644 index 940ff73c..00000000 --- a/src/midori-addons.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_ADDONS_H__ -#define __MIDORI_ADDONS_H__ - -#include - -#include - -G_BEGIN_DECLS - -#define MIDORI_TYPE_ADDONS \ - (midori_addons_get_type ()) -#define MIDORI_ADDONS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_ADDONS, MidoriAddons)) -#define MIDORI_ADDONS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_ADDONS, MidoriAddonsClass)) -#define MIDORI_IS_ADDONS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_ADDONS)) -#define MIDORI_IS_ADDONS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_ADDONS)) -#define MIDORI_ADDONS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_ADDONS, MidoriAddonsClass)) - -typedef struct _MidoriAddons MidoriAddons; -typedef struct _MidoriAddonsPrivate MidoriAddonsPrivate; -typedef struct _MidoriAddonsClass MidoriAddonsClass; - -struct _MidoriAddons -{ - GtkVBox parent_instance; - - MidoriAddonsPrivate* priv; -}; - -struct _MidoriAddonsClass -{ - GtkVBoxClass parent_class; -}; - -typedef enum -{ - MIDORI_ADDON_EXTENSIONS, - MIDORI_ADDON_USER_SCRIPTS, - MIDORI_ADDON_USER_STYLES -} MidoriAddonKind; - -GType -midori_addon_kind_get_type (void) G_GNUC_CONST; - -#define MIDORI_TYPE_ADDON_KIND \ - (midori_addon_kind_get_type ()) - -GType -midori_addons_get_type (void); - -GtkWidget* -midori_addons_new (GtkWidget* web_widget, - MidoriAddonKind kind); - -GtkWidget* -midori_addons_get_toolbar (MidoriAddons* console); - -G_END_DECLS - -#endif /* __MIDORI_ADDONS_H__ */ diff --git a/src/midori-app.c b/src/midori-app.c deleted file mode 100644 index 5d41e255..00000000 --- a/src/midori-app.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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 "midori-app.h" - -#include -#include - -G_DEFINE_TYPE (MidoriApp, midori_app, G_TYPE_OBJECT) - -static MidoriApp* _midori_app_singleton = NULL; - -struct _MidoriAppPrivate -{ - GList* browsers; - MidoriBrowser* browser; - GtkAccelGroup* accel_group; - - MidoriWebSettings* settings; - MidoriTrash* trash; -}; - -#define MIDORI_APP_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_APP, MidoriAppPrivate)) - -enum -{ - PROP_0, - - PROP_SETTINGS, - PROP_TRASH, - PROP_BROWSER, - PROP_BROWSER_COUNT -}; - -enum { - ADD_BROWSER, - QUIT, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static GObject* -midori_app_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam* construct_properties); - -static void -midori_app_finalize (GObject* object); - -static void -midori_app_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec); - -static void -midori_app_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec); - -static void -midori_app_add_browser (MidoriApp* app, - MidoriBrowser* browser); - -static void -midori_app_quit (MidoriApp* app); - -static void -midori_app_class_init (MidoriAppClass* class) -{ - signals[ADD_BROWSER] = g_signal_new ( - "add-browser", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriAppClass, add_browser), - 0, - NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - MIDORI_TYPE_BROWSER); - - signals[QUIT] = g_signal_new ( - "quit", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriAppClass, quit), - 0, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - GObjectClass* gobject_class = G_OBJECT_CLASS (class); - gobject_class->constructor = midori_app_constructor; - gobject_class->finalize = midori_app_finalize; - gobject_class->set_property = midori_app_set_property; - gobject_class->get_property = midori_app_get_property; - - MidoriAppClass* midoriapp_class = MIDORI_APP_CLASS (class); - midoriapp_class->add_browser = midori_app_add_browser; - midoriapp_class->quit = midori_app_quit; - - g_object_class_install_property (gobject_class, - PROP_SETTINGS, - g_param_spec_object ( - "settings", - _("Settings"), - _("The associated settings"), - MIDORI_TYPE_WEB_SETTINGS, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_TRASH, - g_param_spec_object ( - "trash", - _("Trash"), - _("The trash, collecting recently closed tabs and windows"), - MIDORI_TYPE_TRASH, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_BROWSER, - g_param_spec_object ( - "browser", - _("Browser"), - _("The current browser"), - MIDORI_TYPE_BROWSER, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_BROWSER_COUNT, - g_param_spec_uint ( - "browser-count", - _("Browser Count"), - _("The current number of browsers"), - 0, G_MAXUINT, 0, - G_PARAM_READABLE)); - - g_type_class_add_private (class, sizeof (MidoriAppPrivate)); -} - -static GObject* -midori_app_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam* construct_properties) -{ - if (_midori_app_singleton) - return g_object_ref (_midori_app_singleton); - else - return G_OBJECT_CLASS (midori_app_parent_class)->constructor ( - type, n_construct_properties, construct_properties); -} - -static void -midori_app_init (MidoriApp* app) -{ - g_assert (!_midori_app_singleton); - - _midori_app_singleton = app; - - app->priv = MIDORI_APP_GET_PRIVATE (app); - - MidoriAppPrivate* priv = app->priv; - - priv->accel_group = gtk_accel_group_new (); - - priv->settings = midori_web_settings_new (); - priv->trash = midori_trash_new (10); -} - -static void -midori_app_finalize (GObject* object) -{ - MidoriApp* app = MIDORI_APP (object); - MidoriAppPrivate* priv = app->priv; - - g_list_free (priv->browsers); - g_object_unref (priv->accel_group); - - g_object_unref (priv->settings); - g_object_unref (priv->trash); - - G_OBJECT_CLASS (midori_app_parent_class)->finalize (object); -} - -static void -midori_app_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec) -{ - MidoriApp* app = MIDORI_APP (object); - MidoriAppPrivate* priv = app->priv; - - switch (prop_id) - { - case PROP_SETTINGS: - katze_object_assign (priv->settings, g_value_get_object (value)); - g_object_ref (priv->settings); - // FIXME: Propagate settings to all browsers - break; - case PROP_TRASH: - katze_object_assign (priv->trash, g_value_get_object (value)); - g_object_ref (priv->trash); - // FIXME: Propagate trash to all browsers - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_app_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec) -{ - MidoriApp* app = MIDORI_APP (object); - MidoriAppPrivate* priv = app->priv; - - switch (prop_id) - { - case PROP_SETTINGS: - g_value_set_object (value, priv->settings); - break; - case PROP_TRASH: - g_value_set_object (value, priv->trash); - break; - case PROP_BROWSER: - g_value_set_object (value, priv->browser); - break; - case PROP_BROWSER_COUNT: - g_value_set_uint (value, g_list_length (priv->browsers)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_browser_focus_in_event_cb (MidoriBrowser* browser, - GdkEventFocus* event, - MidoriApp* app) -{ - MidoriAppPrivate* priv = app->priv; - - priv->browser = browser; -} - -static void -midori_browser_new_window_cb (MidoriBrowser* browser, - const gchar* uri, - MidoriApp* app) -{ - MidoriAppPrivate* priv = app->priv; - - MidoriBrowser* new_browser = g_object_new (MIDORI_TYPE_BROWSER, - "settings", priv->settings, - "trash", priv->trash, - NULL); - midori_browser_add_uri (new_browser, uri); - gtk_widget_show (GTK_WIDGET (new_browser)); - - g_signal_emit (app, signals[ADD_BROWSER], 0, new_browser); -} - -static gboolean -midori_browser_delete_event_cb (MidoriBrowser* browser, - GdkEvent* event, - MidoriApp* app) -{ - return FALSE; -} - -static gboolean -midori_browser_destroy_cb (MidoriBrowser* browser, - MidoriApp* app) -{ - MidoriAppPrivate* priv = app->priv; - - priv->browsers = g_list_remove (priv->browsers, browser); - if (g_list_nth (priv->browsers, 0)) - return FALSE; - g_signal_emit (app, signals[QUIT], 0); - return TRUE; -} - -static void -midori_browser_quit_cb (MidoriBrowser* browser, - MidoriApp* app) -{ - g_signal_emit (app, signals[QUIT], 0); -} - -static void -midori_app_add_browser (MidoriApp* app, - MidoriBrowser* browser) -{ - MidoriAppPrivate* priv = app->priv; - - gtk_window_add_accel_group (GTK_WINDOW (browser), priv->accel_group); - g_object_connect (browser, - "signal::focus-in-event", midori_browser_focus_in_event_cb, app, - "signal::new-window", midori_browser_new_window_cb, app, - "signal::delete-event", midori_browser_delete_event_cb, app, - "signal::destroy", midori_browser_destroy_cb, app, - "signal::quit", midori_browser_quit_cb, app, - NULL); - - priv->browsers = g_list_prepend (priv->browsers, browser); -} - -static void -midori_app_quit (MidoriApp* app) -{ - gtk_main_quit (); -} - -/** - * midori_app_new: - * - * Instantiates a new #MidoriApp singleton. - * - * Subsequent calls will ref the initial instance. - * - * Return value: a new #MidoriApp - **/ -MidoriApp* -midori_app_new (void) -{ - MidoriApp* app = g_object_new (MIDORI_TYPE_APP, - NULL); - - return app; -} - -/** - * midori_app_get_settings: - * @app: a #MidoriApp - * - * Retrieves the #MidoriWebSettings of the app. - * - * Return value: the assigned #MidoriWebSettings - **/ -MidoriWebSettings* -midori_app_get_settings (MidoriApp* app) -{ - g_return_val_if_fail (MIDORI_IS_APP (app), NULL); - - MidoriAppPrivate* priv = app->priv; - - return priv->settings; -} - -/** - * midori_app_get_trash: - * @app: a #MidoriApp - * - * Retrieves the #MidoriTrash of the app. - * - * Return value: the assigned #MidoriTrash - **/ -MidoriTrash* -midori_app_get_trash (MidoriApp* app) -{ - g_return_val_if_fail (MIDORI_IS_APP (app), NULL); - - MidoriAppPrivate* priv = app->priv; - - return priv->trash; -} diff --git a/src/midori-app.h b/src/midori-app.h deleted file mode 100644 index b5aaa45c..00000000 --- a/src/midori-app.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_APP_H__ -#define __MIDORI_APP_H__ - -#include - -#include "midori-browser.h" -#include "midori-websettings.h" -#include "midori-trash.h" - -G_BEGIN_DECLS - -#define MIDORI_TYPE_APP \ - (midori_app_get_type ()) -#define MIDORI_APP(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_APP, MidoriApp)) -#define MIDORI_APP_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_APP, MidoriAppClass)) -#define MIDORI_IS_APP(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_APP)) -#define MIDORI_IS_APP_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_APP)) -#define MIDORI_APP_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_APP, MidoriAppClass)) - -typedef struct _MidoriApp MidoriApp; -typedef struct _MidoriAppPrivate MidoriAppPrivate; -typedef struct _MidoriAppClass MidoriAppClass; - -struct _MidoriApp -{ - GObject parent_instance; - - MidoriAppPrivate* priv; -}; - -struct _MidoriAppClass -{ - GObjectClass parent_class; - - /* Signals */ - void - (*add_browser) (MidoriApp* app, - MidoriBrowser* browser); - void - (*quit) (MidoriApp* app); -}; - -GType -midori_app_get_type (void); - -MidoriApp* -midori_app_new (void); - -MidoriWebSettings* -midori_app_get_web_settings (MidoriApp* app); - -MidoriTrash* -midori_app_get_trash (MidoriApp* app); - -G_END_DECLS - -#endif /* __MIDORI_APP_H__ */ diff --git a/src/midori-browser.c b/src/midori-browser.c deleted file mode 100644 index 459818f5..00000000 --- a/src/midori-browser.c +++ /dev/null @@ -1,3639 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - 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 "config.h" - -#include "midori-browser.h" - -#include "webSearch.h" - -#include "main.h" -#include "sokoke.h" -#include "midori-webview.h" -#include "midori-preferences.h" -#include "midori-panel.h" -#include "midori-addons.h" -#include "midori-console.h" -#include "midori-trash.h" - -#include -#include -#include -#include -#include - -G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW) - -struct _MidoriBrowserPrivate -{ - GtkActionGroup* action_group; - GtkWidget* menubar; - GtkWidget* menu_bookmarks; - GtkWidget* menu_tools; - GtkWidget* menu_window; - GtkWidget* popup_bookmark; - GtkWidget* throbber; - GtkWidget* navigationbar; - GtkWidget* button_tab_new; - GtkWidget* button_homepage; - GtkWidget* location_icon; - GtkWidget* location; - GtkWidget* search; - GtkWidget* button_trash; - GtkWidget* button_fullscreen; - GtkWidget* bookmarkbar; - - GtkWidget* panel; - GtkWidget* panel_bookmarks; - GtkWidget* panel_console; - GtkWidget* panel_pageholder; - GtkWidget* notebook; - - GtkWidget* find; - GtkWidget* find_text; - GtkToolItem* find_case; - GtkToolItem* find_highlight; - - GtkWidget* statusbar; - GtkWidget* progressbar; - - gchar* uri; - gchar* title; - gchar* statusbar_text; - MidoriWebSettings* settings; - - KatzeXbelItem* proxy_xbel_folder; - MidoriTrash* trash; -}; - -#define MIDORI_BROWSER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_BROWSER, MidoriBrowserPrivate)) - -enum -{ - PROP_0, - - PROP_MENUBAR, - PROP_NAVIGATIONBAR, - PROP_TAB, - PROP_STATUSBAR, - PROP_SETTINGS, - PROP_STATUSBAR_TEXT, - PROP_TRASH -}; - -enum -{ - WINDOW_OBJECT_CLEARED, - STATUSBAR_TEXT_CHANGED, - ELEMENT_MOTION, - NEW_WINDOW, - - ADD_TAB, - ADD_URI, - ACTIVATE_ACTION, - QUIT, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static void -midori_browser_finalize (GObject* object); - -static void -midori_browser_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec); - -static void -midori_browser_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec); - -static GtkAction* -_action_by_name (MidoriBrowser* browser, - const gchar* name) -{ - MidoriBrowserPrivate* priv = browser->priv; - - return gtk_action_group_get_action (priv->action_group, name); -} - -static void -_action_set_sensitive (MidoriBrowser* browser, - const gchar* name, - gboolean sensitive) -{ - gtk_action_set_sensitive (_action_by_name (browser, name), sensitive); -} - -static void -_action_set_active (MidoriBrowser* browser, - const gchar* name, - gboolean active) -{ - GtkAction* action = _action_by_name (browser, name); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active); -} - -static void -_midori_browser_update_actions (MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - guint n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), n > 1); - _action_set_sensitive (browser, "TabClose", n > 1); - _action_set_sensitive (browser, "TabPrevious", n > 1); - _action_set_sensitive (browser, "TabNext", n > 1); - - if (priv->trash) - { - gboolean trash_empty = midori_trash_is_empty (priv->trash); - _action_set_sensitive (browser, "UndoTabClose", !trash_empty); - _action_set_sensitive (browser, "Trash", !trash_empty); - } -} - -static void -_midori_browser_update_interface (MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean loading = FALSE; - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (web_view) - { - loading = midori_web_view_is_loading (MIDORI_WEB_VIEW (web_view)); - _action_set_sensitive (browser, "ZoomNormal", - midori_web_view_get_zoom_level (MIDORI_WEB_VIEW (web_view)) != 1.0); - if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_view), - "zoom-level")) - { - _action_set_sensitive (browser, "ZoomIn", FALSE); - _action_set_sensitive (browser, "ZoomOut", FALSE); - } - _action_set_sensitive (browser, "Back", - webkit_web_view_can_go_back (WEBKIT_WEB_VIEW (web_view))); - _action_set_sensitive (browser, "Forward", - webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW (web_view))); - _action_set_sensitive (browser, "Reload", !loading); - _action_set_sensitive (browser, "Stop", loading); - _action_set_sensitive (browser, "Print", TRUE); - } - else - _action_set_sensitive (browser, "Print", FALSE); - - GtkAction* action = gtk_action_group_get_action (priv->action_group, - "ReloadStop"); - if (!loading) - { - gtk_widget_set_sensitive (priv->throbber, FALSE); - g_object_set (action, - "stock-id", GTK_STOCK_REFRESH, - "tooltip", _("Reload the current page"), NULL); - gtk_widget_hide (priv->progressbar); - } - else - { - gtk_widget_set_sensitive (priv->throbber, TRUE); - g_object_set (action, - "stock-id", GTK_STOCK_STOP, - "tooltip", _("Stop loading the current page"), NULL); - gtk_widget_show (priv->progressbar); - } - katze_throbber_set_animated (KATZE_THROBBER (priv->throbber), loading); - gtk_image_set_from_stock (GTK_IMAGE (priv->location_icon), - GTK_STOCK_FILE, GTK_ICON_SIZE_MENU); -} - -static GtkWidget* -_midori_browser_scrolled_for_child (MidoriBrowser* browser, - GtkWidget* child) -{ - GtkWidget* scrolled = gtk_widget_get_parent (child); - if (GTK_IS_VIEWPORT (scrolled)) - scrolled = gtk_widget_get_parent (scrolled); - return scrolled; -} - -static GtkWidget* -_midori_browser_child_for_scrolled (MidoriBrowser* browser, - GtkWidget* scrolled) -{ - GtkWidget* child = gtk_bin_get_child (GTK_BIN (scrolled)); - if (GTK_IS_VIEWPORT (child)) - child = gtk_bin_get_child (GTK_BIN (child)); - return child; -} - -static void -_midori_browser_set_statusbar_text (MidoriBrowser* browser, - const gchar* text) -{ - MidoriBrowserPrivate* priv = browser->priv; - - katze_assign (priv->statusbar_text, g_strdup (text)); - gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar), 1); - gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar), 1, - priv->statusbar_text ? priv->statusbar_text : ""); -} - -static void -_midori_browser_set_current_page_smartly (MidoriBrowser* browser, - gint n) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean open_tabs_in_the_background; - g_object_get (priv->settings, "open-tabs-in-the-background", - &open_tabs_in_the_background, NULL); - if (!open_tabs_in_the_background) - midori_browser_set_current_page (browser, n); -} - -static void -_midori_browser_update_progress (MidoriBrowser* browser, - gint progress) -{ - MidoriBrowserPrivate* priv = browser->priv; - - if (progress > -1) - { - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progressbar), - progress ? progress / 100.0 : 0); - gchar* message = g_strdup_printf (_("%d%% loaded"), progress); - gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progressbar), - message); - g_free (message); - } - else - { - gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->progressbar)); - gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progressbar), - NULL); - } -} - -static void -midori_web_view_window_object_cleared_cb (GtkWidget* web_view, - WebKitWebFrame* web_frame, - JSGlobalContextRef js_context, - JSObjectRef js_window, - MidoriBrowser* browser) -{ - g_signal_emit (browser, signals[WINDOW_OBJECT_CLEARED], 0, - web_frame, js_context, js_window); -} - -static void -midori_web_view_load_started_cb (GtkWidget* web_view, - WebKitWebFrame* web_frame, - MidoriBrowser* browser) -{ - if (web_view == midori_browser_get_current_web_view (browser)) - { - _midori_browser_update_interface (browser); - _midori_browser_set_statusbar_text (browser, NULL); - } -} - -static void -midori_web_view_progress_started_cb (GtkWidget* web_view, - guint progress, - MidoriBrowser* browser) -{ - if (web_view == midori_browser_get_current_web_view (browser)) - _midori_browser_update_progress (browser, progress); -} - -static void -midori_web_view_progress_changed_cb (GtkWidget* web_view, - guint progress, - MidoriBrowser* browser) -{ - if (web_view == midori_browser_get_current_web_view (browser)) - _midori_browser_update_progress (browser, progress); -} - -static void -midori_web_view_progress_done_cb (GtkWidget* web_view, - guint progress, - MidoriBrowser* browser) -{ - if (web_view == midori_browser_get_current_web_view (browser)) - _midori_browser_update_progress (browser, progress); -} - -static void -midori_web_view_load_done_cb (GtkWidget* web_view, - WebKitWebFrame* web_frame, - MidoriBrowser* browser) -{ - if (web_view == midori_browser_get_current_web_view (browser)) - { - _midori_browser_update_interface (browser); - _midori_browser_set_statusbar_text (browser, NULL); - } -} - -static void -midori_web_view_title_changed_cb (GtkWidget* web_view, - WebKitWebFrame* web_frame, - const gchar* title, - MidoriBrowser* browser) -{ - if (web_view == midori_browser_get_current_web_view (browser)) - { - const gchar* title = midori_web_view_get_display_title ( - MIDORI_WEB_VIEW (web_view)); - gchar* window_title = g_strconcat (title, " - ", - g_get_application_name (), NULL); - gtk_window_set_title (GTK_WINDOW (browser), window_title); - g_free (window_title); - } -} - -static void -midori_web_view_statusbar_text_changed_cb (MidoriWebView* web_view, - const gchar* text, - MidoriBrowser* browser) -{ - _midori_browser_set_statusbar_text (browser, text); -} - -static void -midori_web_view_element_motion_cb (MidoriWebView* web_View, - const gchar* link_uri, - MidoriBrowser* browser) -{ - _midori_browser_set_statusbar_text (browser, link_uri); -} - -static void -midori_web_view_load_committed_cb (GtkWidget* web_view, - WebKitWebFrame* web_frame, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - if (web_view == midori_browser_get_current_web_view (browser)) - { - const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); - gtk_entry_set_text (GTK_ENTRY (priv->location), uri); - _midori_browser_set_statusbar_text (browser, NULL); - } -} - -static gboolean -midori_web_view_console_message_cb (GtkWidget* web_view, - const gchar* message, - gint line, - const gchar* source_id, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - midori_console_add (MIDORI_CONSOLE (priv->panel_console), - message, line, source_id); - return TRUE; -} - -static void -midori_web_view_populate_popup_cb (GtkWidget* web_view, - GtkWidget* menu, - MidoriBrowser* browser) -{ - const gchar* uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); - if (uri) - { - // TODO: bookmark link - } - - if (webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) - { - // TODO: view selection source - } - - if (!uri && !webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) - { - GtkAction* action = _action_by_name (browser, "UndoTabClose"); - GtkWidget* menuitem = gtk_action_create_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - menuitem = gtk_separator_menu_item_new (); - gtk_widget_show (menuitem); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - action = _action_by_name (browser, "BookmarkAdd"); - menuitem = gtk_action_create_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - action = _action_by_name (browser, "SaveAs"); - menuitem = gtk_action_create_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - action = _action_by_name (browser, "SourceView"); - menuitem = gtk_action_create_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - action = _action_by_name (browser, "Print"); - menuitem = gtk_action_create_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - } -} - -static gboolean -midori_web_view_leave_notify_event_cb (GtkWidget* web_view, - GdkEventCrossing* event, - MidoriBrowser* browser) -{ - _midori_browser_set_statusbar_text (browser, NULL); - return TRUE; -} - -static void -midori_web_view_new_tab_cb (GtkWidget* web_view, - const gchar* uri, - MidoriBrowser* browser) -{ - gint n = midori_browser_add_uri (browser, uri); - _midori_browser_set_current_page_smartly (browser, n); -} - -static void -midori_web_view_new_window_cb (GtkWidget* web_view, - const gchar* uri, - MidoriBrowser* browser) -{ - g_signal_emit (browser, signals[NEW_WINDOW], 0, uri); -} - -static void -midori_web_view_close_cb (GtkWidget* web_view, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - if (priv->proxy_xbel_folder) - { - KatzeXbelItem* xbel_item = midori_web_view_get_proxy_xbel_item ( - MIDORI_WEB_VIEW (web_view)); - const gchar* uri = katze_xbel_bookmark_get_href (xbel_item); - if (priv->trash && uri && *uri) - midori_trash_prepend_xbel_item (priv->trash, xbel_item); - katze_xbel_folder_remove_item (priv->proxy_xbel_folder, xbel_item); - katze_xbel_item_unref (xbel_item); - } - GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, web_view); - guint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); - gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), n); - - _midori_browser_update_actions (browser); -} - -static gboolean -midori_web_view_destroy_cb (GtkWidget* widget, - MidoriBrowser* browser) -{ - _midori_browser_update_actions (browser); - return FALSE; -} - -static void -midori_cclosure_marshal_VOID__OBJECT_POINTER_POINTER (GClosure* closure, - GValue* return_value, - guint n_param_values, - const GValue* param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gboolean(*GMarshalFunc_VOID__OBJECT_POINTER_POINTER) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer arg_3, - gpointer data2); - register GMarshalFunc_VOID__OBJECT_POINTER_POINTER callback; - register GCClosure* cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__OBJECT_POINTER_POINTER) (marshal_data - ? marshal_data : cc->callback); - - callback (data1, - g_value_get_object (param_values + 1), - g_value_get_pointer (param_values + 2), - g_value_get_pointer (param_values + 3), - data2); -} - -static void -midori_cclosure_marshal_INT__OBJECT (GClosure* closure, - GValue* return_value, - guint n_param_values, - const GValue* param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gint(*GMarshalFunc_INT__OBJECT) (gpointer data1, - gpointer arg_1, - gpointer data2); - register GMarshalFunc_INT__OBJECT callback; - register GCClosure* cc = (GCClosure*) closure; - register gpointer data1, data2; - gint v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 2); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_INT__OBJECT) (marshal_data - ? marshal_data : cc->callback); - v_return = callback (data1, - g_value_get_object (param_values + 1), - data2); - g_value_set_int (return_value, v_return); -} - -static void -midori_cclosure_marshal_INT__STRING (GClosure* closure, - GValue* return_value, - guint n_param_values, - const GValue* param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gint(*GMarshalFunc_INT__STRING) (gpointer data1, - const gchar* arg_1, - gpointer data2); - register GMarshalFunc_INT__STRING callback; - register GCClosure* cc = (GCClosure*) closure; - register gpointer data1, data2; - gint v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 2); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_INT__STRING) (marshal_data - ? marshal_data : cc->callback); - v_return = callback (data1, - g_value_get_string (param_values + 1), - data2); - g_value_set_int (return_value, v_return); -} - -static void -midori_browser_class_init (MidoriBrowserClass* class) -{ - signals[WINDOW_OBJECT_CLEARED] = g_signal_new ( - "window-object-cleared", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriBrowserClass, window_object_cleared), - 0, - NULL, - midori_cclosure_marshal_VOID__OBJECT_POINTER_POINTER, - G_TYPE_NONE, 3, - WEBKIT_TYPE_WEB_FRAME, - G_TYPE_POINTER, - G_TYPE_POINTER); - - signals[STATUSBAR_TEXT_CHANGED] = g_signal_new ( - "statusbar-text-changed", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriBrowserClass, statusbar_text_changed), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - signals[ELEMENT_MOTION] = g_signal_new ( - "element-motion", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriBrowserClass, element_motion), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - signals[NEW_WINDOW] = g_signal_new ( - "new-window", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriBrowserClass, new_window), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - signals[ADD_TAB] = g_signal_new ( - "add-tab", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriBrowserClass, add_tab), - 0, - NULL, - midori_cclosure_marshal_INT__OBJECT, - G_TYPE_INT, 1, - GTK_TYPE_WIDGET); - - signals[ADD_URI] = g_signal_new ( - "add-uri", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriBrowserClass, add_uri), - 0, - NULL, - midori_cclosure_marshal_INT__STRING, - G_TYPE_INT, 1, - G_TYPE_STRING); - - signals[ACTIVATE_ACTION] = g_signal_new ( - "activate-action", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriBrowserClass, activate_action), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - signals[QUIT] = g_signal_new ( - "quit", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriBrowserClass, quit), - 0, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - class->add_tab = midori_browser_add_tab; - class->add_uri = midori_browser_add_uri; - class->activate_action = midori_browser_activate_action; - class->quit = midori_browser_quit; - - GObjectClass* gobject_class = G_OBJECT_CLASS (class); - gobject_class->finalize = midori_browser_finalize; - gobject_class->set_property = midori_browser_set_property; - gobject_class->get_property = midori_browser_get_property; - - GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; - - g_object_class_install_property (gobject_class, - PROP_MENUBAR, - g_param_spec_object ( - "menubar", - _("Menubar"), - _("The menubar"), - GTK_TYPE_MENU_BAR, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_NAVIGATIONBAR, - g_param_spec_object ( - "navigationbar", - _("Navigationbar"), - _("The navigationbar"), - GTK_TYPE_TOOLBAR, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_TAB, - g_param_spec_object ( - "tab", - _("Tab"), - _("The current tab"), - GTK_TYPE_WIDGET, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_STATUSBAR, - g_param_spec_object ( - "statusbar", - _("Statusbar"), - _("The statusbar"), - GTK_TYPE_STATUSBAR, - G_PARAM_READABLE)); - - /** - * MidoriBrowser:settings: - * - * An associated settings instance that is shared among all web views. - * - * Setting this value is propagated to every present web view. Also - * every newly created web view will use this instance automatically. - */ - g_object_class_install_property (gobject_class, - PROP_SETTINGS, - g_param_spec_object ( - "settings", - _("Settings"), - _("The associated settings"), - MIDORI_TYPE_WEB_SETTINGS, - G_PARAM_READWRITE)); - - /** - * MidoriBrowser:statusbar-text: - * - * The text that is displayed in the statusbar. - * - * This value reflects changes to the text visible in the statusbar, such - * as the uri of a hyperlink the mouse hovers over or the description of - * a menuitem. - * - * Setting this value changes the displayed text until the next change. - */ - g_object_class_install_property (gobject_class, - PROP_STATUSBAR_TEXT, - g_param_spec_string ( - "statusbar-text", - _("Statusbar Text"), - _("The text that is displayed in the statusbar"), - "", - flags)); - - /** - * MidoriBrowser:trash: - * - * The trash, that collects all closed tabs and windows. - * - * This is actually a reference to a trash instance, so if a trash should - * be used it must be initially set. - * - * Note: In the future the trash might collect other types of items. - */ - g_object_class_install_property (gobject_class, - PROP_TRASH, - g_param_spec_object ( - "trash", - _("Trash"), - _("The trash, collecting recently closed tabs and windows"), - MIDORI_TYPE_TRASH, - G_PARAM_READWRITE)); - - g_type_class_add_private (class, sizeof (MidoriBrowserPrivate)); -} - -static void -_action_window_new_activate (GtkAction* action, - MidoriBrowser* browser) -{ - g_signal_emit (browser, signals[NEW_WINDOW], 0, ""); -} - -static void -_action_tab_new_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gint n = midori_browser_add_uri (browser, ""); - midori_browser_set_current_page (browser, n); - gtk_widget_grab_focus (priv->location); -} - -static void -_action_open_activate (GtkAction* action, - MidoriBrowser* browser) -{ - static gchar* last_dir = NULL; - gchar* uri = NULL; - gboolean folder_set = FALSE; - GtkWidget* dialog = gtk_file_chooser_dialog_new ( - ("Open file"), GTK_WINDOW (browser), - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_OPEN); - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (browser)); - - // base the start folder on the current web view's uri if it is local - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (web_view) - g_object_get (web_view, "uri", &uri, NULL); - if (uri) - { - gchar* filename = g_filename_from_uri (uri, NULL, NULL); - if (filename) - { - gchar* dirname = g_path_get_dirname (filename); - if (dirname && g_file_test (dirname, G_FILE_TEST_IS_DIR)) - { - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dirname); - folder_set = TRUE; - } - - g_free (dirname); - g_free (filename); - } - g_free (uri); - } - - if (!folder_set && last_dir && *last_dir) - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), last_dir); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { - uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); - gchar* folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); - g_object_set (web_view, "uri", uri, NULL); - - g_free (last_dir); - last_dir = folder; - g_free (uri); - } - gtk_widget_destroy (dialog); -} - -static void -_action_tab_close_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* widget = midori_browser_get_current_tab (browser); - GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); - gtk_widget_destroy (scrolled); -} - -static void -_action_window_close_activate (GtkAction* action, - MidoriBrowser* browser) -{ - gtk_widget_destroy (GTK_WIDGET (browser)); -} - -static void -_action_print_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* web_view = midori_browser_get_current_tab (browser); - if (web_view) - webkit_web_view_execute_script (WEBKIT_WEB_VIEW (web_view), "print ();"); -} - -static void -_action_quit_activate (GtkAction* action, - MidoriBrowser* browser) -{ - g_signal_emit (browser, signals[QUIT], 0); -} - -static void -_action_edit_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); - gboolean can_cut = FALSE, can_copy = FALSE, can_paste = FALSE; - gboolean has_selection; - - if (WEBKIT_IS_WEB_VIEW (widget)) - { - WebKitWebView* web_view = WEBKIT_WEB_VIEW (widget); - can_cut = webkit_web_view_can_cut_clipboard (web_view); - can_copy = webkit_web_view_can_copy_clipboard (web_view); - can_paste = webkit_web_view_can_paste_clipboard (web_view); - } - else if (GTK_IS_EDITABLE (widget)) - { - GtkEditable* editable = GTK_EDITABLE (widget); - has_selection = gtk_editable_get_selection_bounds (editable, NULL, NULL); - can_cut = has_selection && gtk_editable_get_editable (editable); - can_copy = has_selection; - can_paste = gtk_editable_get_editable (editable); - } - - _action_set_sensitive (browser, "Cut", can_cut); - _action_set_sensitive (browser, "Copy", can_copy); - _action_set_sensitive (browser, "Paste", can_paste); - _action_set_sensitive (browser, "Delete", can_cut); - _action_set_sensitive (browser, "SelectAll", FALSE); -} - -static void -_action_cut_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); - if (G_LIKELY (widget)) - g_signal_emit_by_name (widget, "cut-clipboard"); -} - -static void -_action_copy_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); - if (G_LIKELY (widget)) - g_signal_emit_by_name (widget, "copy-clipboard"); -} - -static void -_action_paste_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); - if (G_LIKELY (widget)) - g_signal_emit_by_name (widget, "paste-clipboard"); -} - -static void -_action_delete_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); - if (G_LIKELY (widget)) - { - if (WEBKIT_IS_WEB_VIEW (widget)) - webkit_web_view_delete_selection (WEBKIT_WEB_VIEW (widget)); - else if (GTK_IS_EDITABLE(widget)) - gtk_editable_delete_selection (GTK_EDITABLE (widget)); - } -} - -static void -_action_select_all_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); - if (G_LIKELY (widget)) - { - if (GTK_IS_EDITABLE (widget)) - gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1); - else - g_signal_emit_by_name (widget, "select-all"); - } -} - -static void -_action_find_activate(GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - if (GTK_WIDGET_VISIBLE (priv->find)) - { - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (web_view)); - gtk_toggle_tool_button_set_active ( - GTK_TOGGLE_TOOL_BUTTON (priv->find_highlight), FALSE); - gtk_widget_hide (priv->find); - } - else - { - GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FIND, - GTK_ICON_SIZE_MENU); - sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->find_text), - SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE (icon)); - gtk_entry_set_text (GTK_ENTRY (priv->find_text), ""); - gtk_widget_show (priv->find); - gtk_widget_grab_focus (GTK_WIDGET (priv->find_text)); - } -} - -static void -_midori_browser_find (MidoriBrowser* browser, - gboolean forward) -{ - MidoriBrowserPrivate* priv = browser->priv; - - const gchar* text = gtk_entry_get_text (GTK_ENTRY (priv->find_text)); - const gboolean case_sensitive = gtk_toggle_tool_button_get_active ( - GTK_TOGGLE_TOOL_BUTTON(priv->find_case)); - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (GTK_WIDGET_VISIBLE (priv->find)) - webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (web_view)); - gboolean found = webkit_web_view_search_text (WEBKIT_WEB_VIEW (web_view), - text, case_sensitive, forward, TRUE); - if (GTK_WIDGET_VISIBLE (priv->find)) - { - GtkWidget* icon; - if (found) - icon = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); - else - icon = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU); - sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->find_text), - SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); - webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (web_view), text, - case_sensitive, 0); - const gboolean highlight = gtk_toggle_tool_button_get_active ( - GTK_TOGGLE_TOOL_BUTTON (priv->find_highlight)); - webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (web_view), - highlight); - } -} - -static void -_action_find_next_activate (GtkAction* action, - MidoriBrowser* browser) -{ - _midori_browser_find (browser, TRUE); -} - -static void -_action_find_previous_activate (GtkAction* action, - MidoriBrowser* browser) -{ - _midori_browser_find (browser, FALSE); -} - -static void -_find_highlight_toggled (GtkToggleToolButton* toolitem, - MidoriBrowser* browser) -{ - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - const gboolean highlight = gtk_toggle_tool_button_get_active (toolitem); - webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (web_view), - highlight); -} - -static void -midori_browser_find_button_close_clicked_cb (GtkWidget* widget, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gtk_widget_hide (priv->find); -} - -static void -midori_browser_navigationbar_notify_style_cb (GObject* object, - GParamSpec* arg1, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - MidoriToolbarStyle toolbar_style; - GtkToolbarStyle gtk_toolbar_style; - - g_object_get (priv->settings, "toolbar-style", &toolbar_style, NULL); - if (toolbar_style == MIDORI_TOOLBAR_DEFAULT) - { - g_object_get (priv->settings, - "gtk-toolbar-style", >k_toolbar_style, NULL); - gtk_toolbar_set_style (GTK_TOOLBAR (priv->navigationbar), - gtk_toolbar_style); - } -} - -static void -midori_browser_menu_trash_item_activate_cb (GtkWidget* menuitem, - MidoriBrowser* browser) -{ - // Create a new web view with an uri which has been closed before - KatzeXbelItem* item = g_object_get_data (G_OBJECT (menuitem), - "KatzeXbelItem"); - const gchar* uri = katze_xbel_bookmark_get_href (item); - gint n = midori_browser_add_uri (browser, uri); - midori_browser_set_current_page (browser, n); - katze_xbel_item_unref (item); -} - -static void -midori_browser_menu_trash_activate_cb (GtkWidget* widget, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkWidget* menu = gtk_menu_new (); - guint n = midori_trash_get_n_items (priv->trash); - GtkWidget* menuitem; - guint i; - for (i = 0; i < n; i++) - { - KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, i); - const gchar* title = katze_xbel_item_get_title (item); - const gchar* uri = katze_xbel_bookmark_get_href (item); - menuitem = gtk_image_menu_item_new_with_label (title ? title : uri); - // FIXME: Get the real icon - GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); - gtk_menu_shell_append(GTK_MENU_SHELL (menu), menuitem); - g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_browser_menu_trash_item_activate_cb), browser); - gtk_widget_show (menuitem); - } - - menuitem = gtk_separator_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - GtkAction* action = gtk_action_group_get_action (priv->action_group, - "TrashEmpty"); - menuitem = gtk_action_create_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - if (GTK_IS_MENU_ITEM (widget)) - gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), menu); - else - sokoke_widget_popup (widget, GTK_MENU (menu), NULL, - SOKOKE_MENU_POSITION_RIGHT); -} - -static void -_action_preferences_activate (GtkAction* action, - MidoriBrowser* browser) -{ - // Show the preferences dialog. Create it if necessary. - static GtkWidget* dialog = NULL; - if (GTK_IS_DIALOG (dialog)) - gtk_window_present (GTK_WINDOW (dialog)); - else - { - MidoriBrowserPrivate* priv = browser->priv; - - dialog = midori_preferences_new (GTK_WINDOW (browser), - priv->settings); - gtk_widget_show (dialog); - } -} - -static void -_action_navigationbar_activate (GtkToggleAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean active = gtk_toggle_action_get_active (action); - g_object_set (priv->settings, "show-navigationbar", active, NULL); - sokoke_widget_set_visible (priv->navigationbar, active); -} - -static void -_action_bookmarkbar_activate (GtkToggleAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean active = gtk_toggle_action_get_active (action); - g_object_set (priv->settings, "show-bookmarkbar", active, NULL); - sokoke_widget_set_visible (priv->bookmarkbar, active); -} - -static void -_action_statusbar_activate (GtkToggleAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean active = gtk_toggle_action_get_active (action); - g_object_set (priv->settings, "show-statusbar", active, NULL); - sokoke_widget_set_visible (priv->statusbar, active); -} - -static void -_action_reload_stop_activate (GtkAction* action, - MidoriBrowser* browser) -{ - gchar* stock_id; - g_object_get (action, "stock-id", &stock_id, NULL); - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - // Refresh or stop, depending on the stock id - if (!strcmp (stock_id, GTK_STOCK_REFRESH)) - { - /*GdkModifierType state = (GdkModifierType)0; - gint x, y; - gdk_window_get_pointer (NULL, &x, &y, &state); - gboolean from_cache = state & GDK_SHIFT_MASK;*/ - webkit_web_view_reload (WEBKIT_WEB_VIEW (web_view)); - } - else - webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view)); - g_free (stock_id); -} - -static void -_action_zoom_in_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (web_view && g_object_class_find_property ( - G_OBJECT_GET_CLASS (web_view), "zoom-level")) - { - MidoriBrowserPrivate* priv = browser->priv; - - gfloat zoom_level, zoom_step; - g_object_get (web_view, "zoom-level", &zoom_level, NULL); - g_object_get (priv->settings, "zoom-step", &zoom_step, NULL); - g_object_set (web_view, "zoom-level", zoom_level + zoom_step, NULL); - } -} - -static void -_action_zoom_out_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (web_view && g_object_class_find_property ( - G_OBJECT_GET_CLASS (web_view), "zoom-level")) - { - MidoriBrowserPrivate* priv = browser->priv; - - gfloat zoom_level, zoom_step; - g_object_get (web_view, "zoom-level", &zoom_level, NULL); - g_object_get (priv->settings, "zoom-step", &zoom_step, NULL); - g_object_set (web_view, "zoom-level", zoom_level - zoom_step, NULL); - } -} - -static void -_action_zoom_normal_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (web_view && g_object_class_find_property ( - G_OBJECT_GET_CLASS (web_view), "zoom-level")) - g_object_set (web_view, "zoom-level", 1.0, NULL); -} - -/*static void -_action_source_view_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - gchar* source = webkit_web_view_copy_source (WEBKIT_WEB_VIEW (web_view)); - webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (web_view), source, ""); - g_free (source); -}*/ - -static void -_action_fullscreen_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GdkWindowState state = gdk_window_get_state (GTK_WIDGET (browser)->window); - if (state & GDK_WINDOW_STATE_FULLSCREEN) - gtk_window_unfullscreen (GTK_WINDOW (browser)); - else - gtk_window_fullscreen (GTK_WINDOW (browser)); -} - -static void -_action_back_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - webkit_web_view_go_back (WEBKIT_WEB_VIEW (web_view)); -} - -static void -_action_forward_activate (GtkAction* action, - MidoriBrowser* browser) -{ - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - webkit_web_view_go_forward (WEBKIT_WEB_VIEW (web_view)); -} - -static void -_action_homepage_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gchar* homepage; - - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - g_object_get (priv->settings, "homepage", &homepage, NULL); - g_object_set (web_view, "uri", homepage, NULL); - g_free (homepage); -} - -static gboolean -midori_browser_location_key_press_event_cb (GtkWidget* widget, - GdkEventKey* event, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - gchar* location_entry_search; - - switch (event->keyval) - { - case GDK_ISO_Enter: - case GDK_KP_Enter: - case GDK_Return: - { - const gchar* uri = gtk_entry_get_text (GTK_ENTRY (widget)); - if (uri) - { - g_object_get (priv->settings, "location-entry-search", - &location_entry_search, NULL); - gchar* new_uri = sokoke_magic_uri (uri, location_entry_search); - g_free (location_entry_search); - // TODO: Use new_uri intermediately when completion is better - /* TODO Completion should be generated from history, that is - the uri as well as the title. */ - sokoke_entry_append_completion (GTK_ENTRY (widget), uri); - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - g_object_set (web_view, "uri", new_uri, NULL); - g_free (new_uri); - gtk_widget_grab_focus (web_view); - } - return TRUE; - } - case GDK_Escape: - { - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - const gchar* uri = midori_web_view_get_display_uri ( - MIDORI_WEB_VIEW (web_view)); - gtk_entry_set_text (GTK_ENTRY (widget), uri); - return TRUE; - } - } - return FALSE; -} - -static void -_action_location_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - if (!GTK_WIDGET_VISIBLE (priv->navigationbar)) - gtk_widget_show (priv->navigationbar); - gtk_widget_grab_focus (priv->location); -} - -static gboolean -midori_browser_location_focus_out_event_cb (GtkWidget* widget, - GdkEventFocus* event, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean show_navigationbar; - g_object_get (priv->settings, - "show-navigationbar", &show_navigationbar, - NULL); - if (!show_navigationbar) - gtk_widget_hide (priv->navigationbar); - return FALSE; -} - -static void -_action_search_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - if (!GTK_WIDGET_VISIBLE (priv->search)) - gtk_widget_show (priv->search); - if (!GTK_WIDGET_VISIBLE (priv->navigationbar)) - gtk_widget_show (priv->navigationbar); - gtk_widget_grab_focus (priv->search); -} - -static gboolean -midori_browser_search_focus_out_event_cb (GtkWidget* widget, - GdkEventFocus* event, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean show_navigationbar; - gboolean show_web_search; - g_object_get (priv->settings, - "show-navigationbar", &show_navigationbar, - "show-web-search", &show_web_search, - NULL); - if (!show_navigationbar) - gtk_widget_hide (priv->navigationbar); - if (!show_web_search) - gtk_widget_hide (priv->search); - return FALSE; -} - -static void -midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, - KatzeXbelItem* bookmark) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean new_bookmark = !bookmark; - GtkWidget* dialog = gtk_dialog_new_with_buttons ( - new_bookmark ? _("New bookmark") : _("Edit bookmark"), - GTK_WINDOW (browser), - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - new_bookmark ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - gtk_window_set_icon_name (GTK_WINDOW (dialog), - new_bookmark ? GTK_STOCK_ADD : GTK_STOCK_REMOVE); - gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); - gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5); - GtkSizeGroup* sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); - - if (new_bookmark) - bookmark = katze_xbel_bookmark_new (); - - GtkWidget* hbox = gtk_hbox_new (FALSE, 8); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); - GtkWidget* label = gtk_label_new_with_mnemonic (_("_Title:")); - gtk_size_group_add_widget (sizegroup, label); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_title = gtk_entry_new (); - gtk_entry_set_activates_default (GTK_ENTRY (entry_title), TRUE); - if (!new_bookmark) - { - const gchar* title = katze_xbel_item_get_title (bookmark); - gtk_entry_set_text (GTK_ENTRY (entry_title), title ? title : ""); - } - gtk_box_pack_start (GTK_BOX (hbox), entry_title, TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); - gtk_widget_show_all (hbox); - - hbox = gtk_hbox_new (FALSE, 8); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); - label = gtk_label_new_with_mnemonic (_("_Description:")); - gtk_size_group_add_widget (sizegroup, label); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_desc = gtk_entry_new (); - gtk_entry_set_activates_default (GTK_ENTRY (entry_desc), TRUE); - if (!new_bookmark) - { - const gchar* desc = katze_xbel_item_get_desc (bookmark); - gtk_entry_set_text (GTK_ENTRY (entry_desc), desc ? desc : ""); - } - gtk_box_pack_start (GTK_BOX (hbox), entry_desc, TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); - gtk_widget_show_all (hbox); - - GtkWidget* entry_uri = NULL; - if (katze_xbel_item_is_bookmark (bookmark)) - { - hbox = gtk_hbox_new (FALSE, 8); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); - label = gtk_label_new_with_mnemonic (_("_URL:")); - gtk_size_group_add_widget (sizegroup, label); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - entry_uri = gtk_entry_new (); - gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE); - if (!new_bookmark) - gtk_entry_set_text (GTK_ENTRY (entry_uri), - katze_xbel_bookmark_get_href (bookmark)); - gtk_box_pack_start (GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); - gtk_widget_show_all (hbox); - } - - GtkWidget* combo_folder = NULL; - if (new_bookmark) - { - hbox = gtk_hbox_new (FALSE, 8); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); - label = gtk_label_new_with_mnemonic (_("_Folder:")); - gtk_size_group_add_widget (sizegroup, label); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - combo_folder = gtk_combo_box_new_text (); - gtk_combo_box_append_text (GTK_COMBO_BOX (combo_folder), _("Root")); - gtk_widget_set_sensitive (combo_folder, FALSE); - gtk_box_pack_start (GTK_BOX (hbox), combo_folder, TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); - gtk_widget_show_all (hbox); - } - - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { - katze_xbel_item_set_title (bookmark, - gtk_entry_get_text (GTK_ENTRY (entry_title))); - katze_xbel_item_set_desc (bookmark, - gtk_entry_get_text(GTK_ENTRY(entry_desc))); - if (katze_xbel_item_is_bookmark (bookmark)) - katze_xbel_bookmark_set_href (bookmark, - gtk_entry_get_text (GTK_ENTRY (entry_uri))); - - // FIXME: We want to choose a folder - if (new_bookmark) - { - katze_xbel_folder_append_item (bookmarks, bookmark); - GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); - GtkTreeModel* treemodel = gtk_tree_view_get_model (treeview); - GtkTreeIter iter; - gtk_tree_store_insert_with_values (GTK_TREE_STORE (treemodel), - &iter, NULL, G_MAXINT, 0, bookmark, -1); - katze_xbel_item_ref (bookmark); - } - - // FIXME: update navigationbar - // FIXME: Update panel in other windows - } - gtk_widget_destroy (dialog); -} - -static void -midori_panel_bookmarks_row_activated_cb (GtkTreeView* treeview, - GtkTreePath* path, - GtkTreeViewColumn* column, - MidoriBrowser* browser) -{ - GtkTreeModel* model = gtk_tree_view_get_model (treeview); - GtkTreeIter iter; - if (gtk_tree_model_get_iter (model, &iter, path)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - if (katze_xbel_item_is_bookmark (item)) - { - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - const gchar* uri = katze_xbel_bookmark_get_href (item); - g_object_set (web_view, "uri", uri, NULL); - } - } -} - -static void -midori_panel_bookmarks_cursor_or_row_changed_cb (GtkTreeView* treeview, - MidoriBrowser* browser) -{ - GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); - if (selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - - gboolean is_separator = katze_xbel_item_is_separator (item); - _action_set_sensitive (browser, "BookmarkEdit", !is_separator); - _action_set_sensitive (browser, "BookmarkDelete", TRUE); - } - else - { - _action_set_sensitive (browser, "BookmarkEdit", FALSE); - _action_set_sensitive (browser, "BookmarkDelete", FALSE); - } - } -} - -static void -_midori_panel_bookmarks_popup (GtkWidget* widget, - GdkEventButton* event, - KatzeXbelItem* item, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean is_bookmark = katze_xbel_item_is_bookmark (item); - - _action_set_sensitive (browser, "BookmarkOpen", is_bookmark); - _action_set_sensitive (browser, "BookmarkOpenTab", is_bookmark); - _action_set_sensitive (browser, "BookmarkOpenWindow", is_bookmark); - - sokoke_widget_popup (widget, GTK_MENU (priv->popup_bookmark), - event, SOKOKE_MENU_POSITION_CURSOR); -} - -static gboolean -midori_panel_bookmarks_button_release_event_cb (GtkWidget* widget, - GdkEventButton* event, - MidoriBrowser* browser) -{ - if (event->button != 2 && event->button != 3) - return FALSE; - - GtkTreeSelection* selection = gtk_tree_view_get_selection ( - GTK_TREE_VIEW (widget)); - if (selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - if (event->button == 2 && katze_xbel_item_is_bookmark (item)) - { - const gchar* uri = katze_xbel_bookmark_get_href (item); - gint n = midori_browser_add_uri (browser, uri); - midori_browser_set_current_page (browser, n); - } - else - _midori_panel_bookmarks_popup (widget, event, item, browser); - return TRUE; - } - } - return FALSE; -} - -static void -midori_panel_bookmarks_popup_menu_cb (GtkWidget* widget, - MidoriBrowser* browser) -{ - GtkTreeSelection* selection = gtk_tree_view_get_selection ( - GTK_TREE_VIEW (widget)); - if (selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - _midori_panel_bookmarks_popup (widget, NULL, item, browser); - } - } -} - -static void -_tree_store_insert_folder (GtkTreeStore* treestore, - GtkTreeIter* parent, - KatzeXbelItem* folder) -{ - guint n = katze_xbel_folder_get_n_items (folder); - guint i; - for (i = 0; i < n; i++) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i); - GtkTreeIter iter; - gtk_tree_store_insert_with_values (treestore, &iter, parent, n, - 0, item, -1); - katze_xbel_item_ref (item); - if (katze_xbel_item_is_folder (item)) - _tree_store_insert_folder (treestore, &iter, item); - } -} - -static void -midori_browser_bookmarks_item_render_icon_cb (GtkTreeViewColumn* column, - GtkCellRenderer* renderer, - GtkTreeModel* model, - GtkTreeIter* iter, - GtkWidget* treeview) -{ - KatzeXbelItem* item; - gtk_tree_model_get (model, iter, 0, &item, -1); - - if (G_UNLIKELY (!item)) - return; - if (G_UNLIKELY (!katze_xbel_item_get_parent (item))) - { - gtk_tree_store_remove (GTK_TREE_STORE (model), iter); - katze_xbel_item_unref (item); - return; - } - - // TODO: Would it be better to not do this on every redraw? - GdkPixbuf* pixbuf = NULL; - if (katze_xbel_item_is_bookmark (item)) - pixbuf = gtk_widget_render_icon (treeview, STOCK_BOOKMARK, - GTK_ICON_SIZE_MENU, NULL); - else if (katze_xbel_item_is_folder (item)) - pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY, - GTK_ICON_SIZE_MENU, NULL); - g_object_set (renderer, "pixbuf", pixbuf, NULL); - if (pixbuf) - g_object_unref (pixbuf); -} - -static void -midori_browser_bookmarks_item_render_text_cb (GtkTreeViewColumn* column, - GtkCellRenderer* renderer, - GtkTreeModel* model, - GtkTreeIter* iter, - GtkWidget* treeview) -{ - KatzeXbelItem* item; - gtk_tree_model_get (model, iter, 0, &item, -1); - - if (G_UNLIKELY (!item)) - return; - if (G_UNLIKELY (!katze_xbel_item_get_parent (item))) - { - gtk_tree_store_remove (GTK_TREE_STORE (model), iter); - katze_xbel_item_unref (item); - return; - } - - if (katze_xbel_item_is_separator (item)) - g_object_set (renderer, "markup", _("Separator"), NULL); - else - g_object_set (renderer, "markup", NULL, - "text", katze_xbel_item_get_title (item), NULL); -} - -static void -_midori_browser_create_bookmark_menu (MidoriBrowser* browser, - KatzeXbelItem* folder, - GtkWidget* menu); - -static void -midori_browser_bookmark_menu_folder_activate_cb (GtkWidget* menuitem, - MidoriBrowser* browser) -{ - GtkWidget* menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menuitem)); - gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) gtk_widget_destroy, NULL);//... - KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT (menuitem), "KatzeXbelItem"); - _midori_browser_create_bookmark_menu (browser, folder, menu); - // Remove all menuitems when the menu is hidden. - // FIXME: We really *want* the line below, but it won't work like that - //g_signal_connect_after (menu, "hide", G_CALLBACK (gtk_container_foreach), gtk_widget_destroy); - gtk_widget_show (menuitem); -} - -static void -midori_browser_bookmarkbar_folder_activate_cb (GtkToolItem* toolitem, - MidoriBrowser* browser) -{ - GtkWidget* menu = gtk_menu_new (); - KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data ( - G_OBJECT (toolitem), "KatzeXbelItem"); - _midori_browser_create_bookmark_menu (browser, folder, menu); - // Remove all menuitems when the menu is hidden. - // FIXME: We really *should* run the line below, but it won't work like that - /*g_signal_connect (menu, "hide", G_CALLBACK (gtk_container_foreach), - gtk_widget_destroy);*/ - sokoke_widget_popup (GTK_WIDGET (toolitem), GTK_MENU (menu), - NULL, SOKOKE_MENU_POSITION_LEFT); -} - -static void -midori_browser_menu_bookmarks_item_activate_cb (GtkWidget* widget, - MidoriBrowser* browser) -{ - KatzeXbelItem* item = (KatzeXbelItem*)g_object_get_data (G_OBJECT (widget), - "KatzeXbelItem"); - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - g_object_set (web_view, "uri", katze_xbel_bookmark_get_href (item), NULL); - gtk_widget_grab_focus (web_view); -} - -static void -_midori_browser_create_bookmark_menu (MidoriBrowser* browser, - KatzeXbelItem* folder, - GtkWidget* menu) -{ - guint n = katze_xbel_folder_get_n_items (folder); - guint i; - for (i = 0; i < n; i++) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i); - const gchar* title = katze_xbel_item_is_separator (item) - ? "" : katze_xbel_item_get_title (item); - /* const gchar* desc = katze_xbel_item_is_separator (item) - ? "" : katze_xbel_item_get_desc (item); */ - GtkWidget* menuitem = NULL; - switch (katze_xbel_item_get_kind (item)) - { - case KATZE_XBEL_ITEM_KIND_FOLDER: - // FIXME: what about katze_xbel_folder_is_folded? - menuitem = gtk_image_menu_item_new_with_label (title); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), - gtk_image_new_from_stock (GTK_STOCK_DIRECTORY, - GTK_ICON_SIZE_MENU)); - GtkWidget* _menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), _menu); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_browser_bookmark_menu_folder_activate_cb), - browser); - g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); - break; - case KATZE_XBEL_ITEM_KIND_BOOKMARK: - menuitem = gtk_image_menu_item_new_with_label (title); - GtkWidget* image = gtk_image_new_from_stock (STOCK_BOOKMARK, - GTK_ICON_SIZE_MENU); - gtk_widget_show (image); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), - image); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_browser_menu_bookmarks_item_activate_cb), - browser); - g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); - break; - case KATZE_XBEL_ITEM_KIND_SEPARATOR: - menuitem = gtk_separator_menu_item_new (); - break; - default: - g_warning ("Unknown xbel item kind"); - } - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - } -} - -static void -_action_bookmark_add_activate (GtkAction* action, - MidoriBrowser* browser) -{ - midori_browser_edit_bookmark_dialog_new (browser, NULL); -} - -static void -_action_manage_search_engines_activate (GtkAction* action, - MidoriBrowser* browser) -{ - // Show the Manage search engines dialog. Create it if necessary. - static GtkWidget* dialog; - if (GTK_IS_DIALOG (dialog)) - gtk_window_present (GTK_WINDOW (dialog)); - else - { - dialog = webSearch_manageSearchEngines_dialog_new (browser); - gtk_widget_show (dialog); - } -} - -static void -_action_tab_previous_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n - 1); -} - -static void -_action_tab_next_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - // Advance one tab or jump to the first one if we are at the last one - gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); - if (n == gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)) - 1) - n = -1; - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n + 1); -} - -static void -midori_browser_window_menu_item_activate_cb (GtkWidget* widget, - GtkWidget* web_view) -{ - MidoriBrowser* browser = MIDORI_BROWSER (gtk_widget_get_toplevel (web_view)); - if (!browser) - { - g_warning ("Orphaned web view"); - return; - } - - MidoriBrowserPrivate* priv = browser->priv; - - GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, web_view); - guint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); -} - -static const gchar* credits_authors[] = { - "Christian Dywan ", NULL }; -static const gchar* credits_documenters/*[]*/ = /*{ - */NULL/* }*/; -static const gchar* credits_artists[] = { - "Nancy Runge ", NULL }; - -static const gchar* license = - "This library is free software; you can redistribute it and/or\n" - "modify it under the terms of the GNU Lesser General Public\n" - "License as published by the Free Software Foundation; either\n" - "version 2.1 of the License, or (at your option) any later version.\n"; - -static void -_action_about_activate (GtkAction* action, - MidoriBrowser* browser) -{ - gtk_show_about_dialog (GTK_WINDOW (browser), - "logo-icon-name", gtk_window_get_icon_name (GTK_WINDOW (browser)), - "name", PACKAGE_NAME, - "version", PACKAGE_VERSION, - "comments", _("A lightweight web browser."), - "copyright", "Copyright © 2007-2008 Christian Dywan", - "website", "http://software.twotoasts.de", - "authors", credits_authors, - "documenters", credits_documenters, - "artists", credits_artists, - "license", license, - "wrap-license", TRUE, - "translator-credits", _("translator-credits"), - NULL); -} - -static void -midori_browser_location_changed_cb (GtkWidget* widget, - MidoriBrowser* browser) -{ - // Preserve changes to the uri - /*const gchar* newUri = gtk_entry_get_text(GTK_ENTRY(widget)); - katze_xbel_bookmark_set_href(browser->sessionItem, newUri);*/ - // FIXME: If we want this feature, this is the wrong approach -} - -static void -_action_panel_activate (GtkToggleAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean active = gtk_toggle_action_get_active (action); - g_object_set (priv->settings, "show-panel", active, NULL); - sokoke_widget_set_visible (priv->panel, active); -} - -static void -_action_open_in_panel_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); - // FIXME: Don't assign the uri here, update it properly while navigating - g_object_set (priv->settings, "last-pageholder-uri", uri, NULL); - gint n = midori_panel_page_num (MIDORI_PANEL (priv->panel), - priv->panel_pageholder); - midori_panel_set_current_page (MIDORI_PANEL (priv->panel), n); - gtk_widget_show (priv->panel); - g_object_set (priv->panel_pageholder, "uri", uri, NULL); -} - - -static void -midori_panel_notify_position_cb (GObject* object, - GParamSpec* arg1, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean position = gtk_paned_get_position (GTK_PANED (object)); - g_object_set (priv->settings, "last-panel-position", position, NULL); -} - -static gboolean -midori_panel_close_cb (MidoriPanel* panel, - MidoriBrowser* browser) -{ - _action_set_active (browser, "Panel", FALSE); - return FALSE; -} - -static void -gtk_notebook_switch_page_cb (GtkWidget* widget, - GtkNotebookPage* page, - guint page_num, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); - gtk_entry_set_text (GTK_ENTRY (priv->location), uri); - const gchar* title = midori_web_view_get_display_title ( - MIDORI_WEB_VIEW (web_view)); - gchar* window_title = g_strconcat (title, " - ", - g_get_application_name (), NULL); - gtk_window_set_title (GTK_WINDOW (browser), window_title); - g_free (window_title); - _midori_browser_set_statusbar_text (browser, NULL); - _midori_browser_update_interface (browser); -} - -static void -_action_bookmark_open_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); - if (selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - if (katze_xbel_item_is_bookmark (item)) - g_object_set (midori_browser_get_current_web_view (browser), - "uri", katze_xbel_bookmark_get_href(item), NULL); - } - } -} - -static void -_action_bookmark_open_tab_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); - if (selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - if (katze_xbel_item_is_bookmark (item)) - { - gint n = midori_browser_add_xbel_item (browser, item); - _midori_browser_set_current_page_smartly (browser, n); - } - } - } -} - -static void -_action_bookmark_open_window_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); - if (selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - if (katze_xbel_item_is_bookmark (item)) - { - gint n = midori_browser_add_xbel_item (browser, item); - _midori_browser_set_current_page_smartly (browser, n); - } - } - } -} - -static void -_action_bookmark_edit_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); - if (selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - if (!katze_xbel_item_is_separator (item)) - midori_browser_edit_bookmark_dialog_new (browser, item); - } - } -} - -static void -_action_undo_tab_close_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - // Reopen the most recent trash item - KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, 0); - gint n = midori_browser_add_xbel_item (browser, item); - midori_browser_set_current_page (browser, n); - midori_trash_remove_nth_item (priv->trash, 0); - _midori_browser_update_actions (browser); -} - -static void -_action_trash_empty_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - midori_trash_empty (priv->trash); - _midori_browser_update_actions (browser); -} - -static void -_action_bookmark_delete_activate (GtkAction* action, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks); - GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); - if (selection) - { - GtkTreeModel* model; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - KatzeXbelItem* item; - gtk_tree_model_get (model, &iter, 0, &item, -1); - KatzeXbelItem* parent = katze_xbel_item_get_parent (item); - katze_xbel_folder_remove_item (parent, item); - katze_xbel_item_unref (item); - } - } -} - -static const GtkActionEntry entries[] = { - { "File", NULL, N_("_File") }, - { "WindowNew", STOCK_WINDOW_NEW, - NULL, "n", - N_("Open a new window"), G_CALLBACK (_action_window_new_activate) }, - { "TabNew", STOCK_TAB_NEW, - NULL, "t", - N_("Open a new tab"), G_CALLBACK (_action_tab_new_activate) }, - { "Open", GTK_STOCK_OPEN, - NULL, "o", - N_("Open a file"), G_CALLBACK (_action_open_activate) }, - { "SaveAs", GTK_STOCK_SAVE_AS, - NULL, "s", - N_("Save to a file"), NULL/*G_CALLBACK (_action_saveas_activate)*/ }, - { "TabClose", NULL, - N_("_Close Tab"), "w", - N_("Close the current tab"), G_CALLBACK (_action_tab_close_activate) }, - { "WindowClose", NULL, - N_("C_lose Window"), "w", - N_("Close this window"), G_CALLBACK (_action_window_close_activate) }, - { "PageSetup", GTK_STOCK_PROPERTIES, - N_("Pa_ge Setup"), "", - "Configure your print settings", NULL/*G_CALLBACK (_action_page_setup_activate)*/ }, - { "PrintPreview", GTK_STOCK_PRINT_PREVIEW, - NULL, "", - N_("Show a preview of the printed page"), NULL/*G_CALLBACK (_action_print_preview_activate)*/ }, - { "Print", GTK_STOCK_PRINT, - NULL, "p", - N_("Print the current page"), G_CALLBACK (_action_print_activate) }, - { "Quit", GTK_STOCK_QUIT, - NULL, "q", - N_("Quit the application"), G_CALLBACK (_action_quit_activate) }, - - { "Edit", NULL, N_("_Edit"), NULL, NULL, G_CALLBACK (_action_edit_activate) }, - { "Undo", GTK_STOCK_UNDO, - NULL, "z", - N_("Undo the last modification"), NULL/*G_CALLBACK (_action_undo_activate)*/ }, - { "Redo", GTK_STOCK_REDO, - NULL, "z", - N_("Redo the last modification"), NULL/*G_CALLBACK (_action_redo_activate)*/ }, - { "Cut", GTK_STOCK_CUT, - NULL, "x", - N_("Cut the selected text"), G_CALLBACK (_action_cut_activate) }, - { "Copy", GTK_STOCK_COPY, - NULL, "c", - N_("Copy the selected text"), G_CALLBACK (_action_copy_activate) }, - { "Copy_", GTK_STOCK_COPY, - NULL, "c", - N_("Copy the selected text"), G_CALLBACK (_action_copy_activate) }, - { "Paste", GTK_STOCK_PASTE, - NULL, "v", - N_("Paste text from the clipboard"), G_CALLBACK (_action_paste_activate) }, - { "Delete", GTK_STOCK_DELETE, - NULL, NULL, - N_("Delete the selected text"), G_CALLBACK (_action_delete_activate) }, - { "SelectAll", GTK_STOCK_SELECT_ALL, - NULL, "a", - N_("Select all text"), G_CALLBACK (_action_select_all_activate) }, - { "Find", GTK_STOCK_FIND, - NULL, "f", - N_("Find a word or phrase in the page"), G_CALLBACK (_action_find_activate) }, - { "FindNext", GTK_STOCK_GO_FORWARD, - N_("Find _Next"), "g", - N_("Find the next occurrence of a word or phrase"), G_CALLBACK (_action_find_next_activate) }, - { "FindPrevious", GTK_STOCK_GO_BACK, - N_("Find _Previous"), "g", - N_("Find the previous occurrence of a word or phrase"), G_CALLBACK (_action_find_previous_activate) }, - { "FindQuick", GTK_STOCK_FIND, - N_("_Quick Find"), "period", - N_("Quickly jump to a word or phrase"), NULL/*G_CALLBACK (_action_find_quick_activate)*/ }, - { "Preferences", GTK_STOCK_PREFERENCES, - NULL, "p", - N_("Configure the application preferences"), G_CALLBACK (_action_preferences_activate) }, - - { "View", NULL, N_("_View") }, - { "Toolbars", NULL, N_("_Toolbars") }, - { "Reload", GTK_STOCK_REFRESH, - NULL, "r", - N_("Reload the current page"), G_CALLBACK (_action_reload_stop_activate) }, - { "Stop", GTK_STOCK_STOP, - NULL, "Escape", - N_("Stop loading the current page"), G_CALLBACK (_action_reload_stop_activate) }, - { "ReloadStop", GTK_STOCK_STOP, - NULL, "r", - N_("Reload the current page"), G_CALLBACK (_action_reload_stop_activate) }, - { "ZoomIn", GTK_STOCK_ZOOM_IN, - NULL, "plus", - N_("Increase the zoom level"), G_CALLBACK (_action_zoom_in_activate) }, - { "ZoomOut", GTK_STOCK_ZOOM_OUT, - NULL, "minus", - N_("Decrease the zoom level"), G_CALLBACK (_action_zoom_out_activate) }, - { "ZoomNormal", GTK_STOCK_ZOOM_100, - NULL, "0", - N_("Reset the zoom level"), G_CALLBACK (_action_zoom_normal_activate) }, - { "SourceView", NULL, - N_("View Source"), "", - N_("View the source code of the page"), /*G_CALLBACK (_action_source_view_activate)*/ }, - { "SelectionSourceView", NULL, - N_("View Selection Source"), "", - N_("View the source code of the selection"), NULL/*G_CALLBACK (_action_selection_source_view_activate)*/ }, - { "Fullscreen", GTK_STOCK_FULLSCREEN, - NULL, "F11", - N_("Toggle fullscreen view"), G_CALLBACK (_action_fullscreen_activate) }, - - { "Go", NULL, N_("_Go") }, - { "Back", GTK_STOCK_GO_BACK, - NULL, "Left", - N_("Go back to the previous page"), G_CALLBACK (_action_back_activate) }, - { "Forward", GTK_STOCK_GO_FORWARD, - NULL, "Right", - N_("Go forward to the next page"), G_CALLBACK (_action_forward_activate) }, - { "Homepage", STOCK_HOMEPAGE, - NULL, "Home", - N_("Go to your homepage"), G_CALLBACK (_action_homepage_activate) }, - { "Location", GTK_STOCK_JUMP_TO, - N_("Location..."), "l", - N_("Open a particular location"), G_CALLBACK (_action_location_activate) }, - { "Search", GTK_STOCK_FIND, - N_("Web Search..."), "f", - N_("Run a web search"), G_CALLBACK (_action_search_activate) }, - { "OpenInPageholder", GTK_STOCK_JUMP_TO, - N_("Open in Page_holder..."), "", - N_("Open the current page in the pageholder"), G_CALLBACK (_action_open_in_panel_activate) }, - { "Trash", STOCK_USER_TRASH, - N_("Closed Tabs and Windows"), "", - N_("Reopen a previously closed tab or window"), NULL }, - { "TrashEmpty", GTK_STOCK_CLEAR, - N_("Empty Trash"), "", - N_("Delete the contents of the trash"), G_CALLBACK (_action_trash_empty_activate) }, - { "UndoTabClose", GTK_STOCK_UNDELETE, - N_("Undo Close Tab"), "", - N_("Open the last closed tab"), G_CALLBACK (_action_undo_tab_close_activate) }, - - { "Bookmarks", NULL, N_("_Bookmarks") }, - { "BookmarkAdd", STOCK_BOOKMARK_ADD, - NULL, "d", - N_("Add a new bookmark"), G_CALLBACK (_action_bookmark_add_activate) }, - { "BookmarksManage", NULL, - N_("_Manage Bookmarks"), "b", - N_("Add, edit and remove bookmarks..."), NULL/*G_CALLBACK (_action_bookmarks_manage_activate)*/ }, - { "BookmarkOpen", GTK_STOCK_OPEN, - NULL, "", - N_("Open the selected bookmark"), G_CALLBACK (_action_bookmark_open_activate) }, - { "BookmarkOpenTab", STOCK_TAB_NEW, - N_("Open in New _Tab"), "", - N_("Open the selected bookmark in a new tab"), G_CALLBACK (_action_bookmark_open_tab_activate) }, - { "BookmarkOpenWindow", STOCK_WINDOW_NEW, - N_("Open in New _Window"), "", - N_("Open the selected bookmark in a new window"), G_CALLBACK (_action_bookmark_open_window_activate) }, - { "BookmarkEdit", GTK_STOCK_EDIT, - NULL, "", - N_("Edit the selected bookmark"), G_CALLBACK (_action_bookmark_edit_activate) }, - { "BookmarkDelete", GTK_STOCK_DELETE, - NULL, "", - N_("Delete the selected bookmark"), G_CALLBACK (_action_bookmark_delete_activate) }, - - { "Tools", NULL, N_("_Tools") }, - { "ManageSearchEngines", GTK_STOCK_PROPERTIES, - N_("_Manage Search Engines"), "s", - N_("Add, edit and remove search engines..."), - G_CALLBACK (_action_manage_search_engines_activate) }, - - { "Window", NULL, N_("_Window") }, - { "TabPrevious", GTK_STOCK_GO_BACK, - N_("_Previous Tab"), "Page_Up", - N_("Switch to the previous tab"), G_CALLBACK (_action_tab_previous_activate) }, - { "TabNext", GTK_STOCK_GO_FORWARD, - N_("_Next Tab"), "Page_Down", - N_("Switch to the next tab"), G_CALLBACK (_action_tab_next_activate) }, - { "TabOverview", NULL, - N_("Tab _Overview"), "", - N_("Show an overview of all open tabs"), NULL/*G_CALLBACK (_action_tab_overview_activate)*/ }, - - { "Help", NULL, N_("_Help") }, - { "HelpContents", GTK_STOCK_HELP, - N_("_Contents"), "F1", - N_("Show the documentation"), NULL/*G_CALLBACK (_action_help_contents_activate)*/ }, - { "About", GTK_STOCK_ABOUT, - NULL, "", - N_("Show information about the program"), G_CALLBACK (_action_about_activate) }, - }; - static const guint entries_n = G_N_ELEMENTS (entries); - -static const GtkToggleActionEntry toggle_entries[] = { - { "PrivateBrowsing", NULL, - N_("P_rivate Browsing"), "", - N_("Don't save any private data while browsing"), NULL/*G_CALLBACK (_action_private_browsing_activate)*/, - FALSE }, - { "WorkOffline", GTK_STOCK_DISCONNECT, - N_("_Work Offline"), "", - N_("Work without a network connection"), NULL/*G_CALLBACK (_action_work_offline_activate)*/, - FALSE }, - - { "Navigationbar", NULL, - N_("_Navigationbar"), "", - N_("Show navigationbar"), G_CALLBACK (_action_navigationbar_activate), - FALSE }, - { "Panel", NULL, - N_("Side_panel"), "F9", - N_("Show sidepanel"), G_CALLBACK (_action_panel_activate), - FALSE }, - { "Bookmarkbar", NULL, - N_("_Bookmarkbar"), "", - N_("Show bookmarkbar"), G_CALLBACK (_action_bookmarkbar_activate), - FALSE }, - { "Transferbar", NULL, - N_("_Transferbar"), "", - N_("Show transferbar"), NULL/*G_CALLBACK (_action_transferbar_activate)*/, - FALSE }, - { "Statusbar", NULL, - N_("_Statusbar"), "", - N_("Show statusbar"), G_CALLBACK (_action_statusbar_activate), - FALSE }, - }; - static const guint toggle_entries_n = G_N_ELEMENTS (toggle_entries); - -static void -midori_browser_window_state_event_cb (MidoriBrowser* browser, - GdkEventWindowState* event) -{ - MidoriBrowserPrivate* priv = browser->priv; - - if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) - { - if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) - { - gtk_widget_hide (priv->menubar); - g_object_set (priv->button_fullscreen, - "stock-id", GTK_STOCK_LEAVE_FULLSCREEN, NULL); - gtk_widget_show (priv->button_fullscreen); - } - else - { - gtk_widget_show (priv->menubar); - gtk_widget_hide (priv->button_fullscreen); - g_object_set (priv->button_fullscreen, - "stock-id", GTK_STOCK_FULLSCREEN, NULL); - } - } -} - -static void -midori_browser_size_allocate_cb (MidoriBrowser* browser, - GtkAllocation* allocation) -{ - MidoriBrowserPrivate* priv = browser->priv; - GtkWidget* widget = GTK_WIDGET (browser); - - if (GTK_WIDGET_REALIZED (widget)) - { - GdkWindowState state = gdk_window_get_state (widget->window); - if (!(state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN))) - { - g_object_set (priv->settings, - "last-window-width", allocation->width, - "last-window-height", allocation->height, NULL); - } - } -} - -static void -midori_browser_destroy_cb (MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - // Destroy tabs first, so widgets can still see window elements on destroy - gtk_container_foreach (GTK_CONTAINER (priv->notebook), - (GtkCallback) gtk_widget_destroy, NULL); -} - -static const gchar* ui_markup = - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - // Closed tabs shall be prepended here - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - // Bookmarks shall be appended here - "" - "" - "" - // Panel items shall be appended here - "" - "" - "" - "" - "" - "" - // All open tabs shall be appended here - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - ""; - -static void -midori_browser_realize_cb (GtkStyle* style, MidoriBrowser* browser) -{ - GdkScreen* screen = gtk_widget_get_screen (GTK_WIDGET (browser)); - if (screen) - { - GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen); - if (gtk_icon_theme_has_icon (icon_theme, "midori")) - gtk_window_set_icon_name (GTK_WINDOW (browser), "midori"); - else - gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser"); - } -} - -static void -midori_browser_init (MidoriBrowser* browser) -{ - browser->priv = MIDORI_BROWSER_GET_PRIVATE (browser); - - MidoriBrowserPrivate* priv = browser->priv; - - // Setup the window metrics - g_signal_connect (browser, "realize", - G_CALLBACK (midori_browser_realize_cb), browser); - g_signal_connect (browser, "window-state-event", - G_CALLBACK (midori_browser_window_state_event_cb), NULL); - g_signal_connect (browser, "size-allocate", - G_CALLBACK (midori_browser_size_allocate_cb), NULL); - g_signal_connect (browser, "destroy", - G_CALLBACK (midori_browser_destroy_cb), NULL); - gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser"); - gtk_window_set_title (GTK_WINDOW (browser), g_get_application_name ()); - GtkWidget* vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (browser), vbox); - gtk_widget_show (vbox); - - // Let us see some ui manager magic - priv->action_group = gtk_action_group_new ("Browser"); - gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (priv->action_group, - entries, entries_n, browser); - gtk_action_group_add_toggle_actions (priv->action_group, - toggle_entries, toggle_entries_n, browser); - GtkUIManager* ui_manager = gtk_ui_manager_new (); - gtk_ui_manager_insert_action_group (ui_manager, priv->action_group, 0); - gtk_window_add_accel_group (GTK_WINDOW (browser), - gtk_ui_manager_get_accel_group (ui_manager)); - - GError* error = NULL; - if (!gtk_ui_manager_add_ui_from_string(ui_manager, ui_markup, -1, &error)) - { - // TODO: Should this be a message dialog? When does this happen? - g_message ("User interface couldn't be created: %s", error->message); - g_error_free (error); - } - - GtkAction* action; - // Make all actions except toplevel menus which lack a callback insensitive - // This will vanish once all actions are implemented - guint i; - for (i = 0; i < entries_n; i++) - { - action = gtk_action_group_get_action(priv->action_group, - entries[i].name); - gtk_action_set_sensitive (action, - entries[i].callback || !entries[i].tooltip); - } - for (i = 0; i < toggle_entries_n; i++) - { - action = gtk_action_group_get_action (priv->action_group, - toggle_entries[i].name); - gtk_action_set_sensitive (action, toggle_entries[i].callback != NULL); - } - - //_action_set_active(browser, "Transferbar", config->toolbarTransfers); - - // Create the menubar - priv->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar"); - GtkWidget* menuitem = gtk_menu_item_new (); - gtk_widget_show (menuitem); - priv->throbber = katze_throbber_new(); - gtk_widget_show(priv->throbber); - gtk_container_add (GTK_CONTAINER (menuitem), priv->throbber); - gtk_widget_set_sensitive (menuitem, FALSE); - gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menubar), menuitem); - gtk_box_pack_start (GTK_BOX (vbox), priv->menubar, FALSE, FALSE, 0); - menuitem = gtk_ui_manager_get_widget (ui_manager, "/menubar/Go/Trash"); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_browser_menu_trash_activate_cb), - browser); - priv->menu_bookmarks = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( - gtk_ui_manager_get_widget (ui_manager, "/menubar/Bookmarks"))); - menuitem = gtk_separator_menu_item_new (); - gtk_widget_show (menuitem); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_bookmarks), menuitem); - priv->popup_bookmark = gtk_ui_manager_get_widget ( - ui_manager, "/popup_bookmark"); - g_object_ref (priv->popup_bookmark); - priv->menu_tools = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( - gtk_ui_manager_get_widget (ui_manager, "/menubar/Tools"))); - menuitem = gtk_separator_menu_item_new(); - gtk_widget_show (menuitem); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_tools), menuitem); - priv->menu_window = gtk_menu_item_get_submenu (GTK_MENU_ITEM ( - gtk_ui_manager_get_widget (ui_manager, "/menubar/Window"))); - menuitem = gtk_separator_menu_item_new(); - gtk_widget_show (menuitem); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_window), menuitem); - gtk_widget_show (priv->menubar); - _action_set_sensitive (browser, "PrivateBrowsing", FALSE); - _action_set_sensitive (browser, "WorkOffline", FALSE); - - // Create the navigationbar - priv->navigationbar = gtk_ui_manager_get_widget ( - ui_manager, "/toolbar_navigation"); - // FIXME: settings should be connected with screen changes - GtkSettings* gtk_settings = gtk_widget_get_settings (GTK_WIDGET (browser)); - if (gtk_settings) - g_signal_connect (gtk_settings, "notify::gtk-toolbar-style", - G_CALLBACK (midori_browser_navigationbar_notify_style_cb), browser); - gtk_toolbar_set_show_arrow (GTK_TOOLBAR (priv->navigationbar), TRUE); - gtk_box_pack_start (GTK_BOX (vbox), priv->navigationbar, FALSE, FALSE, 0); - priv->button_tab_new = gtk_ui_manager_get_widget ( - ui_manager, "/toolbar_navigation/TabNew"); - g_object_set (_action_by_name (browser, "Back"), "is-important", TRUE, NULL); - priv->button_homepage = gtk_ui_manager_get_widget ( - ui_manager, "/toolbar_navigation/Homepage"); - - // Location - priv->location = sexy_icon_entry_new (); - sokoke_entry_setup_completion (GTK_ENTRY (priv->location)); - priv->location_icon = gtk_image_new (); - sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->location) - , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE (priv->location_icon)); - sexy_icon_entry_add_clear_button (SEXY_ICON_ENTRY (priv->location)); - g_object_connect (priv->location, - "signal::key-press-event", - midori_browser_location_key_press_event_cb, browser, - "signal::focus-out-event", - midori_browser_location_focus_out_event_cb, browser, - "signal::changed", - midori_browser_location_changed_cb, browser, - NULL); - GtkToolItem* toolitem = gtk_tool_item_new (); - gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); - gtk_container_add (GTK_CONTAINER(toolitem), priv->location); - gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1); - - // Search - priv->search = sexy_icon_entry_new (); - sexy_icon_entry_set_icon_highlight (SEXY_ICON_ENTRY (priv->search), - SEXY_ICON_ENTRY_PRIMARY, TRUE); - // TODO: Make this actively resizable or enlarge to fit contents? - // FIXME: The interface is somewhat awkward and ought to be rethought - // TODO: Display "show in context menu" search engines as "completion actions" - sokoke_entry_setup_completion (GTK_ENTRY (priv->search)); - g_object_connect (priv->search, - "signal::icon-released", - on_webSearch_icon_released, browser, - "signal::key-press-event", - on_webSearch_key_down, browser, - "signal::scroll-event", - on_webSearch_scroll, browser, - "signal::activate", - on_webSearch_activate, browser, - "signal::focus-out-event", - midori_browser_search_focus_out_event_cb, browser, - NULL); - toolitem = gtk_tool_item_new (); - gtk_container_add (GTK_CONTAINER (toolitem), priv->search); - gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1); - action = gtk_action_group_get_action (priv->action_group, "Trash"); - priv->button_trash = gtk_action_create_tool_item (action); - g_signal_connect (priv->button_trash, "clicked", - G_CALLBACK (midori_browser_menu_trash_activate_cb), browser); - gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), - GTK_TOOL_ITEM (priv->button_trash), -1); - sokoke_container_show_children (GTK_CONTAINER (priv->navigationbar)); - action = gtk_action_group_get_action (priv->action_group, "Fullscreen"); - priv->button_fullscreen = gtk_action_create_tool_item (action); - gtk_widget_hide (priv->button_fullscreen); - g_signal_connect (priv->button_fullscreen, "clicked", - G_CALLBACK (_action_fullscreen_activate), browser); - gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), - GTK_TOOL_ITEM (priv->button_fullscreen), -1); - - // Bookmarkbar - priv->bookmarkbar = gtk_toolbar_new (); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->bookmarkbar), - GTK_ICON_SIZE_MENU); - gtk_toolbar_set_style (GTK_TOOLBAR (priv->bookmarkbar), - GTK_TOOLBAR_BOTH_HORIZ); - _midori_browser_create_bookmark_menu (browser, bookmarks, - priv->menu_bookmarks); - for (i = 0; i < katze_xbel_folder_get_n_items (bookmarks); i++) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item (bookmarks, i); - const gchar* title = katze_xbel_item_is_separator (item) - ? "" : katze_xbel_item_get_title (item); - const gchar* desc = katze_xbel_item_is_separator (item) - ? "" : katze_xbel_item_get_desc (item); - switch (katze_xbel_item_get_kind (item)) - { - case KATZE_XBEL_ITEM_KIND_FOLDER: - toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DIRECTORY); - gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title); - gtk_tool_item_set_is_important(toolitem, TRUE); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (midori_browser_bookmarkbar_folder_activate_cb), - browser); - sokoke_tool_item_set_tooltip_text(toolitem, desc); - g_object_set_data (G_OBJECT (toolitem), "KatzeXbelItem", item); - break; - case KATZE_XBEL_ITEM_KIND_BOOKMARK: - toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK); - gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title); - gtk_tool_item_set_is_important(toolitem, TRUE); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (midori_browser_menu_bookmarks_item_activate_cb), - browser); - sokoke_tool_item_set_tooltip_text(toolitem, desc); - g_object_set_data (G_OBJECT (toolitem), "KatzeXbelItem", item); - break; - case KATZE_XBEL_ITEM_KIND_SEPARATOR: - toolitem = gtk_separator_tool_item_new (); - break; - default: - g_warning ("Unknown item kind"); - } - gtk_toolbar_insert (GTK_TOOLBAR (priv->bookmarkbar), toolitem, -1); - } - sokoke_container_show_children (GTK_CONTAINER (priv->bookmarkbar)); - gtk_box_pack_start (GTK_BOX (vbox), priv->bookmarkbar, FALSE, FALSE, 0); - - // Superuser warning - GtkWidget* hbox; - if ((hbox = sokoke_superuser_warning_new ())) - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - // Create the panel - GtkWidget* hpaned = gtk_hpaned_new (); - g_signal_connect (hpaned, "notify::position", - G_CALLBACK (midori_panel_notify_position_cb), - browser); - gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0); - gtk_widget_show (hpaned); - priv->panel = g_object_new (MIDORI_TYPE_PANEL, - "shadow-type", GTK_SHADOW_IN, - "menu", priv->menu_tools, - NULL); - g_signal_connect (priv->panel, "close", - G_CALLBACK (midori_panel_close_cb), browser); - gtk_paned_pack1 (GTK_PANED (hpaned), priv->panel, FALSE, FALSE); - - // Bookmarks - GtkWidget* box = gtk_vbox_new (FALSE, 0); - GtkTreeViewColumn* column; - GtkCellRenderer* renderer_text; - GtkCellRenderer* renderer_pixbuf; - GtkTreeStore* treestore = gtk_tree_store_new (1, KATZE_TYPE_XBEL_ITEM); - GtkWidget* treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore)); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); - column = gtk_tree_view_column_new (); - renderer_pixbuf = gtk_cell_renderer_pixbuf_new (); - gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE); - gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf, - (GtkTreeCellDataFunc)midori_browser_bookmarks_item_render_icon_cb, - treeview, NULL); - renderer_text = gtk_cell_renderer_text_new (); - gtk_tree_view_column_pack_start (column, renderer_text, FALSE); - gtk_tree_view_column_set_cell_data_func (column, renderer_text, - (GtkTreeCellDataFunc)midori_browser_bookmarks_item_render_text_cb, - treeview, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); - _tree_store_insert_folder (GTK_TREE_STORE (treestore), NULL, bookmarks); - g_object_unref (treestore); - g_object_connect (treeview, - "signal::row-activated", - midori_panel_bookmarks_row_activated_cb, browser, - "signal::cursor-changed", - midori_panel_bookmarks_cursor_or_row_changed_cb, browser, - "signal::columns-changed", - midori_panel_bookmarks_cursor_or_row_changed_cb, browser, - "signal::button-release-event", - midori_panel_bookmarks_button_release_event_cb, browser, - "signal::popup-menu", - midori_panel_bookmarks_popup_menu_cb, browser, - NULL); - midori_panel_bookmarks_cursor_or_row_changed_cb (GTK_TREE_VIEW (treeview), - browser); - gtk_box_pack_start (GTK_BOX (box), treeview, TRUE, TRUE, 0); - priv->panel_bookmarks = treeview; - gtk_widget_show_all (box); - GtkWidget* toolbar = gtk_ui_manager_get_widget (ui_manager, - "/toolbar_bookmarks"); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU); - gtk_widget_show_all (toolbar); - midori_panel_append_page (MIDORI_PANEL (priv->panel), - box, toolbar, - "vcard", _("Bookmarks")); - - // Transfers - GtkWidget* panel = midori_web_view_new (); - gtk_widget_show (panel); - midori_panel_append_page (MIDORI_PANEL (priv->panel), - panel, NULL, - "package", _("Transfers")); - - // Console - priv->panel_console = midori_console_new (); - gtk_widget_show (priv->panel_console); - toolbar = midori_console_get_toolbar (MIDORI_CONSOLE (priv->panel_console)); - gtk_widget_show (toolbar); - midori_panel_append_page (MIDORI_PANEL (priv->panel), - priv->panel_console, toolbar, - "terminal", _("Console")); - - // History - panel = midori_web_view_new (); - gtk_widget_show (panel); - midori_panel_append_page (MIDORI_PANEL (priv->panel), - panel, NULL, - "document-open-recent", _("History")); - - // Pageholder - priv->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW, - "uri", "", - NULL); - gtk_widget_show (priv->panel_pageholder); - midori_panel_append_page (MIDORI_PANEL (priv->panel), - priv->panel_pageholder, NULL, - GTK_STOCK_CONVERT, _("Pageholder")); - - // Userscripts - panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_SCRIPTS); - gtk_widget_show (panel); - toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel)); - gtk_widget_show (toolbar); - midori_panel_append_page (MIDORI_PANEL (priv->panel), - panel, toolbar, - "", _("Userscripts")); - // Userstyles - /*panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_STYLES); - gtk_widget_show (panel); - toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel)); - gtk_widget_show (toolbar); - midori_panel_append_page (MIDORI_PANEL (priv->panel), - panel, toolbar, - "", _("Userstyles"));*/ - - // Notebook, containing all web_views - priv->notebook = gtk_notebook_new (); - gtk_notebook_set_scrollable (GTK_NOTEBOOK (priv->notebook), TRUE); - gtk_paned_pack2 (GTK_PANED (hpaned), priv->notebook, FALSE, FALSE); - g_signal_connect_after (priv->notebook, "switch-page", - G_CALLBACK (gtk_notebook_switch_page_cb), - browser); - gtk_widget_show (priv->notebook); - - // Incremental findbar - priv->find = gtk_toolbar_new (); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->find), GTK_ICON_SIZE_MENU); - gtk_toolbar_set_style (GTK_TOOLBAR (priv->find), GTK_TOOLBAR_BOTH_HORIZ); - toolitem = gtk_tool_item_new (); - gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6); - gtk_container_add (GTK_CONTAINER (toolitem), - gtk_label_new_with_mnemonic (_("_Inline find:"))); - gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); - priv->find_text = sexy_icon_entry_new (); - GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FIND, - GTK_ICON_SIZE_MENU); - sexy_icon_entry_set_icon (SEXY_ICON_ENTRY(priv->find_text), - SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon)); - sexy_icon_entry_add_clear_button (SEXY_ICON_ENTRY(priv->find_text)); - g_signal_connect (priv->find_text, "activate", - G_CALLBACK (_action_find_next_activate), browser); - toolitem = gtk_tool_item_new (); - gtk_container_add (GTK_CONTAINER (toolitem), priv->find_text); - gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); - gtk_toolbar_insert (GTK_TOOLBAR(priv->find), toolitem, -1); - toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK); - gtk_tool_item_set_is_important (toolitem, TRUE); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (_action_find_previous_activate), browser); - gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); - toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD); - gtk_tool_item_set_is_important (toolitem, TRUE); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (_action_find_next_activate), browser); - gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); - priv->find_case = gtk_toggle_tool_button_new_from_stock ( - GTK_STOCK_SPELL_CHECK); - gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->find_case), _("Match Case")); - gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->find_case), TRUE); - gtk_toolbar_insert (GTK_TOOLBAR (priv->find), priv->find_case, -1); - priv->find_highlight = gtk_toggle_tool_button_new_from_stock ( - GTK_STOCK_SELECT_ALL); - g_signal_connect (priv->find_highlight, "toggled", - G_CALLBACK (_find_highlight_toggled), browser); - gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->find_highlight), - "Highlight Matches"); - gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->find_highlight), TRUE); - gtk_toolbar_insert (GTK_TOOLBAR (priv->find), priv->find_highlight, -1); - toolitem = gtk_separator_tool_item_new (); - gtk_separator_tool_item_set_draw ( - GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE); - gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); - gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); - toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE); - gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("Close Findbar")); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (midori_browser_find_button_close_clicked_cb), browser); - gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1); - sokoke_container_show_children (GTK_CONTAINER (priv->find)); - gtk_box_pack_start (GTK_BOX (vbox), priv->find, FALSE, FALSE, 0); - - // Statusbar - // TODO: fix children overlapping statusbar border - priv->statusbar = gtk_statusbar_new (); - gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0); - priv->progressbar = gtk_progress_bar_new (); - // Setting the progressbar's height to 1 makes it fit in the statusbar - gtk_widget_set_size_request (priv->progressbar, -1, 1); - gtk_box_pack_start (GTK_BOX (priv->statusbar), priv->progressbar, - FALSE, FALSE, 3); - - // Extensions - panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_EXTENSIONS); - gtk_widget_show (panel); - toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel)); - gtk_widget_show (toolbar); - midori_panel_append_page (MIDORI_PANEL (priv->panel), - panel, toolbar, - "", _("Extensions")); - - g_object_unref (ui_manager); -} - -static void -midori_browser_finalize (GObject* object) -{ - MidoriBrowser* browser = MIDORI_BROWSER (object); - MidoriBrowserPrivate* priv = browser->priv; - - g_free (priv->uri); - g_free (priv->title); - g_free (priv->statusbar_text); - - if (priv->proxy_xbel_folder) - katze_xbel_item_unref (priv->proxy_xbel_folder); - - if (priv->settings) - g_object_unref (priv->settings); - if (priv->trash) - g_object_unref (priv->trash); - - G_OBJECT_CLASS (midori_browser_parent_class)->finalize (object); -} - -static void -_midori_browser_set_toolbar_style (MidoriBrowser* browser, - MidoriToolbarStyle toolbar_style) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkToolbarStyle gtk_toolbar_style; - GtkSettings* gtk_settings = gtk_widget_get_settings (GTK_WIDGET (browser)); - if (toolbar_style == MIDORI_TOOLBAR_DEFAULT && gtk_settings) - g_object_get (gtk_settings, "gtk-toolbar-style", >k_toolbar_style, NULL); - else - { - switch (toolbar_style) - { - case MIDORI_TOOLBAR_ICONS: - gtk_toolbar_style = GTK_TOOLBAR_ICONS; - break; - case MIDORI_TOOLBAR_TEXT: - gtk_toolbar_style = GTK_TOOLBAR_TEXT; - break; - case MIDORI_TOOLBAR_BOTH: - gtk_toolbar_style = GTK_TOOLBAR_BOTH; - break; - case MIDORI_TOOLBAR_BOTH_HORIZ: - case MIDORI_TOOLBAR_DEFAULT: - gtk_toolbar_style = GTK_TOOLBAR_BOTH_HORIZ; - } - } - gtk_toolbar_set_style (GTK_TOOLBAR (priv->navigationbar), - gtk_toolbar_style); -} - -static void -_midori_browser_update_settings (MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gboolean remember_last_window_size; - gint last_window_width, last_window_height; - gint last_panel_position, last_panel_page; - gboolean show_navigationbar, show_bookmarkbar, show_panel, show_statusbar; - gboolean small_toolbar, show_new_tab, show_homepage, - show_web_search, show_trash; - MidoriToolbarStyle toolbar_style; - gint last_web_search; - gchar* last_pageholder_uri; - g_object_get (priv->settings, - "remember-last-window-size", &remember_last_window_size, - "last-window-width", &last_window_width, - "last-window-height", &last_window_height, - "last-panel-position", &last_panel_position, - "last-panel-page", &last_panel_page, - "show-navigationbar", &show_navigationbar, - "show-bookmarkbar", &show_bookmarkbar, - "show-panel", &show_panel, - "show-statusbar", &show_statusbar, - "small-toolbar", &small_toolbar, - "show-new-tab", &show_new_tab, - "show-homepage", &show_homepage, - "show-web-search", &show_web_search, - "show-trash", &show_trash, - "toolbar-style", &toolbar_style, - "last-web-search", &last_web_search, - "last-pageholder-uri", &last_pageholder_uri, - NULL); - - GdkScreen* screen = gtk_window_get_screen (GTK_WINDOW (browser)); - const gint default_width = (gint)gdk_screen_get_width (screen) / 1.7; - const gint default_height = (gint)gdk_screen_get_height (screen) / 1.7; - - if (remember_last_window_size) - { - if (last_window_width && last_window_height) - gtk_window_set_default_size (GTK_WINDOW (browser), - last_window_width, last_window_height); - else - gtk_window_set_default_size (GTK_WINDOW (browser), - default_width, default_height); - } - - _midori_browser_set_toolbar_style (browser, toolbar_style); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->navigationbar), - small_toolbar ? GTK_ICON_SIZE_SMALL_TOOLBAR - : GTK_ICON_SIZE_LARGE_TOOLBAR); - - update_searchEngine (last_web_search, priv->search); - - gtk_paned_set_position (GTK_PANED (gtk_widget_get_parent (priv->panel)), - last_panel_position); - midori_panel_set_current_page (MIDORI_PANEL (priv->panel), last_panel_page); - g_object_set (priv->panel_pageholder, "uri", last_pageholder_uri, NULL); - - _action_set_active (browser, "Navigationbar", show_navigationbar); - _action_set_active (browser, "Bookmarkbar", show_bookmarkbar); - _action_set_active (browser, "Panel", show_panel); - _action_set_active (browser, "Statusbar", show_statusbar); - - sokoke_widget_set_visible (priv->button_tab_new, show_new_tab); - sokoke_widget_set_visible (priv->button_homepage, show_homepage); - sokoke_widget_set_visible (priv->search, show_web_search); - sokoke_widget_set_visible (priv->button_trash, show_trash); - - g_free (last_pageholder_uri); -} - -static void -midori_browser_settings_notify (MidoriWebSettings* web_settings, - GParamSpec* pspec, - MidoriBrowser* browser) -{ - MidoriBrowserPrivate* priv = browser->priv; - - const gchar* name = g_intern_string (pspec->name); - GValue value = {0, }; - - g_value_init (&value, pspec->value_type); - g_object_get_property (G_OBJECT (priv->settings), name, &value); - - if (name == g_intern_string ("toolbar-style")) - _midori_browser_set_toolbar_style (browser, g_value_get_enum (&value)); - else if (name == g_intern_string ("small-toolbar")) - gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->navigationbar), - g_value_get_boolean (&value) ? GTK_ICON_SIZE_SMALL_TOOLBAR - : GTK_ICON_SIZE_LARGE_TOOLBAR); - else if (name == g_intern_string ("show-new-tab")) - sokoke_widget_set_visible (priv->button_tab_new, - g_value_get_boolean (&value)); - else if (name == g_intern_string ("show-homepage")) - sokoke_widget_set_visible (priv->button_homepage, - g_value_get_boolean (&value)); - else if (name == g_intern_string ("show-web-search")) - sokoke_widget_set_visible (priv->search, - g_value_get_boolean (&value)); - else if (name == g_intern_string ("show-trash")) - sokoke_widget_set_visible (priv->button_trash, - g_value_get_boolean (&value)); - else if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_settings), - name)) - g_warning (_("Unexpected setting '%s'"), name); - g_value_unset (&value); -} - -static void -midori_browser_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec) -{ - MidoriBrowser* browser = MIDORI_BROWSER (object); - MidoriBrowserPrivate* priv = browser->priv; - - switch (prop_id) - { - case PROP_TAB: - midori_browser_set_current_tab (browser, g_value_get_object (value)); - break; - case PROP_STATUSBAR_TEXT: - _midori_browser_set_statusbar_text (browser, g_value_get_string (value)); - break; - case PROP_SETTINGS: - if (priv->settings) - g_signal_handlers_disconnect_by_func (priv->settings, - midori_browser_settings_notify, - browser); - katze_object_assign (priv->settings, g_value_get_object (value)); - g_object_ref (priv->settings); - _midori_browser_update_settings (browser); - g_signal_connect (priv->settings, "notify", - G_CALLBACK (midori_browser_settings_notify), browser); - // FIXME: Assigning settings must be conditional, if web view or not - // FIXME: Assign settings only if the same settings object was used - gtk_container_foreach (GTK_CONTAINER (priv->notebook), - (GtkCallback) midori_web_view_set_settings, - priv->settings); - break; - case PROP_TRASH: - ; // FIXME: Disconnect handlers - katze_object_assign (priv->trash, g_value_get_object (value)); - g_object_ref (priv->trash); - // FIXME: Connect to updates - _midori_browser_update_actions (browser); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_browser_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec) -{ - MidoriBrowser* browser = MIDORI_BROWSER (object); - MidoriBrowserPrivate* priv = browser->priv; - - switch (prop_id) - { - case PROP_MENUBAR: - g_value_set_object (value, priv->menubar); - break; - case PROP_NAVIGATIONBAR: - g_value_set_object (value, priv->navigationbar); - break; - case PROP_TAB: - g_value_set_object (value, midori_browser_get_current_tab (browser)); - break; - case PROP_STATUSBAR: - g_value_set_object (value, priv->statusbar); - break; - case PROP_STATUSBAR_TEXT: - g_value_set_string (value, priv->statusbar_text); - break; - case PROP_SETTINGS: - g_value_set_object (value, priv->settings); - break; - case PROP_TRASH: - g_value_set_object (value, priv->trash); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * midori_browser_new: - * - * Creates a new browser widget. - * - * A browser is a window with a menubar, toolbars, a notebook, panels - * and a statusbar. You should mostly treat it as an opaque widget. - * - * Return value: a new #MidoriBrowser - **/ -MidoriBrowser* -midori_browser_new (void) -{ - MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER, - NULL); - - return browser; -} - -/** - * midori_browser_add_tab: - * @browser: a #MidoriBrowser - * @widget: a tab - * - * Appends an arbitrary widget in the form of a new tab and creates an - * according item in the Window menu. - * - * Return value: the index of the new tab, or -1 in case of an error - **/ -gint -midori_browser_add_tab (MidoriBrowser* browser, - GtkWidget* widget) -{ - g_return_val_if_fail (GTK_IS_WIDGET (widget), -1); - - MidoriBrowserPrivate* priv = browser->priv; - - GtkWidget* scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS); - GtkWidget* child; - GObjectClass* gobject_class = G_OBJECT_GET_CLASS (widget); - if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal) - child = widget; - else - { - child = gtk_viewport_new (NULL, NULL); - gtk_widget_show (child); - gtk_container_add (GTK_CONTAINER (child), widget); - } - gtk_container_add (GTK_CONTAINER (scrolled), child); - gtk_widget_show (scrolled); - - GtkWidget* label = NULL; - GtkWidget* menuitem = NULL; - - if (MIDORI_IS_WEB_VIEW (widget)) - { - label = midori_web_view_get_proxy_tab_label (MIDORI_WEB_VIEW (widget)); - - menuitem = midori_web_view_get_proxy_menu_item (MIDORI_WEB_VIEW (widget)); - - if (priv->proxy_xbel_folder) - { - KatzeXbelItem* xbel_item = midori_web_view_get_proxy_xbel_item ( - MIDORI_WEB_VIEW (widget)); - katze_xbel_item_ref (xbel_item); - katze_xbel_folder_append_item (priv->proxy_xbel_folder, xbel_item); - } - - g_object_connect (widget, - "signal::window-object-cleared", - midori_web_view_window_object_cleared_cb, browser, - "signal::load-started", - midori_web_view_load_started_cb, browser, - "signal::load-committed", - midori_web_view_load_committed_cb, browser, - "signal::progress-started", - midori_web_view_progress_started_cb, browser, - "signal::progress-changed", - midori_web_view_progress_changed_cb, browser, - "signal::progress-done", - midori_web_view_progress_done_cb, browser, - "signal::load-done", - midori_web_view_load_done_cb, browser, - "signal::title-changed", - midori_web_view_title_changed_cb, browser, - "signal::status-bar-text-changed", - midori_web_view_statusbar_text_changed_cb, browser, - "signal::element-motion", - midori_web_view_element_motion_cb, browser, - "signal::console-message", - midori_web_view_console_message_cb, browser, - "signal::close", - midori_web_view_close_cb, browser, - "signal::new-tab", - midori_web_view_new_tab_cb, browser, - "signal::new-window", - midori_web_view_new_window_cb, browser, - "signal::populate-popup", - midori_web_view_populate_popup_cb, browser, - "signal::leave-notify-event", - midori_web_view_leave_notify_event_cb, browser, - "signal::destroy", - midori_web_view_destroy_cb, browser, - NULL); - } - - if (menuitem) - { - gtk_widget_show (menuitem); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_browser_window_menu_item_activate_cb), scrolled); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_window), menuitem); - } - - guint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); - gtk_notebook_insert_page (GTK_NOTEBOOK (priv->notebook), scrolled, - label, n + 1); - #if GTK_CHECK_VERSION(2, 10, 0) - gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (priv->notebook), - scrolled, TRUE); - gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (priv->notebook), - scrolled, TRUE); - #endif - _midori_browser_update_actions (browser); - - n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); - return n; -} - -/** - * midori_browser_remove_tab: - * @browser: a #MidoriBrowser - * @widget: a tab - * - * Removes an existing tab from the browser, including an associated menu item. - **/ -void -midori_browser_remove_tab (MidoriBrowser* browser, - GtkWidget* widget) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); - gtk_container_remove (GTK_CONTAINER (priv->notebook), scrolled); - - // FIXME: Remove the menuitem if this is a web view -} - -/** - * midori_browser_add_xbel_item: - * @browser: a #MidoriBrowser - * @xbel_item: a bookmark - * - * Appends a #KatzeXbelItem in the form of a new tab. - * - * Return value: the index of the new tab, or -1 in case of an error - **/ -gint -midori_browser_add_xbel_item (MidoriBrowser* browser, - KatzeXbelItem* xbel_item) -{ - MidoriBrowserPrivate* priv = browser->priv; - - g_return_val_if_fail (katze_xbel_item_is_bookmark (xbel_item), -1); - - const gchar* uri = katze_xbel_bookmark_get_href (xbel_item); - const gchar* title = katze_xbel_item_get_title (xbel_item); - GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, - "uri", uri, - "title", title, - "settings", priv->settings, - NULL); - gtk_widget_show (web_view); - - return midori_browser_add_tab (browser, web_view); -} - -/** - * midori_browser_add_uri: - * @browser: a #MidoriBrowser - * @uri: an URI - * - * Appends an uri in the form of a new tab. - * - * Return value: the index of the new tab, or -1 - **/ -gint -midori_browser_add_uri (MidoriBrowser* browser, - const gchar* uri) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, - "uri", uri, - "settings", priv->settings, - NULL); - gtk_widget_show (web_view); - - return midori_browser_add_tab (browser, web_view); -} - -/** - * midori_browser_activate_action: - * @browser: a #MidoriBrowser - * @name: name of the action - * - * Activates the specified action. - **/ -void -midori_browser_activate_action (MidoriBrowser* browser, - const gchar* name) -{ - GtkAction* action = _action_by_name (browser, name); - if (action) - gtk_action_activate (action); - else - g_warning (_("Unexpected action '%s'."), name); -} - -/** - * midori_browser_set_current_page: - * @browser: a #MidoriBrowser - * @n: the index of a page - * - * Switches to the page with the index @n. - * - * The widget will also grab the focus automatically. - **/ -void -midori_browser_set_current_page (MidoriBrowser* browser, - gint n) -{ - MidoriBrowserPrivate* priv = browser->priv; - - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); - GtkWidget* scrolled = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n); - GtkWidget* widget = _midori_browser_child_for_scrolled (browser, scrolled); - if (widget && MIDORI_IS_WEB_VIEW (widget) - && !strcmp (midori_web_view_get_display_uri ( - MIDORI_WEB_VIEW (widget)), "")) - gtk_widget_grab_focus (priv->location); - else - gtk_widget_grab_focus (widget); -} - -/** - * midori_browser_get_current_page: - * @browser: a #MidoriBrowser - * - * Determines the currently selected page. - * - * If there is no page present at all, %NULL is returned. - * - * Return value: the selected page, or -1 - **/ -gint -midori_browser_get_current_page (MidoriBrowser* browser) -{ - g_return_val_if_fail (MIDORI_IS_BROWSER (browser), -1); - - MidoriBrowserPrivate* priv = browser->priv; - - return gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); -} - -/** - * midori_browser_set_current_tab: - * @browser: a #MidoriBrowser - * @widget: a #GtkWidget - * - * Switches to the page containing @widget. - * - * The widget will also grab the focus automatically. - **/ -void -midori_browser_set_current_tab (MidoriBrowser* browser, - GtkWidget* widget) -{ - MidoriBrowserPrivate* priv = browser->priv; - - GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); - gint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); - if (widget && MIDORI_IS_WEB_VIEW (widget) - && !strcmp (midori_web_view_get_display_uri ( - MIDORI_WEB_VIEW (widget)), "")) - gtk_widget_grab_focus (priv->location); - else - gtk_widget_grab_focus (widget); -} - -/** - * midori_browser_get_current_tab: - * @browser: a #MidoriBrowser - * - * Retrieves the currently selected tab. - * - * If there is no tab present at all, %NULL is returned. - * - * Return value: the selected tab, or %NULL - **/ -GtkWidget* -midori_browser_get_current_tab (MidoriBrowser* browser) -{ - g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); - - MidoriBrowserPrivate* priv = browser->priv; - - gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); - if (n >= 0) - { - GtkWidget* widget = _midori_browser_child_for_scrolled (browser, - gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n)); - return widget; - } - else - return NULL; -} - -/** - * midori_browser_get_current_web_view: - * @browser: a #MidoriBrowser - * - * Determines the currently selected web view. - * - * If there is no web view selected or if there is no tab present - * at all, %NULL is returned. - * - * See also midori_browser_get_current_page - * - * Return value: the selected web view, or %NULL - **/ -GtkWidget* -midori_browser_get_current_web_view (MidoriBrowser* browser) -{ - g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); - - GtkWidget* web_view = midori_browser_get_current_tab (browser); - return MIDORI_IS_WEB_VIEW (web_view) ? web_view : NULL; -} - -/** - * midori_browser_get_proxy_xbel_folder: - * @browser: a #MidoriBrowser - * - * Retrieves a proxy xbel folder representing the respective proxy xbel items - * of the present web views that can be used for session management. - * - * The folder is created on the first call and will be updated to reflect - * changes to all items automatically. - * - * Note that this implicitly creates proxy xbel items of all web views. - * - * Return value: the proxy #KatzeXbelItem - **/ -KatzeXbelItem* -midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser) -{ - g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); - - MidoriBrowserPrivate* priv = browser->priv; - - if (!priv->proxy_xbel_folder) - { - priv->proxy_xbel_folder = katze_xbel_folder_new (); - // FIXME: Fill in xbel items of all present web views - } - return priv->proxy_xbel_folder; -} - -/** - * midori_browser_quit: - * @browser: a #MidoriBrowser - * - * Quits the browser, including any other browser windows. - **/ -void -midori_browser_quit (MidoriBrowser* browser) -{ - g_return_if_fail (MIDORI_IS_BROWSER (browser)); - - g_signal_emit (browser, signals[QUIT], 0); -} diff --git a/src/midori-browser.h b/src/midori-browser.h deleted file mode 100644 index d029e6a1..00000000 --- a/src/midori-browser.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_BROWSER_H__ -#define __MIDORI_BROWSER_H__ - -#include - -#include - -G_BEGIN_DECLS - -#define MIDORI_TYPE_BROWSER \ - (midori_browser_get_type ()) -#define MIDORI_BROWSER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_BROWSER, MidoriBrowser)) -#define MIDORI_BROWSER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_BROWSER, MidoriBrowserClass)) -#define MIDORI_IS_BROWSER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_BROWSER)) -#define MIDORI_IS_BROWSER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_BROWSER)) -#define MIDORI_BROWSER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_BROWSER, MidoriBrowserClass)) - -typedef struct _MidoriBrowser MidoriBrowser; -typedef struct _MidoriBrowserPrivate MidoriBrowserPrivate; -typedef struct _MidoriBrowserClass MidoriBrowserClass; - -struct _MidoriBrowser -{ - GtkWindow parent_instance; - - MidoriBrowserPrivate* priv; -}; - -struct _MidoriBrowserClass -{ - GtkWindowClass parent_class; - - /* Signals */ - void - (*window_object_cleared) (MidoriBrowser* browser, - WebKitWebFrame* web_frame, - JSContextRef* context, - JSObjectRef* window_object); - void - (*statusbar_text_changed) (MidoriBrowser* browser, - const gchar* text); - void - (*element_motion) (MidoriBrowser* browser, - const gchar* link_uri); - void - (*new_window) (MidoriBrowser* browser, - const gchar* uri); - - void - (*add_tab) (MidoriBrowser* browser, - GtkWidget* widget); - void - (*add_uri) (MidoriBrowser* browser, - const gchar* uri); - void - (*activate_action) (MidoriBrowser* browser, - const gchar* name); - void - (*quit) (MidoriBrowser* browser); -}; - -GType -midori_browser_get_type (void); - -MidoriBrowser* -midori_browser_new (void); - -gint -midori_browser_add_tab (MidoriBrowser* browser, - GtkWidget* widget); - -void -midori_browser_remove_tab (MidoriBrowser* browser, - GtkWidget* widget); - -gint -midori_browser_add_xbel_item (MidoriBrowser* browser, - KatzeXbelItem* xbel_item); - -gint -midori_browser_add_uri (MidoriBrowser* browser, - const gchar* uri); - -void -midori_browser_activate_action (MidoriBrowser* browser, - const gchar* name); - -void -midori_browser_set_current_page (MidoriBrowser* browser, - gint n); - -gint -midori_browser_get_current_page (MidoriBrowser* browser); - -void -midori_browser_set_current_tab (MidoriBrowser* browser, - GtkWidget* widget); - -GtkWidget* -midori_browser_get_current_tab (MidoriBrowser* browser); - -GtkWidget* -midori_browser_get_current_web_view (MidoriBrowser* browser); - -KatzeXbelItem* -midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser); - -void -midori_browser_quit (MidoriBrowser* browser); - -G_END_DECLS - -#endif /* __MIDORI_BROWSER_H__ */ diff --git a/src/midori-console.c b/src/midori-console.c deleted file mode 100644 index 693608da..00000000 --- a/src/midori-console.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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 "midori-console.h" - -#include "sokoke.h" -#include - -G_DEFINE_TYPE (MidoriConsole, midori_console, GTK_TYPE_VBOX) - -struct _MidoriConsolePrivate -{ - GtkWidget* toolbar; - GtkWidget* treeview; -}; - -#define MIDORI_CONSOLE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_CONSOLE, MidoriConsolePrivate)) - -static void -midori_console_class_init (MidoriConsoleClass* class) -{ - g_type_class_add_private (class, sizeof (MidoriConsolePrivate)); -} - -static void -midori_console_button_clear_clicked_cb (GtkToolItem* toolitem, - MidoriConsole* console) -{ - MidoriConsolePrivate* priv = console->priv; - - GtkTreeModel* model = gtk_tree_view_get_model ( - GTK_TREE_VIEW (priv->treeview)); - gtk_tree_store_clear (GTK_TREE_STORE (model)); -} - -static void -midori_console_treeview_render_icon_cb (GtkTreeViewColumn* column, - GtkCellRenderer* renderer, - GtkTreeModel* model, - GtkTreeIter* iter, - GtkWidget* treeview) -{ - // gchar* source_id; - // gtk_tree_model_get (model, iter, 2, &source_id, -1); - - g_object_set (renderer, "stock-id", GTK_STOCK_DIALOG_WARNING, NULL); - - // g_free (source_id); -} - -static void -midori_console_treeview_render_text_cb (GtkTreeViewColumn* column, - GtkCellRenderer* renderer, - GtkTreeModel* model, - GtkTreeIter* iter, - GtkWidget* treeview) -{ - gchar* message; - gint line; - gchar* source_id; - gtk_tree_model_get (model, iter, 0, &message, 1, &line, 2, &source_id, -1); - - gchar* text = g_strdup_printf ("%d @ %s\n%s", line, source_id, message); - g_object_set (renderer, "text", text, NULL); - g_free (text); - - g_free (message); - g_free (source_id); -} - -static void -midori_console_treeview_row_activated_cb (GtkTreeView* treeview, - GtkTreePath* path, - GtkTreeViewColumn* column, - MidoriConsole* console) -{ - /*GtkTreeModel* model = gtk_tree_view_get_model (treeview); - GtkTreeIter iter; - if (gtk_tree_model_get_iter (model, &iter, path)) - { - gchar* source_id; - gtk_tree_model_get (model, &iter, 2, &source_id, -1); - g_free (source_id); - }*/ -} - -static void -midori_console_init (MidoriConsole* console) -{ - console->priv = MIDORI_CONSOLE_GET_PRIVATE (console); - - MidoriConsolePrivate* priv = console->priv; - - // Create the treeview - GtkTreeViewColumn* column; - GtkCellRenderer* renderer_text; - GtkCellRenderer* renderer_pixbuf; - GtkTreeStore* treestore = gtk_tree_store_new (3, G_TYPE_STRING, - G_TYPE_INT, - G_TYPE_STRING); - priv->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore)); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE); - column = gtk_tree_view_column_new (); - renderer_pixbuf = gtk_cell_renderer_pixbuf_new (); - gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE); - gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf, - (GtkTreeCellDataFunc)midori_console_treeview_render_icon_cb, - priv->treeview, NULL); - renderer_text = gtk_cell_renderer_text_new (); - gtk_tree_view_column_pack_start (column, renderer_text, FALSE); - gtk_tree_view_column_set_cell_data_func (column, renderer_text, - (GtkTreeCellDataFunc)midori_console_treeview_render_text_cb, - priv->treeview, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column); - g_object_unref (treestore); - g_signal_connect (priv->treeview, "row-activated", - G_CALLBACK (midori_console_treeview_row_activated_cb), - console); - gtk_widget_show (priv->treeview); - gtk_box_pack_start (GTK_BOX (console), priv->treeview, TRUE, TRUE, 0); -} - -/** - * midori_console_new: - * - * Creates a new empty console. - * - * Return value: a new #MidoriConsole - **/ -GtkWidget* -midori_console_new (void) -{ - MidoriConsole* console = g_object_new (MIDORI_TYPE_CONSOLE, - NULL); - - return GTK_WIDGET (console); -} - -/** - * midori_console_get_toolbar: - * - * Retrieves the toolbar of the console. A new widget is created on - * the first call of this function. - * - * Return value: a new #MidoriConsole - **/ -GtkWidget* -midori_console_get_toolbar (MidoriConsole* console) -{ - g_return_val_if_fail (MIDORI_IS_CONSOLE (console), NULL); - - MidoriConsolePrivate* priv = console->priv; - - if (!priv->toolbar) - { - GtkWidget* toolbar = gtk_toolbar_new (); - gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); - GtkToolItem* toolitem = gtk_tool_item_new (); - // TODO: What about a find entry here that filters e.g. by url? - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); - gtk_widget_show (GTK_WIDGET (toolitem)); - toolitem = gtk_separator_tool_item_new (); - gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), - FALSE); - gtk_tool_item_set_expand (toolitem, TRUE); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); - gtk_widget_show (GTK_WIDGET (toolitem)); - toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLEAR); - gtk_tool_item_set_is_important (toolitem, TRUE); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (midori_console_button_clear_clicked_cb), console); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); - gtk_widget_show (GTK_WIDGET (toolitem)); - priv->toolbar = toolbar; - } - - return priv->toolbar; -} - -/** - * midori_console_add: - * @console: a #MidoriConsole - * @message: a descriptive message - * @line: the line in the source file - * @source_id: the source - * - * Adds a new message to the console. - **/ -void -midori_console_add (MidoriConsole* console, - const gchar* message, - gint line, - const gchar* source_id) -{ - g_return_if_fail (MIDORI_IS_CONSOLE (console)); - - MidoriConsolePrivate* priv = console->priv; - - GtkTreeView* treeview = GTK_TREE_VIEW (priv->treeview); - GtkTreeModel* treemodel = gtk_tree_view_get_model (treeview); - gtk_tree_store_insert_with_values (GTK_TREE_STORE (treemodel), - NULL, NULL, G_MAXINT, - 0, message, 1, line, 2, source_id, -1); -} diff --git a/src/midori-console.h b/src/midori-console.h deleted file mode 100644 index 884c2b2b..00000000 --- a/src/midori-console.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_CONSOLE_H__ -#define __MIDORI_CONSOLE_H__ - -#include - -#include - -G_BEGIN_DECLS - -#define MIDORI_TYPE_CONSOLE \ - (midori_console_get_type ()) -#define MIDORI_CONSOLE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_CONSOLE, MidoriConsole)) -#define MIDORI_CONSOLE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_CONSOLE, MidoriConsoleClass)) -#define MIDORI_IS_CONSOLE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_CONSOLE)) -#define MIDORI_IS_CONSOLE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_CONSOLE)) -#define MIDORI_CONSOLE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_CONSOLE, MidoriConsoleClass)) - -typedef struct _MidoriConsole MidoriConsole; -typedef struct _MidoriConsolePrivate MidoriConsolePrivate; -typedef struct _MidoriConsoleClass MidoriConsoleClass; - -struct _MidoriConsole -{ - GtkVBox parent_instance; - - MidoriConsolePrivate* priv; -}; - -struct _MidoriConsoleClass -{ - GtkVBoxClass parent_class; -}; - -GType -midori_console_get_type (void); - -GtkWidget* -midori_console_new (void); - -GtkWidget* -midori_console_get_toolbar (MidoriConsole* console); - -void -midori_console_add (MidoriConsole* console, - const gchar* message, - gint line, - const gchar* source_id); - -G_END_DECLS - -#endif /* __MIDORI_CONSOLE_H__ */ diff --git a/src/midori-panel.c b/src/midori-panel.c deleted file mode 100644 index 9c321d1e..00000000 --- a/src/midori-panel.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - 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 "midori-panel.h" - -#include "sokoke.h" -#include - -G_DEFINE_TYPE (MidoriPanel, midori_panel, GTK_TYPE_HBOX) - -struct _MidoriPanelPrivate -{ - GtkWidget* toolbar; - GtkWidget* toolbar_label; - GtkWidget* frame; - GtkWidget* toolbook; - GtkWidget* notebook; - GSList* group; - GtkMenu* menu; -}; - -#define MIDORI_PANEL_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_PANEL, MidoriPanelPrivate)) - -enum -{ - PROP_0, - - PROP_SHADOW_TYPE, - PROP_MENU, - PROP_PAGE -}; - -enum { - CLOSE, - SWITCH_PAGE, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static void -midori_panel_finalize (GObject* object); - -static void -midori_panel_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec); - -static void -midori_panel_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec); - -static gboolean -midori_panel_close_cb (MidoriPanel* panel) -{ - gtk_widget_hide (GTK_WIDGET (panel)); - return FALSE; -} - -static void -midori_cclosure_marshal_BOOLEAN__VOID (GClosure* closure, - GValue* return_value, - guint n_param_values, - const GValue* param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gboolean(*GMarshalFunc_BOOLEAN__VOID) (gpointer data1, - gpointer data2); - register GMarshalFunc_BOOLEAN__VOID callback; - register GCClosure* cc = (GCClosure*) closure; - register gpointer data1, data2; - gboolean v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 1); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data - ? marshal_data : cc->callback); - v_return = callback (data1, data2); - g_value_set_boolean (return_value, v_return); -} - -static void -midori_panel_class_init (MidoriPanelClass* class) -{ - - signals[CLOSE] = g_signal_new ( - "close", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriPanelClass, close), - g_signal_accumulator_true_handled, - NULL, - midori_cclosure_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, 0); - - signals[SWITCH_PAGE] = g_signal_new ( - "switch-page", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriPanelClass, switch_page), - 0, - NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - - class->close = midori_panel_close_cb; - - GObjectClass* gobject_class = G_OBJECT_CLASS (class); - gobject_class->finalize = midori_panel_finalize; - gobject_class->set_property = midori_panel_set_property; - gobject_class->get_property = midori_panel_get_property; - - GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; - - g_object_class_install_property (gobject_class, - PROP_SHADOW_TYPE, - g_param_spec_enum ( - "shadow-type", - "Shadow Type", - _("Appearance of the shadow around each panel"), - GTK_TYPE_SHADOW_TYPE, - GTK_SHADOW_NONE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_MENU, - g_param_spec_object ( - "menu", - "Menu", - _("Menu to hold panel items"), - GTK_TYPE_MENU, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_PAGE, - g_param_spec_int ( - "page", - "Page", - _("The index of the current page"), - -1, G_MAXINT, -1, - flags)); - - g_type_class_add_private (class, sizeof (MidoriPanelPrivate)); -} - -static void -midori_panel_button_close_clicked_cb (GtkWidget* toolitem, - MidoriPanel* panel) -{ - gboolean return_value; - g_signal_emit (panel, signals[CLOSE], 0, &return_value); -} - -static void -midori_panel_init (MidoriPanel* panel) -{ - panel->priv = MIDORI_PANEL_GET_PRIVATE (panel); - - MidoriPanelPrivate* priv = panel->priv; - - // Create the sidebar - priv->toolbar = gtk_toolbar_new (); - gtk_toolbar_set_style (GTK_TOOLBAR (priv->toolbar), GTK_TOOLBAR_BOTH); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->toolbar), - GTK_ICON_SIZE_BUTTON); - gtk_toolbar_set_orientation (GTK_TOOLBAR (priv->toolbar), - GTK_ORIENTATION_VERTICAL); - gtk_box_pack_start (GTK_BOX (panel), priv->toolbar, FALSE, FALSE, 0); - gtk_widget_show_all (priv->toolbar); - GtkWidget* vbox = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0); - - // Create the titlebar - GtkWidget* labelbar = gtk_toolbar_new (); - gtk_toolbar_set_icon_size (GTK_TOOLBAR (labelbar), GTK_ICON_SIZE_MENU); - gtk_toolbar_set_style (GTK_TOOLBAR (labelbar), GTK_TOOLBAR_ICONS); - GtkToolItem* toolitem = gtk_tool_item_new (); - gtk_tool_item_set_expand (toolitem, TRUE); - priv->toolbar_label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (priv->toolbar_label), 0, 0.5); - gtk_container_add (GTK_CONTAINER (toolitem), priv->toolbar_label); - gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6); - gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1); - toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE); - gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("Close panel")); - sokoke_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem), _("Close panel")); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (midori_panel_button_close_clicked_cb), panel); - gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1); - gtk_box_pack_start (GTK_BOX (vbox), labelbar, FALSE, FALSE, 0); - gtk_widget_show_all (vbox); - - // Create the toolbook - priv->toolbook = gtk_notebook_new (); - gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->toolbook), FALSE); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->toolbook), FALSE); - gtk_box_pack_start (GTK_BOX (vbox), priv->toolbook, FALSE, FALSE, 0); - gtk_widget_show (priv->toolbook); - - // Create the notebook - priv->notebook = gtk_notebook_new (); - gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE); - priv->frame = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (priv->frame), priv->notebook); - gtk_box_pack_start (GTK_BOX (vbox), priv->frame, TRUE, TRUE, 0); - gtk_widget_show_all (priv->frame); -} - -static void -midori_panel_finalize (GObject* object) -{ - MidoriPanel* panel = MIDORI_PANEL (object); - MidoriPanelPrivate* priv = panel->priv; - - if (priv->menu) - { - // FIXME: Remove all menu items - } - - G_OBJECT_CLASS (midori_panel_parent_class)->finalize (object); -} - -static void -midori_panel_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec) -{ - MidoriPanel* panel = MIDORI_PANEL (object); - MidoriPanelPrivate* priv = panel->priv; - - switch (prop_id) - { - case PROP_SHADOW_TYPE: - gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), - g_value_get_enum (value)); - break; - case PROP_MENU: - katze_object_assign (priv->menu, g_value_get_object (value)); - // FIXME: Move existing items to the new menu - break; - case PROP_PAGE: - midori_panel_set_current_page (panel, g_value_get_int (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_panel_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec) -{ - MidoriPanel* panel = MIDORI_PANEL (object); - MidoriPanelPrivate* priv = panel->priv; - - switch (prop_id) - { - case PROP_SHADOW_TYPE: - g_value_set_enum (value, - gtk_frame_get_shadow_type (GTK_FRAME (priv->frame))); - break; - case PROP_MENU: - g_value_set_object (value, priv->menu); - break; - case PROP_PAGE: - g_value_set_int (value, midori_panel_get_current_page (panel)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * midori_panel_new: - * - * Creates a new empty panel. - * - * Return value: a new #MidoriPanel - **/ -GtkWidget* -midori_panel_new (void) -{ - MidoriPanel* panel = g_object_new (MIDORI_TYPE_PANEL, - NULL); - - return GTK_WIDGET (panel); -} - -static void -midori_panel_menu_item_activate_cb (GtkWidget* widget, - MidoriPanel* panel) -{ - GtkWidget* child = g_object_get_data (G_OBJECT (widget), "page"); - guint n = midori_panel_page_num (panel, child); - midori_panel_set_current_page (panel, n); - g_signal_emit (panel, signals[SWITCH_PAGE], 0, n); -} - -/** - * midori_panel_append_page: - * @panel: a #MidoriPanel - * @child: the child widget - * @toolbar: a toolbar widget, or %NULL - * @icon: a stock ID or icon name, or %NULL - * @label: a string to use as the label, or %NULL - * - * Appends a new page to the panel. If @toolbar is specified it will - * be packaged above @child. - * - * If @icon is an icon name, the according image is used as an - * icon for this page. - * - * If @label is given, it is used as the label of this page. - * - * In the case of an error, -1 is returned. - * - * Return value: the index of the new page, or -1 - **/ -gint -midori_panel_append_page (MidoriPanel* panel, - GtkWidget* child, - GtkWidget* toolbar, - const gchar* icon, - const gchar* label) -{ - g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); - g_return_val_if_fail (GTK_IS_WIDGET (child), -1); - g_return_val_if_fail (!toolbar || GTK_IS_WIDGET (toolbar), -1); - - MidoriPanelPrivate* priv = panel->priv; - - GtkWidget* scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS); - gtk_widget_show (scrolled); - GtkWidget* widget; - GObjectClass* gobject_class = G_OBJECT_GET_CLASS (child); - if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal) - widget = child; - else - { - widget = gtk_viewport_new (NULL, NULL); - gtk_widget_show (widget); - gtk_container_add (GTK_CONTAINER (widget), child); - } - gtk_container_add (GTK_CONTAINER (scrolled), widget); - gtk_container_add (GTK_CONTAINER (priv->notebook), scrolled); - - if (!toolbar) - toolbar = gtk_event_box_new (); - gtk_widget_show (toolbar); - gtk_container_add (GTK_CONTAINER (priv->toolbook), toolbar); - - guint n = midori_panel_page_num (panel, child); - - const gchar* text = label ? label : _("Untitled"); - g_object_set_data (G_OBJECT (child), "label", (gchar*)text); - - GtkWidget* image; - GtkToolItem* toolitem = gtk_radio_tool_button_new (priv->group); - priv->group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON ( - toolitem)); - gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), text); - if (icon) - { - image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_BUTTON); - gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image); - } - g_object_set_data (G_OBJECT (toolitem), "page", child); - g_signal_connect (toolitem, "clicked", - G_CALLBACK (midori_panel_menu_item_activate_cb), panel); - gtk_widget_show_all (GTK_WIDGET (toolitem)); - gtk_toolbar_insert (GTK_TOOLBAR (priv->toolbar), toolitem, -1); - - if (priv->menu) - { - GtkWidget* menuitem = gtk_image_menu_item_new_with_label (text); - if (icon) - { - image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), - image); - } - gtk_widget_show_all (menuitem); - g_object_set_data (G_OBJECT (menuitem), "page", child); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_panel_menu_item_activate_cb), - panel); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menuitem); - } - - return n; -} - -/** - * midori_panel_get_current_page: - * @panel: a #MidoriPanel - * - * Retrieves the index of the currently selected page. - * - * If @panel has no children, -1 is returned. - * - * Return value: the index of the current page, or -1 - **/ -gint -midori_panel_get_current_page (MidoriPanel* panel) -{ - g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); - - MidoriPanelPrivate* priv = panel->priv; - - return gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)); -} - -static GtkWidget* -_midori_panel_child_for_scrolled (MidoriPanel* panel, - GtkWidget* scrolled) -{ - GtkWidget* child = gtk_bin_get_child (GTK_BIN (scrolled)); - if (GTK_IS_VIEWPORT (child)) - child = gtk_bin_get_child (GTK_BIN (child)); - return child; -} - -/** - * midori_panel_get_nth_page: - * @panel: a #MidoriPanel - * - * Retrieves the child widget of the nth page. - * - * If @panel has no children, %NULL is returned. - * - * Return value: the child widget of the new page, or %NULL - **/ -GtkWidget* -midori_panel_get_nth_page (MidoriPanel* panel, - guint page_num) -{ - g_return_val_if_fail (MIDORI_IS_PANEL (panel), NULL); - - MidoriPanelPrivate* priv = panel->priv; - - GtkWidget* scrolled = gtk_notebook_get_nth_page ( - GTK_NOTEBOOK (priv->notebook), page_num); - if (scrolled) - return _midori_panel_child_for_scrolled (panel, scrolled); - return NULL; -} - -/** - * midori_panel_get_n_pages: - * @panel: a #MidoriPanel - * - * Retrieves the number of pages contained in the panel. - * - * Return value: the number of pages - **/ -guint -midori_panel_get_n_pages (MidoriPanel* panel) -{ - g_return_val_if_fail (MIDORI_IS_PANEL (panel), 0); - - MidoriPanelPrivate* priv = panel->priv; - - return gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)); -} - -static GtkWidget* -_midori_panel_scrolled_for_child (MidoriPanel* panel, - GtkWidget* child) -{ - GtkWidget* scrolled = gtk_widget_get_parent (GTK_WIDGET (child)); - if (GTK_IS_VIEWPORT (scrolled)) - scrolled = gtk_widget_get_parent (scrolled); - return scrolled; -} - -/** - * midori_panel_page_num: - * @panel: a #MidoriPanel - * - * Retrieves the index of the page associated to @widget. - * - * If @panel has no children, -1 is returned. - * - * Return value: the index of page associated to @widget, or -1 - **/ -gint -midori_panel_page_num (MidoriPanel* panel, - GtkWidget* child) -{ - g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1); - - MidoriPanelPrivate* priv = panel->priv; - - GtkWidget* scrolled = _midori_panel_scrolled_for_child (panel, child); - return gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled); -} - -/** - * midori_panel_set_current_page: - * @panel: a #MidoriPanel - * @n: index of the page to switch to, or -1 to mean the last page - * - * Switches to the page with the given index. - * - * The child must be visible, otherwise the underlying GtkNotebook will - * silently ignore the attempt to switch the page. - **/ -void -midori_panel_set_current_page (MidoriPanel* panel, - gint n) -{ - g_return_if_fail (MIDORI_IS_PANEL (panel)); - - MidoriPanelPrivate* priv = panel->priv; - - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->toolbook), n); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n); - GtkWidget* child = midori_panel_get_nth_page (panel, n); - if (child) - { - const gchar* label = g_object_get_data (G_OBJECT (child), "label"); - g_object_set (priv->toolbar_label, "label", label, NULL); - } -} diff --git a/src/midori-panel.h b/src/midori-panel.h deleted file mode 100644 index eb3908bc..00000000 --- a/src/midori-panel.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_PANEL_H__ -#define __MIDORI_PANEL_H__ - -#include - -#include - -G_BEGIN_DECLS - -#define MIDORI_TYPE_PANEL \ - (midori_panel_get_type ()) -#define MIDORI_PANEL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PANEL, MidoriPanel)) -#define MIDORI_PANEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_PANEL, MidoriPanelClass)) -#define MIDORI_IS_PANEL(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PANEL)) -#define MIDORI_IS_PANEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PANEL)) -#define MIDORI_PANEL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PANEL, MidoriPanelClass)) - -typedef struct _MidoriPanel MidoriPanel; -typedef struct _MidoriPanelPrivate MidoriPanelPrivate; -typedef struct _MidoriPanelClass MidoriPanelClass; - -struct _MidoriPanel -{ - GtkHBox parent_instance; - - MidoriPanelPrivate* priv; -}; - -struct _MidoriPanelClass -{ - GtkHBoxClass parent_class; - - /* Signals */ - gboolean - (*close) (MidoriPanel* panel); - - void - (*switch_page) (MidoriPanel* panel, - gint page); -}; - -GType -midori_panel_get_type (void); - -GtkWidget* -midori_panel_new (void); - -gint -midori_panel_append_page (MidoriPanel* panel, - GtkWidget* child, - GtkWidget* toolbar, - const gchar* icon, - const gchar* label); - -gint -midori_panel_get_current_page (MidoriPanel* panel); - -GtkWidget* -midori_panel_get_nth_page (MidoriPanel* panel, - guint page_num); - -guint -midori_panel_get_n_pages (MidoriPanel* panel); - -gint -midori_panel_page_num (MidoriPanel* panel, - GtkWidget* child); - -void -midori_panel_set_current_page (MidoriPanel* panel, - gint n); - -G_END_DECLS - -#endif /* __MIDORI_PANEL_H__ */ diff --git a/src/midori-preferences.c b/src/midori-preferences.c deleted file mode 100644 index b3ddc9e7..00000000 --- a/src/midori-preferences.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - 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 "midori-preferences.h" - -#include "sokoke.h" - -#include - -G_DEFINE_TYPE (MidoriPreferences, midori_preferences, GTK_TYPE_DIALOG) - -struct _MidoriPreferencesPrivate -{ - GtkWidget* notebook; -}; - -#define MIDORI_PREFERENCES_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_PREFERENCES, MidoriPreferencesPrivate)) - -enum -{ - PROP_0, - - PROP_SETTINGS -}; - -static void -midori_preferences_finalize (GObject* object); - -static void -midori_preferences_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec); - -static void -midori_preferences_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec); - -static void -midori_preferences_class_init (MidoriPreferencesClass* class) -{ - GObjectClass* gobject_class = G_OBJECT_CLASS (class); - gobject_class->finalize = midori_preferences_finalize; - gobject_class->set_property = midori_preferences_set_property; - gobject_class->get_property = midori_preferences_get_property; - - g_object_class_install_property (gobject_class, - PROP_SETTINGS, - g_param_spec_object ( - "settings", - "Settings", - _("Settings instance to provide properties"), - MIDORI_TYPE_WEB_SETTINGS, - G_PARAM_WRITABLE)); - - g_type_class_add_private (class, sizeof (MidoriPreferencesPrivate)); -} - -static void -clear_button_clicked_cb (GtkWidget* button, GtkWidget* file_chooser) -{ - gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (file_chooser), ""); - // Emit "file-set" manually for Gtk doesn't emit it otherwise - g_signal_emit_by_name (file_chooser, "file-set"); -} - -static void -midori_preferences_init (MidoriPreferences* preferences) -{ - preferences->priv = MIDORI_PREFERENCES_GET_PRIVATE (preferences); - MidoriPreferencesPrivate* priv = preferences->priv; - - priv->notebook = NULL; - - gchar* dialog_title = g_strdup_printf (_("%s Preferences"), - g_get_application_name ()); - g_object_set (preferences, - "icon-name", GTK_STOCK_PREFERENCES, - "title", dialog_title, - "has-separator", FALSE, - NULL); - gtk_dialog_add_buttons (GTK_DIALOG (preferences), - GTK_STOCK_HELP, GTK_RESPONSE_HELP, - GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, - NULL); - // TODO: Implement some kind of help function - gtk_dialog_set_response_sensitive (GTK_DIALOG (preferences), - GTK_RESPONSE_HELP, FALSE); //... - g_signal_connect (preferences, "response", - G_CALLBACK (gtk_widget_destroy), preferences); - - // TODO: Do we want tooltips for explainations or can we omit that? - g_free (dialog_title); -} - -static void -midori_preferences_finalize (GObject* object) -{ - G_OBJECT_CLASS (midori_preferences_parent_class)->finalize (object); -} - -static void -midori_preferences_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec) -{ - MidoriPreferences* preferences = MIDORI_PREFERENCES (object); - - switch (prop_id) - { - case PROP_SETTINGS: - { - GtkWidget* xfce_heading; - GtkWindow* parent; - g_object_get (object, "transient-for", &parent, NULL); - if ((xfce_heading = sokoke_xfce_header_new ( - gtk_window_get_icon_name (parent), - gtk_window_get_title (GTK_WINDOW (object))))) - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox), - xfce_heading, FALSE, FALSE, 0); - midori_preferences_set_settings (preferences, - g_value_get_object (value)); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_preferences_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec) -{ - switch (prop_id) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * midori_preferences_new: - * @parent: the parent window - * @settings: the settings - * - * Creates a new preferences dialog. - * - * Return value: a new #MidoriPreferences - **/ -GtkWidget* -midori_preferences_new (GtkWindow* parent, - MidoriWebSettings* settings) -{ - g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL); - g_return_val_if_fail (MIDORI_IS_WEB_SETTINGS (settings), NULL); - - MidoriPreferences* preferences = g_object_new (MIDORI_TYPE_PREFERENCES, - "transient-for", parent, - "settings", settings, - NULL); - - return GTK_WIDGET (preferences); -} - -/** - * midori_preferences_set_settings: - * @settings: the settings - * - * Assigns a settings instance to a preferences dialog. - * - * Note: This must not be called more than once. - **/ -void -midori_preferences_set_settings (MidoriPreferences* preferences, - MidoriWebSettings* settings) -{ - g_return_if_fail (MIDORI_IS_PREFERENCES (preferences)); - g_return_if_fail (MIDORI_IS_WEB_SETTINGS (settings)); - - MidoriPreferencesPrivate* priv = preferences->priv; - - g_return_if_fail (!priv->notebook); - - priv->notebook = gtk_notebook_new (); - gtk_container_set_border_width (GTK_CONTAINER (priv->notebook), 6); - GtkSizeGroup* sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); - GtkWidget* page; GtkWidget* frame; GtkWidget* table; GtkWidget* align; - GtkWidget* label; GtkWidget* button; - GtkWidget* entry; GtkWidget* hbox; - #define PAGE_NEW(__label) page = gtk_vbox_new (FALSE, 0); \ - gtk_container_set_border_width (GTK_CONTAINER (page), 5); \ - gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), page, \ - gtk_label_new (__label)) - #define FRAME_NEW(__label) frame = sokoke_hig_frame_new (__label); \ - gtk_container_set_border_width (GTK_CONTAINER (frame), 5); \ - gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); - #define TABLE_NEW(__rows, __cols) table = gtk_table_new ( \ - __rows, __cols, FALSE); \ - gtk_container_set_border_width (GTK_CONTAINER (table), 5); \ - gtk_container_add (GTK_CONTAINER (frame), table); - #define WIDGET_ADD(__widget, __left, __right, __top, __bottom) \ - gtk_table_attach (GTK_TABLE (table), __widget \ - , __left, __right, __top, __bottom \ - , GTK_FILL, GTK_FILL, 8, 2) - #define FILLED_ADD(__widget, __left, __right, __top, __bottom) \ - gtk_table_attach (GTK_TABLE (table), __widget \ - , __left, __right, __top, __bottom\ - , GTK_EXPAND | GTK_FILL, GTK_FILL, 8, 2) - #define INDENTED_ADD(__widget, __left, __right, __top, __bottom) \ - align = gtk_alignment_new (0, 0.5, 0, 0); \ - gtk_container_add (GTK_CONTAINER (align), __widget); \ - gtk_size_group_add_widget (sizegroup, align); \ - WIDGET_ADD (align, __left, __right, __top, __bottom) - #define SPANNED_ADD(__widget, __left, __right, __top, __bottom) \ - align = gtk_alignment_new (0, 0.5, 0, 0); \ - gtk_container_add (GTK_CONTAINER (align), __widget); \ - FILLED_ADD (align, __left, __right, __top, __bottom) - // Page "General" - PAGE_NEW (_("General")); - FRAME_NEW (_("Startup")); - TABLE_NEW (2, 2); - label = katze_property_label (settings, "load-on-startup"); - INDENTED_ADD (label, 0, 1, 0, 1); - button = katze_property_proxy (settings, "load-on-startup", NULL); - FILLED_ADD (button, 1, 2, 0, 1); - label = katze_property_label (settings, "homepage"); - INDENTED_ADD (label, 0, 1, 1, 2); - entry = katze_property_proxy (settings, "homepage", NULL); - FILLED_ADD (entry, 1, 2, 1, 2); - // TODO: We need something like "use current website" - FRAME_NEW (_("Transfers")); - TABLE_NEW (1, 2); - label = katze_property_label (settings, "download-folder"); - INDENTED_ADD (label, 0, 1, 0, 1); - button = katze_property_proxy (settings, "download-folder", "folder"); - FILLED_ADD (button, 1, 2, 0, 1); - button = katze_property_proxy (settings, "show-download-notification", "blurb"); - SPANNED_ADD (button, 0, 2, 1, 2); - - // Page "Appearance" - PAGE_NEW (_("Appearance")); - FRAME_NEW (_("Font settings")); - TABLE_NEW (5, 2); - label = katze_property_label (settings, "default-font-family"); - INDENTED_ADD (label, 0, 1, 0, 1); - hbox = gtk_hbox_new (FALSE, 4); - button = katze_property_proxy (settings, "default-font-family", "font"); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); - entry = katze_property_proxy (settings, "default-font-size", NULL); - gtk_box_pack_end (GTK_BOX (hbox), entry, FALSE, FALSE, 4); - FILLED_ADD (hbox, 1, 2, 0, 1); - label = katze_property_label (settings, "minimum-font-size"); - INDENTED_ADD (label, 0, 1, 1, 2); - hbox = gtk_hbox_new (FALSE, 4); - entry = katze_property_proxy (settings, "minimum-font-size", NULL); - INDENTED_ADD (entry, 1, 2, 1, 2); - label = katze_property_label (settings, "preferred-encoding"); - INDENTED_ADD (label, 0, 1, 2, 3); - button = katze_property_proxy (settings, "preferred-encoding", NULL); - FILLED_ADD (button, 1, 2, 2, 3); - - // Page "Behavior" - PAGE_NEW (_("Behavior")); - FRAME_NEW (_("Features")); - TABLE_NEW (5, 2); - button = katze_property_proxy (settings, "auto-load-images", NULL); - INDENTED_ADD (button, 0, 1, 0, 1); - button = katze_property_proxy (settings, "auto-shrink-images", NULL); - SPANNED_ADD (button, 1, 2, 0, 1); - button = katze_property_proxy (settings, "print-backgrounds", NULL); - INDENTED_ADD (button, 0, 1, 1, 2); - button = katze_property_proxy (settings, "resizable-text-areas", NULL); - SPANNED_ADD (button, 1, 2, 1, 2); - button = katze_property_proxy (settings, "enable-scripts", NULL); - INDENTED_ADD (button, 0, 1, 2, 3); - button = katze_property_proxy (settings, "enable-plugins", NULL); - SPANNED_ADD(button, 1, 2, 2, 3); - label = katze_property_label (settings, "user-stylesheet-uri"); - INDENTED_ADD (label, 0, 1, 3, 4); - hbox = gtk_hbox_new (FALSE, 4); - entry = katze_property_proxy (settings, "user-stylesheet-uri", "uri"); - gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); - button = gtk_button_new (); - gtk_container_add (GTK_CONTAINER (button), - gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU)); - g_signal_connect (button, "clicked", - G_CALLBACK (clear_button_clicked_cb), entry); - gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 4); - FILLED_ADD (hbox, 1, 2, 3, 4); - label = katze_property_label (settings, "location-entry-search"); - INDENTED_ADD (label, 0, 1, 4, 5); - entry = katze_property_proxy (settings, "location-entry-search", NULL); - FILLED_ADD (entry, 1, 2, 4, 5); - - // Page "Interface" - PAGE_NEW (_("Interface")); - FRAME_NEW (_("Navigationbar")); - TABLE_NEW (3, 2); - INDENTED_ADD (katze_property_label (settings, "toolbar-style"), 0, 1, 0, 1); - button = katze_property_proxy (settings, "toolbar-style", NULL); - FILLED_ADD(button, 1, 2, 0, 1); - button = katze_property_proxy (settings, "show-new-tab", NULL); - INDENTED_ADD (button, 0, 1, 1, 2); - button = katze_property_proxy (settings, "show-web-search", NULL); - SPANNED_ADD (button, 1, 2, 1, 2); - button = katze_property_proxy (settings, "show-homepage", NULL); - INDENTED_ADD (button, 0, 1, 2, 3); - button = katze_property_proxy (settings, "show-trash", NULL); - SPANNED_ADD (button, 1, 2, 2, 3); - FRAME_NEW(_("Browsing")); - TABLE_NEW (3, 2); - label = katze_property_label (settings, "open-new-pages-in"); - INDENTED_ADD (label, 0, 1, 0, 1); - button = katze_property_proxy (settings, "open-new-pages-in", NULL); - FILLED_ADD (button, 1, 2, 0, 1); - button = katze_property_proxy (settings, "middle-click-opens-selection", NULL); - INDENTED_ADD (button, 0, 1, 1, 2); - button = katze_property_proxy (settings, "open-tabs-in-the-background", NULL); - SPANNED_ADD (button, 1, 2, 1, 2); - button = katze_property_proxy (settings, "open-popups-in-tabs", NULL); - SPANNED_ADD (button, 0, 1, 2, 3); - button = katze_property_proxy (settings, "close-buttons-on-tabs", NULL); - SPANNED_ADD (button, 1, 2, 2, 3); - - // Page "Network" - PAGE_NEW (_("Network")); - FRAME_NEW (_("Network")); - TABLE_NEW (2, 2); - label = katze_property_label (settings, "http-proxy"); - INDENTED_ADD (label, 0, 1, 0, 1); - button = katze_property_proxy (settings, "http-proxy", NULL); - FILLED_ADD (button, 1, 2, 0, 1); - label = katze_property_label (settings, "cache-size"); - INDENTED_ADD (label, 0, 1, 1, 2); - hbox = gtk_hbox_new (FALSE, 4); - entry = katze_property_proxy (settings, "cache-size", NULL); - gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("MB")), - FALSE, FALSE, 0); - FILLED_ADD (hbox, 1, 2, 1, 2); - - // Page "Privacy" - PAGE_NEW (_("Privacy")); - FRAME_NEW (_("Web Cookies")); - TABLE_NEW (3, 2); - label = katze_property_label (settings, "accept-cookies"); - INDENTED_ADD (label, 0, 1, 0, 1); - button = katze_property_proxy (settings, "accept-cookies", NULL); - FILLED_ADD (button, 1, 2, 0, 1); - button = katze_property_proxy (settings, "original-cookies-only", "blurb"); - SPANNED_ADD (button, 0, 2, 1, 2); - label = katze_property_label (settings, "maximum-cookie-age"); - INDENTED_ADD (label, 0, 1, 2, 3); - hbox = gtk_hbox_new (FALSE, 4); - entry = katze_property_proxy (settings, "maximum-cookie-age", NULL); - gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("days")), - FALSE, FALSE, 0); - FILLED_ADD (hbox, 1, 2, 2, 3); - FRAME_NEW (_("History")); - TABLE_NEW (3, 2); - button = katze_property_proxy (settings, "remember-last-visited-pages", NULL); - SPANNED_ADD (button, 0, 1, 0, 1); - hbox = gtk_hbox_new (FALSE, 4); - button = katze_property_proxy (settings, "maximum-history-age", NULL); - gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("days")), - FALSE, FALSE, 0); - SPANNED_ADD (hbox, 1, 2, 0, 1); - button = katze_property_proxy (settings, "remember-last-form-inputs", NULL); - SPANNED_ADD (button, 0, 2, 1, 2); - button = katze_property_proxy (settings, "remember-last-downloaded-files", NULL); - SPANNED_ADD (button, 0, 2, 2, 3); - - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox), - priv->notebook, FALSE, FALSE, 4); - gtk_widget_show_all (GTK_DIALOG (preferences)->vbox); -} diff --git a/src/midori-preferences.h b/src/midori-preferences.h deleted file mode 100644 index e47d843c..00000000 --- a/src/midori-preferences.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_PREFERENCES_H__ -#define __MIDORI_PREFERENCES_H__ - -#include "midori-websettings.h" - -#include - -#include - -G_BEGIN_DECLS - -#define MIDORI_TYPE_PREFERENCES \ - (midori_preferences_get_type ()) -#define MIDORI_PREFERENCES(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PREFERENCES, MidoriPreferences)) -#define MIDORI_PREFERENCES_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_PREFERENCES, MidoriPreferencesClass)) -#define MIDORI_IS_PREFERENCES(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PREFERENCES)) -#define MIDORI_IS_PREFERENCES_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PREFERENCES)) -#define MIDORI_PREFERENCES_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PREFERENCES, MidoriPreferencesClass)) - -typedef struct _MidoriPreferences MidoriPreferences; -typedef struct _MidoriPreferencesPrivate MidoriPreferencesPrivate; -typedef struct _MidoriPreferencesClass MidoriPreferencesClass; - -struct _MidoriPreferences -{ - GtkDialog parent_instance; - - MidoriPreferencesPrivate* priv; -}; - -struct _MidoriPreferencesClass -{ - GtkDialogClass parent_class; -}; - -GType -midori_preferences_get_type (void); - -GtkWidget* -midori_preferences_new (GtkWindow* parent, - MidoriWebSettings* settings); - -void -midori_preferences_set_settings (MidoriPreferences* preferences, - MidoriWebSettings* settings); - -G_END_DECLS - -#endif /* __MIDORI_PREFERENCES_H__ */ diff --git a/src/midori-trash.c b/src/midori-trash.c deleted file mode 100644 index 10dce2c8..00000000 --- a/src/midori-trash.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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 "midori-trash.h" - -#include "sokoke.h" -#include - -G_DEFINE_TYPE (MidoriTrash, midori_trash, G_TYPE_OBJECT) - -struct _MidoriTrashPrivate -{ - guint limit; - KatzeXbelItem* xbel_folder; -}; - -#define MIDORI_TRASH_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_TRASH, MidoriTrashPrivate)) - -enum -{ - PROP_0, - - PROP_LIMIT -}; - -enum { - INSERTED, - REMOVED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static void -midori_trash_finalize (GObject* object); - -static void -midori_trash_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec); - -static void -midori_trash_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec); - -static void -midori_trash_class_init (MidoriTrashClass* class) -{ - signals[INSERTED] = g_signal_new ( - "inserted", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriTrashClass, inserted), - 0, - NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, - G_TYPE_UINT); - - signals[REMOVED] = g_signal_new ( - "removed", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriTrashClass, removed), - 0, - NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, - G_TYPE_UINT); - - GObjectClass* gobject_class = G_OBJECT_CLASS (class); - gobject_class->finalize = midori_trash_finalize; - gobject_class->set_property = midori_trash_set_property; - gobject_class->get_property = midori_trash_get_property; - - GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; - - g_object_class_install_property (gobject_class, - PROP_LIMIT, - g_param_spec_uint ( - "limit", - "Limit", - _("The maximum number of items"), - 0, G_MAXUINT, 10, - flags)); - - g_type_class_add_private (class, sizeof (MidoriTrashPrivate)); -} - - - -static void -midori_trash_init (MidoriTrash* trash) -{ - trash->priv = MIDORI_TRASH_GET_PRIVATE (trash); - - MidoriTrashPrivate* priv = trash->priv; - - priv->xbel_folder = katze_xbel_folder_new (); -} - -static void -midori_trash_finalize (GObject* object) -{ - MidoriTrash* trash = MIDORI_TRASH (object); - MidoriTrashPrivate* priv = trash->priv; - - katze_xbel_item_unref (priv->xbel_folder); - - G_OBJECT_CLASS (midori_trash_parent_class)->finalize (object); -} - -static void -midori_trash_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec) -{ - MidoriTrash* trash = MIDORI_TRASH (object); - MidoriTrashPrivate* priv = trash->priv; - - switch (prop_id) - { - case PROP_LIMIT: - priv->limit = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_trash_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec) -{ - MidoriTrash* trash = MIDORI_TRASH (object); - MidoriTrashPrivate* priv = trash->priv; - - switch (prop_id) - { - case PROP_LIMIT: - g_value_set_uint (value, priv->limit); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * midori_trash_new: - * @limit: the maximum number of items - * - * Creates a new #MidoriTrash that can contain a specified number of items, - * meaning that each additional item will replace the oldest existing item. - * - * The value 0 for @limit actually means that there is no limit. - * - * You will typically want to assign this to a #MidoriBrowser. - * - * Return value: a new #MidoriTrash - **/ -MidoriTrash* -midori_trash_new (guint limit) -{ - MidoriTrash* trash = g_object_new (MIDORI_TYPE_TRASH, - "limit", limit, - NULL); - - return trash; -} - -/** - * midori_trash_is_empty: - * @trash: a #MidoriTrash - * - * Determines whether the @trash contains no items. - * - * Return value: %TRUE if there are no items, %FALSE otherwise - **/ -gboolean -midori_trash_is_empty (MidoriTrash* trash) -{ - g_return_val_if_fail (MIDORI_IS_TRASH (trash), FALSE); - - MidoriTrashPrivate* priv = trash->priv; - - return katze_xbel_folder_is_empty (priv->xbel_folder); -} - -/** - * midori_trash_get_n_items: - * @trash: a #MidoriTrash - * - * Determines the number of items in @trash. - * - * Return value: the current number of items - **/ -guint -midori_trash_get_n_items (MidoriTrash* trash) -{ - g_return_val_if_fail (MIDORI_IS_TRASH (trash), 0); - - MidoriTrashPrivate* priv = trash->priv; - - return katze_xbel_folder_get_n_items (priv->xbel_folder); -} - -/** - * midori_trash_get_nth_xbel_item: - * @trash: a #MidoriTrash - * @n: the index of an item - * - * Retrieve an item contained in @trash by its index. - * - * Note that you mustn't unref this item. - * - * Return value: the index at the given index or %NULL - **/ -KatzeXbelItem* -midori_trash_get_nth_xbel_item (MidoriTrash* trash, - guint n) -{ - g_return_val_if_fail (MIDORI_IS_TRASH (trash), 0); - - MidoriTrashPrivate* priv = trash->priv; - - return katze_xbel_folder_get_nth_item (priv->xbel_folder, n); -} - -/** - * midori_trash_prepend_xbel_item: - * @trash: a #MidoriTrash - * @xbel_item: a #KatzeXbelItem - * - * Prepends a #KatzeXbelItem to @trash. - * - * The item is copied. If there is a limit set, the oldest item is - * removed automatically. - * - * Return value: %TRUE if there are no items, %FALSE otherwise - **/ -void -midori_trash_prepend_xbel_item (MidoriTrash* trash, - KatzeXbelItem* xbel_item) -{ - g_return_if_fail (MIDORI_IS_TRASH (trash)); - - MidoriTrashPrivate* priv = trash->priv; - - KatzeXbelItem* copy = katze_xbel_item_copy (xbel_item); - katze_xbel_folder_prepend_item (priv->xbel_folder, copy); - g_signal_emit (trash, signals[INSERTED], 0, 0); - guint n = katze_xbel_folder_get_n_items (priv->xbel_folder); - if (n > 10) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, - n - 1); - g_signal_emit (trash, signals[REMOVED], 0, n - 1); - katze_xbel_item_unref (item); - } -} - -/** - * midori_trash_remove_nth_item: - * @trash: a #MidoriTrash - * @n: the index of an item - * - * Removes the item at the specified position from @trash. - * - * Nothing happens if the function fails. - **/ -void -midori_trash_remove_nth_item (MidoriTrash* trash, - guint n) -{ - g_return_if_fail (MIDORI_IS_TRASH (trash)); - - MidoriTrashPrivate* priv = trash->priv; - - KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, n); - if (!n) - return; - katze_xbel_folder_remove_item (priv->xbel_folder, item); - g_signal_emit (trash, signals[REMOVED], 0, n); - katze_xbel_item_unref (item); -} - -/** - * midori_trash_empty: - * @trash: a #MidoriTrash - * - * Deletes all items currently contained in @trash. - **/ -void -midori_trash_empty (MidoriTrash* trash) -{ - g_return_if_fail (MIDORI_IS_TRASH (trash)); - - MidoriTrashPrivate* priv = trash->priv; - - guint n = katze_xbel_folder_get_n_items (priv->xbel_folder); - guint i; - for (i = 0; i < n; i++) - { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item (priv->xbel_folder, - i); - g_signal_emit (trash, signals[REMOVED], 0, i); - katze_xbel_item_unref (item); - } -} diff --git a/src/midori-trash.h b/src/midori-trash.h deleted file mode 100644 index bc711792..00000000 --- a/src/midori-trash.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_TRASH_H__ -#define __MIDORI_TRASH_H__ - -#include - -G_BEGIN_DECLS - -#define MIDORI_TYPE_TRASH \ - (midori_trash_get_type ()) -#define MIDORI_TRASH(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_TRASH, MidoriTrash)) -#define MIDORI_TRASH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_TRASH, MidoriTrashClass)) -#define MIDORI_IS_TRASH(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_TRASH)) -#define MIDORI_IS_TRASH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_TRASH)) -#define MIDORI_TRASH_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_TRASH, MidoriTrashClass)) - -typedef struct _MidoriTrash MidoriTrash; -typedef struct _MidoriTrashPrivate MidoriTrashPrivate; -typedef struct _MidoriTrashClass MidoriTrashClass; - -struct _MidoriTrash -{ - GObject parent_instance; - - MidoriTrashPrivate* priv; -}; - -struct _MidoriTrashClass -{ - GObjectClass parent_class; - - /* Signals */ - void - (*inserted) (MidoriTrash* trash, - guint n); - void - (*removed) (MidoriTrash* trash, - guint n); -}; - -GType -midori_trash_get_type (void); - -MidoriTrash* -midori_trash_new (guint limit); - -gboolean -midori_trash_is_empty (MidoriTrash* trash); - -guint -midori_trash_get_n_items (MidoriTrash* trash); - -KatzeXbelItem* -midori_trash_get_nth_xbel_item (MidoriTrash* trash, - guint n); - -void -midori_trash_prepend_xbel_item (MidoriTrash* trash, - KatzeXbelItem* xbel_item); - -void -midori_trash_remove_nth_item (MidoriTrash* trash, - guint n); - -void -midori_trash_empty (MidoriTrash* trash); - -G_END_DECLS - -#endif /* __MIDORI_TRASH_H__ */ diff --git a/src/midori-websettings.c b/src/midori-websettings.c deleted file mode 100644 index 20bbcc01..00000000 --- a/src/midori-websettings.c +++ /dev/null @@ -1,1021 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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 "midori-websettings.h" - -#include "sokoke.h" - -#include -#include - -G_DEFINE_TYPE (MidoriWebSettings, midori_web_settings, WEBKIT_TYPE_WEB_SETTINGS) - -struct _MidoriWebSettingsPrivate -{ - gboolean remember_last_window_size; - gint last_window_width; - gint last_window_height; - gint last_panel_position; - gint last_panel_page; - gint last_web_search; - gchar* last_pageholder_uri; - - gboolean show_navigationbar; - gboolean show_bookmarkbar; - gboolean show_panel; - gboolean show_statusbar; - - MidoriToolbarStyle toolbar_style; - gboolean small_toolbar; - gboolean show_new_tab; - gboolean show_homepage; - gboolean show_web_search; - gboolean show_trash; - - MidoriStartup load_on_startup; - gchar* homepage; - gchar* download_folder; - gboolean show_download_notification; - gchar* location_entry_search; - MidoriPreferredEncoding preferred_encoding; - - gint tab_label_size; - gboolean close_buttons_on_tabs; - MidoriNewPage open_new_pages_in; - gboolean middle_click_opens_selection; - gboolean open_tabs_in_the_background; - gboolean open_popups_in_tabs; - - MidoriAcceptCookies accept_cookies; - gboolean original_cookies_only; - gint maximum_cookie_age; - - gboolean remember_last_visited_pages; - gint maximum_history_age; - gboolean remember_last_form_inputs; - gboolean remember_last_downloaded_files; - - gchar* http_proxy; - gint cache_size; -}; - -#define MIDORI_WEB_SETTINGS_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsPrivate)) - -enum -{ - PROP_0, - - PROP_REMEMBER_LAST_WINDOW_SIZE, - PROP_LAST_WINDOW_WIDTH, - PROP_LAST_WINDOW_HEIGHT, - PROP_LAST_PANEL_POSITION, - PROP_LAST_PANEL_PAGE, - PROP_LAST_WEB_SEARCH, - PROP_LAST_PAGEHOLDER_URI, - - PROP_SHOW_NAVIGATIONBAR, - PROP_SHOW_BOOKMARKBAR, - PROP_SHOW_PANEL, - PROP_SHOW_STATUSBAR, - - PROP_TOOLBAR_STYLE, - PROP_SMALL_TOOLBAR, - PROP_SHOW_NEW_TAB, - PROP_SHOW_HOMEPAGE, - PROP_SHOW_WEB_SEARCH, - PROP_SHOW_TRASH, - - PROP_LOAD_ON_STARTUP, - PROP_HOMEPAGE, - PROP_DOWNLOAD_FOLDER, - PROP_SHOW_DOWNLOAD_NOTIFICATION, - PROP_LOCATION_ENTRY_SEARCH, - PROP_PREFERRED_ENCODING, - - PROP_TAB_LABEL_SIZE, - PROP_CLOSE_BUTTONS_ON_TABS, - PROP_OPEN_NEW_PAGES_IN, - PROP_MIDDLE_CLICK_OPENS_SELECTION, - PROP_OPEN_TABS_IN_THE_BACKGROUND, - PROP_OPEN_POPUPS_IN_TABS, - - PROP_ACCEPT_COOKIES, - PROP_ORIGINAL_COOKIES_ONLY, - PROP_MAXIMUM_COOKIE_AGE, - - PROP_REMEMBER_LAST_VISITED_PAGES, - PROP_MAXIMUM_HISTORY_AGE, - PROP_REMEMBER_LAST_FORM_INPUTS, - PROP_REMEMBER_LAST_DOWNLOADED_FILES, - - PROP_HTTP_PROXY, - PROP_CACHE_SIZE -}; - -GType -midori_startup_get_type (void) -{ - static GType type = 0; - if (!type) - { - static const GEnumValue values[] = { - { MIDORI_STARTUP_BLANK_PAGE, "MIDORI_STARTUP_BLANK_PAGE", N_("Blank page") }, - { MIDORI_STARTUP_HOMEPAGE, "MIDORI_STARTUP_HOMEPAGE", N_("Homepage") }, - { MIDORI_STARTUP_LAST_OPEN_PAGES, "MIDORI_STARTUP_LAST_OPEN_PAGES", N_("Last open pages") }, - { 0, NULL, NULL } - }; - type = g_enum_register_static ("MidoriStartup", values); - } - return type; -} - -GType -midori_preferred_encoding_get_type (void) -{ - static GType type = 0; - if (!type) - { - static const GEnumValue values[] = { - { MIDORI_ENCODING_CHINESE, "MIDORI_ENCODING_CHINESE", N_("Chinese (BIG5)") }, - { MIDORI_ENCODING_JAPANESE, "MIDORI_ENCODING_JAPANESE", N_("Japanese (SHIFT_JIS)") }, - { MIDORI_ENCODING_RUSSIAN, "MIDORI_ENCODING_RUSSIAN", N_("Russian (KOI8-R)") }, - { MIDORI_ENCODING_UNICODE, "MIDORI_ENCODING_UNICODE", N_("Unicode (UTF-8)") }, - { MIDORI_ENCODING_WESTERN, "MIDORI_ENCODING_WESTERN", N_("Western (ISO-8859-1)") }, - { MIDORI_ENCODING_WESTERN, "MIDORI_ENCODING_CUSTOM", N_("Custom...") }, - { 0, NULL, NULL } - }; - type = g_enum_register_static ("MidoriPreferredEncoding", values); - } - return type; -} - -GType -midori_new_page_get_type (void) -{ - static GType type = 0; - if (!type) - { - static const GEnumValue values[] = { - { MIDORI_NEW_PAGE_TAB, "MIDORI_NEW_PAGE_TAB", N_("New tab") }, - { MIDORI_NEW_PAGE_WINDOW, "MIDORI_NEW_PAGE_WINDOW", N_("New window") }, - { MIDORI_NEW_PAGE_CURRENT, "MIDORI_NEW_PAGE_CURRENT", N_("Current tab") }, - { 0, NULL, NULL } - }; - type = g_enum_register_static ("MidoriNewPage", values); - } - return type; -} - -GType -midori_toolbar_style_get_type (void) -{ - static GType type = 0; - if (!type) - { - static const GEnumValue values[] = { - { MIDORI_TOOLBAR_DEFAULT, "MIDORI_TOOLBAR_DEFAULT", N_("Default") }, - { MIDORI_TOOLBAR_ICONS, "MIDORI_TOOLBAR_ICONS", N_("Icons") }, - { MIDORI_TOOLBAR_TEXT, "MIDORI_TOOLBAR_TEXT", N_("Text") }, - { MIDORI_TOOLBAR_BOTH, "MIDORI_TOOLBAR_BOTH", N_("Both") }, - { MIDORI_TOOLBAR_BOTH_HORIZ, "MIDORI_TOOLBAR_BOTH_HORIZ", N_("Both horizontal") }, - { 0, NULL, NULL } - }; - type = g_enum_register_static ("MidoriToolbarStyle", values); - } - return type; -} - -GType -midori_accept_cookies_get_type (void) -{ - static GType type = 0; - if (!type) - { - static const GEnumValue values[] = { - { MIDORI_ACCEPT_COOKIES_ALL, "MIDORI_ACCEPT_COOKIES_ALL", N_("All cookies") }, - { MIDORI_ACCEPT_COOKIES_SESSION, "MIDORI_ACCEPT_COOKIES_SESSION", N_("Session cookies") }, - { MIDORI_ACCEPT_COOKIES_NONE, "MIDORI_ACCEPT_COOKIES_NONE", N_("None") }, - { 0, NULL, NULL } - }; - type = g_enum_register_static ("MidoriAcceptCookies", values); - } - return type; -} - -static void -midori_web_settings_finalize (GObject* object); - -static void -midori_web_settings_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec); - -static void -midori_web_settings_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec); - -static void -midori_web_settings_notify (GObject* object, - GParamSpec* pspec); - -static void -midori_web_settings_class_init (MidoriWebSettingsClass* class) -{ - GObjectClass* gobject_class = G_OBJECT_CLASS (class); - gobject_class->finalize = midori_web_settings_finalize; - gobject_class->set_property = midori_web_settings_set_property; - gobject_class->get_property = midori_web_settings_get_property; - gobject_class->notify = midori_web_settings_notify; - - GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; - - g_object_class_install_property (gobject_class, - PROP_REMEMBER_LAST_WINDOW_SIZE, - g_param_spec_boolean ( - "remember-last-window-size", - _("Remember last window size"), - _("Whether to save the last window size"), - TRUE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_LAST_WINDOW_WIDTH, - g_param_spec_int ( - "last-window-width", - _("Last window width"), - _("The last saved window width"), - 0, G_MAXINT, 0, - flags)); - - g_object_class_install_property (gobject_class, - PROP_LAST_WINDOW_HEIGHT, - g_param_spec_int ( - "last-window-height", - _("Last window height"), - _("The last saved window height"), - 0, G_MAXINT, 0, - flags)); - - g_object_class_install_property (gobject_class, - PROP_LAST_PANEL_POSITION, - g_param_spec_int ( - "last-panel-position", - _("Last panel position"), - _("The last saved panel position"), - 0, G_MAXINT, 0, - flags)); - - g_object_class_install_property (gobject_class, - PROP_LAST_PANEL_PAGE, - g_param_spec_int ( - "last-panel-page", - _("Last panel page"), - _("The last saved panel page"), - 0, G_MAXINT, 0, - flags)); - - g_object_class_install_property (gobject_class, - PROP_LAST_WEB_SEARCH, - g_param_spec_int ( - "last-web-search", - _("Last Web search"), - _("The last saved Web search"), - 0, G_MAXINT, 0, - flags)); - - g_object_class_install_property (gobject_class, - PROP_LAST_PAGEHOLDER_URI, - g_param_spec_string ( - "last-pageholder-uri", - _("Last pageholder URI"), - _("The URI last opened in the pageholder"), - "", - flags)); - - - - g_object_class_install_property (gobject_class, - PROP_SHOW_NAVIGATIONBAR, - g_param_spec_boolean ( - "show-navigationbar", - _("Show Navigationbar"), - _("Whether to show the navigationbar"), - TRUE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_BOOKMARKBAR, - g_param_spec_boolean ( - "show-bookmarkbar", - _("Show Bookmarkbar"), - _("Whether to show the bookmarkbar"), - FALSE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_PANEL, - g_param_spec_boolean ( - "show-panel", - _("Show Panel"), - _("Whether to show the panel"), - FALSE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_STATUSBAR, - g_param_spec_boolean ( - "show-statusbar", - _("Show Statusbar"), - _("Whether to show the statusbar"), - TRUE, - flags)); - - - g_object_class_install_property (gobject_class, - PROP_TOOLBAR_STYLE, - g_param_spec_enum ( - "toolbar-style", - _("Toolbar Style"), - _("The style of the toolbar"), - MIDORI_TYPE_TOOLBAR_STYLE, - MIDORI_TOOLBAR_DEFAULT, - flags)); - - g_object_class_install_property (gobject_class, - PROP_SMALL_TOOLBAR, - g_param_spec_boolean ( - "small-toolbar", - _("Small toolbar"), - _("Use small toolbar icons"), - FALSE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_NEW_TAB, - g_param_spec_boolean ( - "show-new-tab", - _("Show New Tab"), - _("Show the New Tab button in the toolbar"), - TRUE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_HOMEPAGE, - g_param_spec_boolean ( - "show-homepage", - _("Show Homepage"), - _("Show the Homepage button in the toolbar"), - TRUE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_WEB_SEARCH, - g_param_spec_boolean ( - "show-web-search", - _("Show Web search"), - _("Show the Web search entry in the toolbar"), - TRUE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_TRASH, - g_param_spec_boolean ( - "show-trash", - _("Show Trash"), - _("Show the Trash button in the toolbar"), - TRUE, - flags)); - - - - g_object_class_install_property (gobject_class, - PROP_LOAD_ON_STARTUP, - g_param_spec_enum ( - "load-on-startup", - _("Load on Startup"), - _("What to load on startup"), - MIDORI_TYPE_STARTUP, - MIDORI_STARTUP_HOMEPAGE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_HOMEPAGE, - g_param_spec_string ( - "homepage", - _("Homepage"), - _("The homepage"), - "http://www.google.com", - flags)); - - g_object_class_install_property (gobject_class, - PROP_DOWNLOAD_FOLDER, - g_param_spec_string ( - "download-folder", - _("Download Folder"), - _("The folder downloaded files are saved to"), - g_get_home_dir (), - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_DOWNLOAD_NOTIFICATION, - g_param_spec_boolean ( - "show-download-notification", - _("Show Download Notification"), - _("Show a notification window for finished downloads"), - TRUE, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_LOCATION_ENTRY_SEARCH, - g_param_spec_string ( - "location-entry-search", - _("Location entry Search"), - _("The search to perform inside the location entry"), - "http://www.google.com/search?q=%s", - flags)); - - g_object_class_install_property (gobject_class, - PROP_PREFERRED_ENCODING, - g_param_spec_enum ( - "preferred-encoding", - _("Preferred Encoding"), - _("The preferred character encoding"), - MIDORI_TYPE_PREFERRED_ENCODING, - MIDORI_ENCODING_WESTERN, - flags)); - - - - g_object_class_install_property (gobject_class, - PROP_TAB_LABEL_SIZE, - g_param_spec_int ( - "tab-label-size", - _("Tab Label Size"), - _("The desired tab label size"), - 0, G_MAXINT, 10, - flags)); - - g_object_class_install_property (gobject_class, - PROP_CLOSE_BUTTONS_ON_TABS, - g_param_spec_boolean ( - "close-buttons-on-tabs", - _("Close Buttons on Tabs"), - _("Whether tabs have close buttons"), - TRUE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_OPEN_NEW_PAGES_IN, - g_param_spec_enum ( - "open-new-pages-in", - _("Open new pages in"), - _("Where to open new pages"), - MIDORI_TYPE_NEW_PAGE, - MIDORI_NEW_PAGE_TAB, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_MIDDLE_CLICK_OPENS_SELECTION, - g_param_spec_boolean ( - "middle-click-opens-selection", - _("Middle click opens Selection"), - _("Load an URL from the selection via middle click"), - FALSE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_OPEN_TABS_IN_THE_BACKGROUND, - g_param_spec_boolean ( - "open-tabs-in-the-background", - _("Open tabs in the background"), - _("Whether to open new tabs in the background"), - FALSE, - flags)); - - g_object_class_install_property (gobject_class, - PROP_OPEN_POPUPS_IN_TABS, - g_param_spec_boolean ( - "open-popups-in-tabs", - _("Open popups in tabs"), - _("Whether to open popup windows in tabs"), - TRUE, - flags)); - - - - g_object_class_install_property (gobject_class, - PROP_ACCEPT_COOKIES, - g_param_spec_enum ( - "accept-cookies", - _("Accept cookies"), - _("What type of cookies to accept"), - MIDORI_TYPE_ACCEPT_COOKIES, - MIDORI_ACCEPT_COOKIES_ALL, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_ORIGINAL_COOKIES_ONLY, - g_param_spec_boolean ( - "original-cookies-only", - _("Original cookies only"), - _("Accept cookies from the original website only"), - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_MAXIMUM_COOKIE_AGE, - g_param_spec_int ( - "maximum-cookie-age", - _("Maximum cookie age"), - _("The maximum number of days to save cookies for"), - 0, G_MAXINT, 30, - G_PARAM_READABLE)); - - - - g_object_class_install_property (gobject_class, - PROP_REMEMBER_LAST_VISITED_PAGES, - g_param_spec_boolean ( - "remember-last-visited-pages", - _("Remember last visited pages"), - _("Whether the last visited pages are saved"), - TRUE, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_MAXIMUM_HISTORY_AGE, - g_param_spec_int ( - "maximum-history-age", - _("Maximum history age"), - _("The maximum number of days to save the history for"), - 0, G_MAXINT, 30, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_REMEMBER_LAST_FORM_INPUTS, - g_param_spec_boolean ( - "remember-last-form-inputs", - _("Remember last form inputs"), - _("Whether the last form inputs are saved"), - TRUE, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_REMEMBER_LAST_DOWNLOADED_FILES, - g_param_spec_boolean ( - "remember-last-downloaded-files", - _("Remember last downloaded files"), - _("Whether the last downloaded files are saved"), - TRUE, - G_PARAM_READABLE)); - - - - g_object_class_install_property (gobject_class, - PROP_HTTP_PROXY, - g_param_spec_string ( - "http-proxy", - _("HTTP Proxy"), - _("The proxy used for HTTP connections"), - g_getenv ("http_proxy"), - flags)); - - g_object_class_install_property (gobject_class, - PROP_CACHE_SIZE, - g_param_spec_int ( - "cache-size", - _("Cache size"), - _("The allowed size of the cache"), - 0, G_MAXINT, 100, - G_PARAM_READABLE)); - - g_type_class_add_private (class, sizeof (MidoriWebSettingsPrivate)); -} - -static void -notify_default_encoding_cb (GObject* object, GParamSpec* pspec) -{ - MidoriWebSettings* web_settings = MIDORI_WEB_SETTINGS (object); - MidoriWebSettingsPrivate* priv = web_settings->priv; - - const gchar* string; - g_object_get (object, "default-encoding", &string, NULL); - const gchar* encoding = string ? string : ""; - if (!strcmp (encoding, "BIG5")) - priv->preferred_encoding = MIDORI_ENCODING_CHINESE; - else if (!strcmp (encoding, "SHIFT_JIS")) - priv->preferred_encoding = MIDORI_ENCODING_JAPANESE; - else if (!strcmp (encoding, "KOI8-R")) - priv->preferred_encoding = MIDORI_ENCODING_RUSSIAN; - else if (!strcmp (encoding, "UTF-8")) - priv->preferred_encoding = MIDORI_ENCODING_UNICODE; - else if (!strcmp (encoding, "ISO-8859-1")) - priv->preferred_encoding = MIDORI_ENCODING_WESTERN; - else - priv->preferred_encoding = MIDORI_ENCODING_CUSTOM; - g_object_notify (object, "preferred-encoding"); -} - -static void -midori_web_settings_init (MidoriWebSettings* web_settings) -{ - web_settings->priv = MIDORI_WEB_SETTINGS_GET_PRIVATE (web_settings); - - g_signal_connect (web_settings, "notify::default-encoding", - G_CALLBACK (notify_default_encoding_cb), NULL); -} - -static void -midori_web_settings_finalize (GObject* object) -{ - G_OBJECT_CLASS (midori_web_settings_parent_class)->finalize (object); -} - -static void -midori_web_settings_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec) -{ - MidoriWebSettings* web_settings = MIDORI_WEB_SETTINGS (object); - MidoriWebSettingsPrivate* priv = web_settings->priv; - - switch (prop_id) - { - case PROP_REMEMBER_LAST_WINDOW_SIZE: - priv->remember_last_window_size = g_value_get_boolean (value); - break; - case PROP_LAST_WINDOW_WIDTH: - priv->last_window_width = g_value_get_int (value); - break; - case PROP_LAST_WINDOW_HEIGHT: - priv->last_window_height = g_value_get_int (value); - break; - case PROP_LAST_PANEL_POSITION: - priv->last_panel_position = g_value_get_int (value); - break; - case PROP_LAST_PANEL_PAGE: - priv->last_panel_page = g_value_get_int (value); - break; - case PROP_LAST_WEB_SEARCH: - priv->last_web_search = g_value_get_int (value); - break; - case PROP_LAST_PAGEHOLDER_URI: - katze_assign (priv->last_pageholder_uri, g_value_dup_string (value)); - break; - - case PROP_SHOW_NAVIGATIONBAR: - priv->show_navigationbar = g_value_get_boolean (value); - break; - case PROP_SHOW_BOOKMARKBAR: - priv->show_bookmarkbar = g_value_get_boolean (value); - break; - case PROP_SHOW_PANEL: - priv->show_panel = g_value_get_boolean (value); - break; - case PROP_SHOW_STATUSBAR: - priv->show_statusbar = g_value_get_boolean (value); - break; - - case PROP_TOOLBAR_STYLE: - priv->toolbar_style = g_value_get_enum (value); - break; - case PROP_SMALL_TOOLBAR: - priv->small_toolbar = g_value_get_boolean (value); - break; - case PROP_SHOW_NEW_TAB: - priv->show_new_tab = g_value_get_boolean (value); - break; - case PROP_SHOW_HOMEPAGE: - priv->show_homepage = g_value_get_boolean (value); - break; - case PROP_SHOW_WEB_SEARCH: - priv->show_web_search = g_value_get_boolean (value); - break; - case PROP_SHOW_TRASH: - priv->show_trash = g_value_get_boolean (value); - break; - - case PROP_LOAD_ON_STARTUP: - priv->load_on_startup = g_value_get_enum (value); - break; - case PROP_HOMEPAGE: - katze_assign (priv->homepage, g_value_dup_string (value)); - break; - case PROP_DOWNLOAD_FOLDER: - katze_assign (priv->download_folder, g_value_dup_string (value)); - break; - case PROP_SHOW_DOWNLOAD_NOTIFICATION: - priv->show_download_notification = g_value_get_boolean (value); - break; - case PROP_LOCATION_ENTRY_SEARCH: - katze_assign (priv->location_entry_search, g_value_dup_string (value)); - break; - case PROP_PREFERRED_ENCODING: - priv->preferred_encoding = g_value_get_enum (value); - switch (priv->preferred_encoding) - { - case MIDORI_ENCODING_CHINESE: - g_object_set (object, "default-encoding", "BIG5", NULL); - break; - case MIDORI_ENCODING_JAPANESE: - g_object_set (object, "default-encoding", "SHIFT_JIS", NULL); - break; - case MIDORI_ENCODING_RUSSIAN: - g_object_set (object, "default-encoding", "KOI8-R", NULL); - break; - case MIDORI_ENCODING_UNICODE: - g_object_set (object, "default-encoding", "UTF-8", NULL); - break; - case MIDORI_ENCODING_WESTERN: - g_object_set (object, "default-encoding", "ISO-8859-1", NULL); - break; - case MIDORI_ENCODING_CUSTOM: - g_object_set (object, "default-encoding", "", NULL); - } - break; - - case PROP_TAB_LABEL_SIZE: - priv->tab_label_size = g_value_get_int (value); - break; - case PROP_CLOSE_BUTTONS_ON_TABS: - priv->close_buttons_on_tabs = g_value_get_boolean (value); - break; - case PROP_OPEN_NEW_PAGES_IN: - priv->open_new_pages_in = g_value_get_enum (value); - break; - case PROP_MIDDLE_CLICK_OPENS_SELECTION: - priv->middle_click_opens_selection = g_value_get_boolean (value); - break; - case PROP_OPEN_TABS_IN_THE_BACKGROUND: - priv->open_tabs_in_the_background = g_value_get_boolean (value); - break; - case PROP_OPEN_POPUPS_IN_TABS: - priv->open_popups_in_tabs = g_value_get_boolean (value); - break; - - case PROP_ACCEPT_COOKIES: - priv->accept_cookies = g_value_get_enum (value); - break; - case PROP_ORIGINAL_COOKIES_ONLY: - priv->original_cookies_only = g_value_get_boolean (value); - break; - case PROP_MAXIMUM_COOKIE_AGE: - priv->maximum_cookie_age = g_value_get_int (value); - break; - - case PROP_REMEMBER_LAST_VISITED_PAGES: - priv->remember_last_visited_pages = g_value_get_boolean (value); - break; - case PROP_MAXIMUM_HISTORY_AGE: - priv->maximum_history_age = g_value_get_int (value); - break; - case PROP_REMEMBER_LAST_FORM_INPUTS: - priv->remember_last_form_inputs = g_value_get_boolean (value); - break; - case PROP_REMEMBER_LAST_DOWNLOADED_FILES: - priv->remember_last_downloaded_files = g_value_get_boolean (value); - break; - - case PROP_HTTP_PROXY: - katze_assign (priv->http_proxy, g_value_dup_string (value)); - g_setenv ("http_proxy", priv->http_proxy ? priv->http_proxy : "", TRUE); - break; - case PROP_CACHE_SIZE: - priv->cache_size = g_value_get_int (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_web_settings_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec) -{ - MidoriWebSettings* web_settings = MIDORI_WEB_SETTINGS (object); - MidoriWebSettingsPrivate* priv = web_settings->priv; - - switch (prop_id) - { - case PROP_REMEMBER_LAST_WINDOW_SIZE: - g_value_set_boolean (value, priv->remember_last_window_size); - break; - case PROP_LAST_WINDOW_WIDTH: - g_value_set_int (value, priv->last_window_width); - break; - case PROP_LAST_WINDOW_HEIGHT: - g_value_set_int (value, priv->last_window_height); - break; - case PROP_LAST_PANEL_POSITION: - g_value_set_int (value, priv->last_panel_position); - break; - case PROP_LAST_PANEL_PAGE: - g_value_set_int (value, priv->last_panel_page); - break; - case PROP_LAST_WEB_SEARCH: - g_value_set_int (value, priv->last_web_search); - break; - case PROP_LAST_PAGEHOLDER_URI: - g_value_set_string (value, priv->last_pageholder_uri); - break; - - case PROP_SHOW_NAVIGATIONBAR: - g_value_set_boolean (value, priv->show_navigationbar); - break; - case PROP_SHOW_BOOKMARKBAR: - g_value_set_boolean (value, priv->show_bookmarkbar); - break; - case PROP_SHOW_PANEL: - g_value_set_boolean (value, priv->show_panel); - break; - case PROP_SHOW_STATUSBAR: - g_value_set_boolean (value, priv->show_statusbar); - break; - - case PROP_TOOLBAR_STYLE: - g_value_set_enum (value, priv->toolbar_style); - break; - case PROP_SMALL_TOOLBAR: - g_value_set_boolean (value, priv->small_toolbar); - break; - case PROP_SHOW_NEW_TAB: - g_value_set_boolean (value, priv->show_new_tab); - break; - case PROP_SHOW_HOMEPAGE: - g_value_set_boolean (value, priv->show_homepage); - break; - case PROP_SHOW_WEB_SEARCH: - g_value_set_boolean (value, priv->show_web_search); - break; - case PROP_SHOW_TRASH: - g_value_set_boolean (value, priv->show_trash); - break; - - case PROP_LOAD_ON_STARTUP: - g_value_set_enum (value, priv->load_on_startup); - break; - case PROP_HOMEPAGE: - g_value_set_string (value, priv->homepage); - break; - case PROP_DOWNLOAD_FOLDER: - g_value_set_string (value, priv->download_folder); - break; - case PROP_SHOW_DOWNLOAD_NOTIFICATION: - g_value_set_boolean (value, priv->show_download_notification); - break; - case PROP_LOCATION_ENTRY_SEARCH: - g_value_set_string (value, priv->location_entry_search); - break; - case PROP_PREFERRED_ENCODING: - g_value_set_enum (value, priv->preferred_encoding); - break; - - case PROP_TAB_LABEL_SIZE: - g_value_set_int (value, priv->tab_label_size); - break; - case PROP_CLOSE_BUTTONS_ON_TABS: - g_value_set_boolean (value, priv->close_buttons_on_tabs); - break; - case PROP_OPEN_NEW_PAGES_IN: - g_value_set_enum (value, priv->open_new_pages_in); - break; - case PROP_MIDDLE_CLICK_OPENS_SELECTION: - g_value_set_boolean (value, priv->middle_click_opens_selection); - break; - case PROP_OPEN_TABS_IN_THE_BACKGROUND: - g_value_set_boolean (value, priv->open_tabs_in_the_background); - break; - case PROP_OPEN_POPUPS_IN_TABS: - g_value_set_boolean (value, priv->open_popups_in_tabs); - break; - - case PROP_ACCEPT_COOKIES: - g_value_set_enum (value, priv->accept_cookies); - break; - case PROP_ORIGINAL_COOKIES_ONLY: - g_value_set_boolean (value, priv->original_cookies_only); - break; - case PROP_MAXIMUM_COOKIE_AGE: - g_value_set_int (value, priv->maximum_cookie_age); - break; - - case PROP_REMEMBER_LAST_VISITED_PAGES: - g_value_set_boolean (value, priv->remember_last_visited_pages); - break; - case PROP_MAXIMUM_HISTORY_AGE: - g_value_set_int (value, priv->maximum_history_age); - break; - case PROP_REMEMBER_LAST_FORM_INPUTS: - g_value_set_boolean (value, priv->remember_last_form_inputs); - break; - case PROP_REMEMBER_LAST_DOWNLOADED_FILES: - g_value_set_boolean (value, priv->remember_last_downloaded_files); - break; - - case PROP_HTTP_PROXY: - g_value_set_string (value, priv->http_proxy); - break; - case PROP_CACHE_SIZE: - g_value_set_int (value, priv->cache_size); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_web_settings_notify (GObject* object, - GParamSpec* pspec) -{ - -} - -/** - * midori_web_settings_new: - * - * Creates a new #MidoriWebSettings instance with default values. - * - * You will typically want to assign this to a #MidoriWebView or #MidoriBrowser. - * - * Return value: a new #MidoriWebSettings - **/ -MidoriWebSettings* -midori_web_settings_new (void) -{ - MidoriWebSettings* web_settings = g_object_new (MIDORI_TYPE_WEB_SETTINGS, - NULL); - - return web_settings; -} - -/** - * midori_web_settings_copy: - * - * Copies an existing #MidoriWebSettings instance. - * - * Return value: a new #MidoriWebSettings - **/ -MidoriWebSettings* -midori_web_settings_copy (MidoriWebSettings* web_settings) -{ - g_return_val_if_fail (MIDORI_IS_WEB_SETTINGS (web_settings), NULL); - - MidoriWebSettingsPrivate* priv = web_settings->priv; - - MidoriWebSettings* copy; - copy = MIDORI_WEB_SETTINGS (webkit_web_settings_copy ( - WEBKIT_WEB_SETTINGS (web_settings))); - g_object_set (copy, - "load-on-startup", priv->load_on_startup, - "homepage", priv->homepage, - "download-folder", priv->download_folder, - "show-download-notification", priv->show_download_notification, - "location-entry-search", priv->location_entry_search, - "preferred-encoding", priv->preferred_encoding, - - "toolbar-style", priv->toolbar_style, - "small-toolbar", priv->small_toolbar, - "show-web-search", priv->show_web_search, - "show-new-tab", priv->show_new_tab, - "show-trash", priv->show_trash, - - "tab-label-size", priv->tab_label_size, - "close-buttons-on-tabs", priv->close_buttons_on_tabs, - "open-new-pages-in", priv->open_new_pages_in, - "middle-click-opens-selection", priv->middle_click_opens_selection, - "open-tabs-in-the-background", priv->open_tabs_in_the_background, - "open-popups-in-tabs", priv->open_popups_in_tabs, - - "accept-cookies", priv->accept_cookies, - "original-cookies-only", priv->original_cookies_only, - "maximum-cookie-age", priv->maximum_cookie_age, - - "remember-last-visited-pages", priv->remember_last_visited_pages, - "maximum-history-age", priv->maximum_history_age, - "remember-last-form-inputs", priv->remember_last_form_inputs, - "remember-last-downloaded-files", priv->remember_last_downloaded_files, - - "http-proxy", priv->http_proxy, - "cache-size", priv->cache_size, - NULL); - - return copy; -} diff --git a/src/midori-websettings.h b/src/midori-websettings.h deleted file mode 100644 index ceb8c380..00000000 --- a/src/midori-websettings.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_WEB_SETTINGS_H__ -#define __MIDORI_WEB_SETTINGS_H__ - -#include - -#include - -G_BEGIN_DECLS - -#define MIDORI_TYPE_WEB_SETTINGS \ - (midori_web_settings_get_type ()) -#define MIDORI_WEB_SETTINGS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettings)) -#define MIDORI_WEB_SETTINGS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsClass)) -#define MIDORI_IS_WEB_SETTINGS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_SETTINGS)) -#define MIDORI_IS_WEB_SETTINGS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_SETTINGS)) -#define MIDORI_WEB_SETTINGS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsClass)) - -typedef struct _MidoriWebSettings MidoriWebSettings; -typedef struct _MidoriWebSettingsPrivate MidoriWebSettingsPrivate; -typedef struct _MidoriWebSettingsClass MidoriWebSettingsClass; - -struct _MidoriWebSettings -{ - WebKitWebSettings parent_instance; - - MidoriWebSettingsPrivate* priv; -}; - -typedef enum -{ - MIDORI_STARTUP_BLANK_PAGE, - MIDORI_STARTUP_HOMEPAGE, - MIDORI_STARTUP_LAST_OPEN_PAGES -} MidoriStartup; - -GType -midori_startup_get_type (void) G_GNUC_CONST; - -#define MIDORI_TYPE_STARTUP \ - (midori_startup_get_type ()) - -typedef enum -{ - MIDORI_ENCODING_CHINESE, - MIDORI_ENCODING_JAPANESE, - MIDORI_ENCODING_RUSSIAN, - MIDORI_ENCODING_UNICODE, - MIDORI_ENCODING_WESTERN, - MIDORI_ENCODING_CUSTOM -} MidoriPreferredEncoding; - -GType -midori_preferred_encoding_get_type (void) G_GNUC_CONST; - -#define MIDORI_TYPE_PREFERRED_ENCODING \ - (midori_preferred_encoding_get_type ()) - -typedef enum -{ - MIDORI_NEW_PAGE_TAB, - MIDORI_NEW_PAGE_WINDOW, - MIDORI_NEW_PAGE_CURRENT -} MidoriNewPage; - -GType -midori_new_page_get_type (void) G_GNUC_CONST; - -#define MIDORI_TYPE_NEW_PAGE \ - (midori_new_page_get_type ()) - -typedef enum -{ - MIDORI_TOOLBAR_DEFAULT, - MIDORI_TOOLBAR_ICONS, - MIDORI_TOOLBAR_TEXT, - MIDORI_TOOLBAR_BOTH, - MIDORI_TOOLBAR_BOTH_HORIZ -} MidoriToolbarStyle; - -GType -midori_toolbar_style_get_type (void) G_GNUC_CONST; - -#define MIDORI_TYPE_TOOLBAR_STYLE \ - (midori_toolbar_style_get_type ()) - -typedef enum -{ - MIDORI_ACCEPT_COOKIES_ALL, - MIDORI_ACCEPT_COOKIES_SESSION, - MIDORI_ACCEPT_COOKIES_NONE -} MidoriAcceptCookies; - -GType -midori_accept_cookies_get_type (void) G_GNUC_CONST; - -#define MIDORI_TYPE_ACCEPT_COOKIES \ - (midori_accept_cookies_get_type ()) - -struct _MidoriWebSettingsClass -{ - WebKitWebSettingsClass parent_class; - - /* Signals */ - void - (*dummy) (MidoriWebSettings* web_settings); -}; - -GType -midori_web_settings_get_type (void); - -MidoriWebSettings* -midori_web_settings_new (void); - -MidoriWebSettings* -midori_web_settings_copy (MidoriWebSettings* web_settings); - -G_END_DECLS - -#endif /* __MIDORI_WEB_SETTINGS_H__ */ diff --git a/src/midori-webview.c b/src/midori-webview.c deleted file mode 100644 index b5e0f080..00000000 --- a/src/midori-webview.c +++ /dev/null @@ -1,1122 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - 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 "midori-webview.h" - -#include "main.h" -#include "sokoke.h" - -#include -#include - -// This is unstable API, so we need to declare it -gchar* -webkit_web_view_get_selected_text (WebKitWebView* web_view); - -G_DEFINE_TYPE (MidoriWebView, midori_web_view, WEBKIT_TYPE_WEB_VIEW) - -struct _MidoriWebViewPrivate -{ - GtkWidget* tab_icon; - GtkWidget* tab_label; - GtkWidget* tab_close; - GdkPixbuf* icon; - gchar* uri; - gchar* title; - gboolean is_loading; - gint progress; - gchar* statusbar_text; - gchar* link_uri; - - gint tab_label_size; - gboolean close_button; - gboolean middle_click_opens_selection; - MidoriWebSettings* settings; - - GtkWidget* proxy_menu_item; - GtkWidget* proxy_tab_label; - KatzeXbelItem* proxy_xbel_item; -}; - -#define MIDORI_WEB_VIEW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - MIDORI_TYPE_WEB_VIEW, MidoriWebViewPrivate)) - -enum -{ - PROP_0, - - PROP_ICON, - PROP_URI, - PROP_TITLE, - PROP_STATUSBAR_TEXT, - PROP_SETTINGS -}; - -enum { - LOAD_STARTED, - PROGRESS_STARTED, - PROGRESS_CHANGED, - PROGRESS_DONE, - LOAD_DONE, - ELEMENT_MOTION, - CLOSE, - NEW_TAB, - NEW_WINDOW, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static void -midori_web_view_finalize (GObject* object); - -static void -midori_web_view_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec); - -static void -midori_web_view_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec); - -/*static WebKitWebView* -midori_web_view_create_web_view (WebKitWebView* web_view) -{ - MidoriWebView* new_web_view = NULL; - g_signal_emit (web_view, signals[NEW_WINDOW], 0, &new_web_view); - if (new_web_view) - return WEBKIT_WEB_VIEW (new_web_view); - return WEBKIT_WEB_VIEW (midori_web_view_new ()); -}*/ - -static void -midori_web_view_class_init (MidoriWebViewClass* class) -{ - signals[PROGRESS_STARTED] = g_signal_new ( - "progress-started", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, progress_started), - 0, - NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - - signals[PROGRESS_CHANGED] = g_signal_new ( - "progress-changed", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, progress_changed), - 0, - NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - - signals[PROGRESS_DONE] = g_signal_new ( - "progress-done", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, progress_done), - 0, - NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - - signals[LOAD_DONE] = g_signal_new ( - "load-done", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, load_done), - 0, - NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - WEBKIT_TYPE_WEB_FRAME); - - signals[ELEMENT_MOTION] = g_signal_new( - "element-motion", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, element_motion), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - signals[CLOSE] = g_signal_new( - "close", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriWebViewClass, close), - 0, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[NEW_TAB] = g_signal_new( - "new-tab", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriWebViewClass, new_tab), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - signals[NEW_WINDOW] = g_signal_new( - "new-window", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, new_window), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - /*WEBKIT_WEB_VIEW_CLASS (class)->create_web_view = g_signal_new ("create-web-view", - G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET(MidoriWebViewClass, create_web_view), - 0, - NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - MIDORI_TYPE_WEB_VIEW);*/ - - GObjectClass* gobject_class = G_OBJECT_CLASS (class); - gobject_class->finalize = midori_web_view_finalize; - gobject_class->set_property = midori_web_view_set_property; - gobject_class->get_property = midori_web_view_get_property; - - GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; - - g_object_class_install_property (gobject_class, - PROP_ICON, - g_param_spec_object ( - "icon", - "Icon", - _("The icon of the currently loaded page"), - GDK_TYPE_PIXBUF, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_URI, - g_param_spec_string ( - "uri", - "Uri", - _("The URI of the currently loaded page"), - "", - flags)); - - g_object_class_install_property (gobject_class, - PROP_TITLE, - g_param_spec_string ( - "title", - "Title", - _("The title of the currently loaded page"), - NULL, - flags)); - - g_object_class_install_property (gobject_class, - PROP_STATUSBAR_TEXT, - g_param_spec_string ( - "statusbar-text", - "Statusbar Text", - _("The text that is displayed in the statusbar"), - "", - flags)); - - g_object_class_override_property (gobject_class, - PROP_SETTINGS, - "settings"); - - g_type_class_add_private (class, sizeof (MidoriWebViewPrivate)); -} - -/*static void -webkit_web_view_load_started (MidoriWebView* web_view, - WebKitWebFrame* web_frame) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - priv->is_loading = TRUE; - priv->progress = -1; - katze_throbber_set_animated(KATZE_THROBBER(priv->tab_icon), TRUE); -}*/ - -static void -_midori_web_view_set_uri (MidoriWebView* web_view, - const gchar* uri) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - katze_assign (priv->uri, g_strdup (uri)); - if (priv->proxy_xbel_item) - { - const gchar* uri = midori_web_view_get_display_uri (web_view); - katze_xbel_bookmark_set_href (priv->proxy_xbel_item, uri); - } - g_object_set (web_view, "title", NULL, NULL); -} - -static void -webkit_web_view_load_committed (MidoriWebView* web_view, - WebKitWebFrame* web_frame) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - priv->progress = 0; - const gchar* uri = webkit_web_frame_get_uri (web_frame); - _midori_web_view_set_uri (web_view, uri); -} - -static void -webkit_web_view_load_started (MidoriWebView* web_view, - WebKitWebFrame* web_frame) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - // FIXME: This is a hack, until signals are fixed upstream - priv->is_loading = TRUE; - if (priv->tab_icon) - katze_throbber_set_animated (KATZE_THROBBER (priv->tab_icon), TRUE); - - priv->progress = 0; - g_signal_emit (web_view, signals[PROGRESS_STARTED], 0, priv->progress); -} - -static void -webkit_web_view_progress_changed (MidoriWebView* web_view, gint progress) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - priv->progress = progress; - g_signal_emit (web_view, signals[PROGRESS_CHANGED], 0, priv->progress); -} - -static void -webkit_web_view_load_finished (MidoriWebView* web_view) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - priv->progress = 100; - g_signal_emit (web_view, signals[PROGRESS_DONE], 0, priv->progress); -} - -static void -webkit_web_frame_load_done (WebKitWebFrame* web_frame, gboolean success, - MidoriWebView* web_view) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - priv->is_loading = FALSE; - priv->progress = -1; - if (priv->tab_icon) - katze_throbber_set_animated (KATZE_THROBBER (priv->tab_icon), FALSE); - g_signal_emit (web_view, signals[LOAD_DONE], 0, web_frame); -} - -static void -webkit_web_view_title_changed (MidoriWebView* web_view, - WebKitWebFrame* web_frame, const gchar* title) -{ - g_object_set (web_view, "title", title, NULL); -} - -static void -webkit_web_view_statusbar_text_changed (MidoriWebView* web_view, - const gchar* text) -{ - g_object_set (web_view, "statusbar-text", text, NULL); -} - -static void -webkit_web_view_hovering_over_link (MidoriWebView* web_view, - const gchar* tooltip, - const gchar* link_uri) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - katze_assign (priv->link_uri, g_strdup (link_uri)); - g_signal_emit (web_view, signals[ELEMENT_MOTION], 0, link_uri); -} - -static gboolean -gtk_widget_button_press_event (MidoriWebView* web_view, - GdkEventButton* event) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - GdkModifierType state = (GdkModifierType)0; - gint x, y; - gdk_window_get_pointer (NULL, &x, &y, &state); - switch (event->button) - { - case 1: - if (!priv->link_uri) - return FALSE; - if (state & GDK_SHIFT_MASK) - { - // Open link in new window - g_signal_emit (web_view, signals[NEW_WINDOW], 0, priv->link_uri); - return TRUE; - } - else if(state & GDK_MOD1_MASK) - { - // Open link in new tab - g_signal_emit (web_view, signals[NEW_TAB], 0, priv->link_uri); - return TRUE; - } - break; - case 2: - if (state & GDK_CONTROL_MASK) - { - // FIXME: Reset font multiplier or zoom level - return FALSE; // Allow Ctrl + Middle click - } - else - { - if (!priv->link_uri) - return FALSE; - // Open link in new tab - g_signal_emit (web_view, signals[NEW_TAB], 0, priv->link_uri); - return TRUE; - } - break; - case 3: - return FALSE; - } - return FALSE; -} - -static gboolean -gtk_widget_button_press_event_after (MidoriWebView* web_view, - GdkEventButton* event) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - if (event->button == 2 && priv->middle_click_opens_selection) - { - GdkModifierType state = (GdkModifierType) event->state; - GtkClipboard* clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); - gchar* uri = gtk_clipboard_wait_for_text (clipboard); - if (uri && strchr (uri, '.') && !strchr (uri, ' ')) - { - if (state & GDK_CONTROL_MASK) - g_signal_emit (web_view, signals[NEW_TAB], 0, uri); - else - g_object_set (web_view, "uri", uri, NULL); - g_free (uri); - return TRUE; - } - } - return FALSE; -} - -static gboolean -gtk_widget_scroll_event (MidoriWebView* web_view, - GdkEventScroll* event) -{ - GdkModifierType state = (GdkModifierType)0; - gint x, y; - gdk_window_get_pointer (NULL, &x, &y, &state); - if (state & GDK_CONTROL_MASK) - { - // FIXME: Increase or decrease the font multiplier or zoom level - if (event->direction == GDK_SCROLL_DOWN) - ; - else if(event->direction == GDK_SCROLL_UP) - ; - return TRUE; - } - else - return FALSE; -} - -static void -midori_web_view_menu_new_tab_activate_cb (GtkWidget* widget, - MidoriWebView* web_view) -{ - const gchar* uri = g_object_get_data (G_OBJECT (widget), "uri"); - g_signal_emit (web_view, signals[NEW_TAB], 0, uri); -} - -static void -webkit_web_view_populate_popup_cb (GtkWidget* web_view, - GtkWidget* menu) -{ - const gchar* uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); - if (uri) - { - GtkWidget* menuitem = gtk_image_menu_item_new_with_mnemonic ( - _("Open Link in New _Tab")); - GdkScreen* screen = gtk_widget_get_screen (web_view); - GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen); - if (gtk_icon_theme_has_icon (icon_theme, STOCK_TAB_NEW)) - { - GtkWidget* icon = gtk_image_new_from_stock (STOCK_TAB_NEW, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); - } - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 1); - g_object_set_data (G_OBJECT (menuitem), "uri", (gchar*)uri); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), web_view); - gtk_widget_show (menuitem); - } - - if (!uri && webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view))) - { - gchar* text = webkit_web_view_get_selected_text ( - WEBKIT_WEB_VIEW (web_view)); - if (text && strchr (text, '.') && !strchr (text, ' ')) - { - GtkWidget* menuitem = gtk_image_menu_item_new_with_mnemonic ( - _("Open URL in New _Tab")); - GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1); - g_object_set_data (G_OBJECT (menuitem), "uri", text); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), web_view); - gtk_widget_show (menuitem); - } - // FIXME: We are leaking 'text' which is not const but should be. - } -} - -static void -_midori_web_view_update_tab_label_size (MidoriWebView* web_view) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - if (priv->tab_label) - { - if (priv->tab_label_size > -1) - { - gint width, height; - sokoke_widget_get_text_size (priv->tab_label, "M", - &width, &height); - gtk_widget_set_size_request (priv->tab_label, - width * priv->tab_label_size, -1); - gtk_label_set_ellipsize (GTK_LABEL (priv->tab_label), - PANGO_ELLIPSIZE_END); - } - else - { - gtk_widget_set_size_request (priv->tab_label, -1, -1); - gtk_label_set_ellipsize (GTK_LABEL (priv->tab_label), - PANGO_ELLIPSIZE_NONE); - } - } -} - -static void -_midori_web_view_update_settings (MidoriWebView* web_view) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - g_object_get (G_OBJECT (priv->settings), - "tab-label-size", &priv->tab_label_size, - "close-buttons-on-tabs", &priv->close_button, - "middle-click-opens-selection", &priv->middle_click_opens_selection, - NULL); -} - -static void -midori_web_view_settings_notify (MidoriWebSettings* web_settings, - GParamSpec* pspec, - MidoriWebView* web_view) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - const gchar* name = g_intern_string (pspec->name); - GValue value = {0, }; - g_value_init (&value, pspec->value_type); - g_object_get_property (G_OBJECT (priv->settings), name, &value); - - if (name == g_intern_string ("tab-label-size")) - { - priv->tab_label_size = g_value_get_int (&value); - _midori_web_view_update_tab_label_size (web_view); - } - else if (name == g_intern_string ("close-buttons-on-tabs")) - { - priv->close_button = g_value_get_boolean (&value); - if (priv->tab_close) - sokoke_widget_set_visible (priv->tab_close, priv->close_button); - } - else if (name == g_intern_string ("middle-click-opens-selection")) - priv->middle_click_opens_selection = g_value_get_boolean (&value); - else if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_settings), - name)) - g_warning (_("Unexpected setting '%s'"), name); - g_value_unset (&value); -} - -static void -midori_web_view_init (MidoriWebView* web_view) -{ - web_view->priv = MIDORI_WEB_VIEW_GET_PRIVATE (web_view); - - MidoriWebViewPrivate* priv = web_view->priv; - priv->is_loading = FALSE; - priv->progress = -1; - - priv->settings = midori_web_settings_new (); - _midori_web_view_update_settings (web_view); - g_object_set (web_view, "WebKitWebView::settings", priv->settings, NULL); - g_signal_connect (priv->settings, "notify", - G_CALLBACK (midori_web_view_settings_notify), web_view); - - WebKitWebFrame* web_frame; - web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view)); - - g_object_connect (web_view, - //"signal::load-started", - //webkit_web_view_load_started, NULL, - "signal::load-committed", - webkit_web_view_load_committed, NULL, - "signal::load-started", - webkit_web_view_load_started, NULL, - "signal::load-progress-changed", - webkit_web_view_progress_changed, NULL, - "signal::load-finished", - webkit_web_view_load_finished, NULL, - //"signal::load-done", - //webkit_web_view_load_done, NULL, - "signal::title-changed", - webkit_web_view_title_changed, NULL, - "signal::status-bar-text-changed", - webkit_web_view_statusbar_text_changed, NULL, - "signal::hovering-over-link", - webkit_web_view_hovering_over_link, NULL, - "signal::button-press-event", - gtk_widget_button_press_event, NULL, - "signal_after::button-press-event", - gtk_widget_button_press_event_after, NULL, - "signal::scroll-event", - gtk_widget_scroll_event, NULL, - "signal::populate-popup", - webkit_web_view_populate_popup_cb, NULL, - NULL); - g_object_connect (web_frame, - "signal::load-done", - webkit_web_frame_load_done, web_view, - NULL); -} - -static void -midori_web_view_finalize (GObject* object) -{ - MidoriWebView* web_view = MIDORI_WEB_VIEW (object); - MidoriWebViewPrivate* priv = web_view->priv; - - if (priv->icon) - g_object_unref (priv->icon); - g_free (priv->uri); - g_free (priv->title); - g_free (priv->statusbar_text); - g_free (priv->link_uri); - - if (priv->proxy_menu_item) - gtk_widget_destroy (priv->proxy_menu_item); - if (priv->proxy_xbel_item) - katze_xbel_item_unref (priv->proxy_xbel_item); - - if (priv->settings) - g_object_unref (priv->settings); - - G_OBJECT_CLASS (midori_web_view_parent_class)->finalize (object); -} - -static void -midori_web_view_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec) -{ - MidoriWebView* web_view = MIDORI_WEB_VIEW (object); - MidoriWebViewPrivate* priv = web_view->priv; - - switch (prop_id) - { - case PROP_ICON: - katze_object_assign (priv->icon, g_value_get_object (value)); - g_object_ref (priv->icon); - if (priv->tab_icon) - katze_throbber_set_static_pixbuf (KATZE_THROBBER (priv->tab_icon), - priv->icon); - break; - case PROP_URI: - { - const gchar* uri = g_value_get_string (value); - if (uri && *uri) - { - // FIXME: Autocomplete the uri - webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), uri); - } - break; - } - case PROP_TITLE: - katze_assign (priv->title, g_value_dup_string (value)); - const gchar* title = midori_web_view_get_display_title (web_view); - if (priv->tab_label) - { - gtk_label_set_text (GTK_LABEL (priv->tab_label), title); - sokoke_widget_set_tooltip_text (priv->tab_label, title); - } - if (priv->proxy_menu_item) - gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN ( - priv->proxy_menu_item))), title); - if (priv->proxy_xbel_item) - katze_xbel_item_set_title (priv->proxy_xbel_item, title); - break; - case PROP_STATUSBAR_TEXT: - katze_assign (priv->statusbar_text, g_value_dup_string (value)); - break; - case PROP_SETTINGS: - g_signal_handlers_disconnect_by_func (priv->settings, - midori_web_view_settings_notify, - web_view); - katze_object_assign (priv->settings, g_value_get_object (value)); - g_object_ref (priv->settings); - _midori_web_view_update_settings (web_view); - g_object_set (object, "WebKitWebView::settings", priv->settings, NULL); - g_signal_connect (priv->settings, "notify", - G_CALLBACK (midori_web_view_settings_notify), web_view); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_web_view_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec) -{ - MidoriWebView* web_view = MIDORI_WEB_VIEW (object); - MidoriWebViewPrivate* priv = web_view->priv; - - switch (prop_id) - { - case PROP_ICON: - g_value_set_object (value, priv->icon); - break; - case PROP_URI: - g_value_set_string (value, priv->uri); - break; - case PROP_TITLE: - g_value_set_string (value, priv->title); - break; - case PROP_STATUSBAR_TEXT: - g_value_set_string (value, priv->statusbar_text); - break; - case PROP_SETTINGS: - g_value_set_object (value, priv->settings); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * midori_web_view_new: - * - * Creates a new web view widget. - * - * Return value: a new #MidoriWebView - **/ -GtkWidget* -midori_web_view_new (void) -{ - MidoriWebView* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, - NULL); - - return GTK_WIDGET (web_view); -} - -/** - * midori_web_view_set_settings: - * @web_view: a #MidoriWebView - * @web_settings: a #MidoriWebSettings - * - * Assigns a settings instance to the web view. - **/ -void -midori_web_view_set_settings (MidoriWebView* web_view, - MidoriWebSettings* web_settings) -{ - g_object_set (web_view, "settings", web_settings, NULL); -} - -/** - * midori_web_view_get_proxy_menu_item: - * @web_view: a #MidoriWebView - * - * Retrieves a proxy menu item that is typically added to a Window menu - * and which on activation switches to the right window/ tab. - * - * The item is created on the first call and will be updated to reflect - * changes to the icon and title automatically. - * - * Note: The item is only valid as the web view is embedded in a #GtkNotebook. - * - * Return value: the proxy #GtkMenuItem or %NULL - **/ -GtkWidget* -midori_web_view_get_proxy_menu_item (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), FALSE); - - MidoriWebViewPrivate* priv = web_view->priv; - - if (!priv->proxy_menu_item) - { - const gchar* title = midori_web_view_get_display_title (web_view); - GtkWidget* menu_item = gtk_image_menu_item_new_with_label (title); - GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), icon); - - priv->proxy_menu_item = menu_item; - } - return priv->proxy_menu_item; -} - -/** - * midori_web_view_get_proxy_tab_icon: - * @web_view: a #MidoriWebView - * - * Retrieves a proxy tab icon that is typically used in a tab label. - * - * The icon is created on the first call and will be updated to reflect - * loading progress and changes of the actual icon. - * - * Note: If a proxy tab label has been created before, this represents - * the existing icon used in the label. - * - * Return value: the proxy #GtkImage - **/ -GtkWidget* -midori_web_view_get_proxy_tab_icon (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - MidoriWebViewPrivate* priv = web_view->priv; - - if (!priv->tab_icon) - { - priv->tab_icon = katze_throbber_new (); - if (priv->icon) - katze_throbber_set_static_pixbuf (KATZE_THROBBER(priv->tab_icon), - priv->icon); - else - katze_throbber_set_static_stock_id (KATZE_THROBBER(priv->tab_icon), - GTK_STOCK_FILE); - } - return priv->tab_icon; -} - -static gboolean -midori_web_view_tab_label_button_release_event (GtkWidget* tab_label, - GdkEventButton* event, - MidoriWebView* web_view) -{ - MidoriWebViewPrivate* priv = web_view->priv; - - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) - { - // Toggle the label visibility on double click - GtkWidget* child = gtk_bin_get_child (GTK_BIN (tab_label)); - GList* children = gtk_container_get_children (GTK_CONTAINER (child)); - child = (GtkWidget*)g_list_nth_data (children, 1); - gboolean visible = gtk_widget_get_child_visible (GTK_WIDGET (child)); - gtk_widget_set_child_visible (GTK_WIDGET (child), !visible); - gint width, height; - sokoke_widget_get_text_size(tab_label, "M", &width, &height); - gtk_widget_set_size_request (child, !visible - ? width * priv->tab_label_size : 0, !visible ? -1 : 0); - g_list_free (children); - return TRUE; - } - else if (event->button == 2) - { - // Close the web view on middle click - g_signal_emit (web_view, signals[CLOSE], 0); - return TRUE; - } - - return FALSE; -} - -static void -midori_web_view_tab_close_style_set (GtkWidget* tab_close, - GtkStyle* previous_style, - MidoriWebView* web_view) -{ - GtkSettings* gtk_settings = gtk_widget_get_settings (tab_close); - gint width, height; - gtk_icon_size_lookup_for_settings (gtk_settings, GTK_ICON_SIZE_BUTTON, - &width, &height); - gtk_widget_set_size_request (tab_close, width + 2, height + 2); -} - -static void -midori_web_view_tab_close_clicked (GtkWidget* tab_close, - MidoriWebView* web_view) -{ - g_signal_emit (web_view, signals[CLOSE], 0); -} - -/** - * midori_web_view_get_proxy_tab_label: - * @web_view: a #MidoriWebView - * - * Retrieves a proxy tab label that is typically used as the label of - * a #GtkNotebook page. - * - * The label is created on the first call and will be updated to reflect - * changes to the icon and title automatically. - * - * The icon embedded in the label will reflect the loading status of the - * web view. - * - * Note: This fails if a proxy tab icon has been created already. - * - * Return value: the proxy #GtkEventBox - **/ -GtkWidget* -midori_web_view_get_proxy_tab_label (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - MidoriWebViewPrivate* priv = web_view->priv; - - GtkWidget* proxy_tab_icon = priv->tab_icon; - g_return_val_if_fail (!proxy_tab_icon, NULL); - - if (!priv->proxy_tab_label) - { - priv->tab_icon = midori_web_view_get_proxy_tab_icon (web_view); - - GtkWidget* event_box = gtk_event_box_new (); - gtk_event_box_set_visible_window(GTK_EVENT_BOX (event_box), FALSE); - GtkWidget* hbox = gtk_hbox_new (FALSE, 1); - gtk_container_add (GTK_CONTAINER (event_box), GTK_WIDGET (hbox)); - gtk_box_pack_start (GTK_BOX (hbox), priv->tab_icon, FALSE, FALSE, 0); - const gchar* title = midori_web_view_get_display_title (web_view); - priv->tab_label = gtk_label_new (title); - gtk_misc_set_alignment (GTK_MISC (priv->tab_label), 0.0, 0.5); - // TODO: make the tab initially look "unvisited" until it's focused - gtk_box_pack_start (GTK_BOX (hbox), priv->tab_label, FALSE, TRUE, 0); - priv->proxy_tab_label = event_box; - _midori_web_view_update_tab_label_size (web_view); - - GtkWidget* close_button = gtk_button_new (); - gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE); - gtk_button_set_focus_on_click (GTK_BUTTON (close_button), FALSE); - GtkRcStyle* rcstyle = gtk_rc_style_new (); - rcstyle->xthickness = rcstyle->ythickness = 0; - gtk_widget_modify_style(close_button, rcstyle); - GtkWidget* image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, - GTK_ICON_SIZE_MENU); - gtk_button_set_image (GTK_BUTTON(close_button), image); - gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0); - gtk_widget_show_all (GTK_WIDGET (event_box)); - if (!priv->close_button) - gtk_widget_hide (close_button); - priv->tab_close = close_button; - - g_signal_connect(priv->proxy_tab_label, "button-release-event", - G_CALLBACK(midori_web_view_tab_label_button_release_event), - web_view); - g_signal_connect(priv->tab_close, "style-set", - G_CALLBACK(midori_web_view_tab_close_style_set), - web_view); - g_signal_connect(priv->tab_close, "clicked", - G_CALLBACK(midori_web_view_tab_close_clicked), - web_view); - } - return priv->proxy_tab_label; -} - -/** - * midori_web_view_get_proxy_xbel_item: - * @web_view: a #MidoriWebView - * - * Retrieves a proxy xbel item that can be used for bookmark storage as - * well as session management. - * - * The item is created on the first call and will be updated to reflect - * changes to the title and href automatically. - * - * Note: Currently the item is always a bookmark, but this might change - * in the future. - * - * Return value: the proxy #KatzeXbelItem - **/ -KatzeXbelItem* -midori_web_view_get_proxy_xbel_item (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - MidoriWebViewPrivate* priv = web_view->priv; - - if (!priv->proxy_xbel_item) - { - priv->proxy_xbel_item = katze_xbel_bookmark_new (); - const gchar* uri = midori_web_view_get_display_uri (web_view); - katze_xbel_bookmark_set_href (priv->proxy_xbel_item, uri); - const gchar* title = midori_web_view_get_display_title (web_view); - katze_xbel_item_set_title (priv->proxy_xbel_item, title); - } - return priv->proxy_xbel_item; -} - -/** - * midori_web_view_is_loading: - * @web_view: a #MidoriWebView - * - * Determines whether currently a page is being loaded or not. - * - * Return value: %TRUE if a page is being loaded, %FALSE otherwise - **/ -gint -midori_web_view_is_loading (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), -1); - - MidoriWebViewPrivate* priv = web_view->priv; - return priv->is_loading; -} - -/** - * midori_web_view_get_progress: - * @web_view: a #MidoriWebView - * - * Retrieves the current loading progress in percent or -1 if no data - * has been loaded so far. - * - * The value is undefined if no loading is in progress. - * - * Return value: the current loading progress or -1 - **/ -gint -midori_web_view_get_progress (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), -1); - - MidoriWebViewPrivate* priv = web_view->priv; - return priv->progress; -} - -/** - * midori_web_view_get_display_uri: - * @web_view: a #MidoriWebView - * - * Retrieves a string that is suitable for displaying, particularly an - * empty URI is represented as "". - * - * You can assume that the string is not %NULL. - * - * Return value: an URI string - **/ -const gchar* -midori_web_view_get_display_uri (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), ""); - - MidoriWebViewPrivate* priv = web_view->priv; - return priv->uri ? priv->uri : ""; -} - -/** - * midori_web_view_get_display_title: - * @web_view: a #MidoriWebView - * - * Retrieves a string that is suitable for displaying as a title. Most of the - * time this will be the title or the current URI. - * - * You can assume that the string is not %NULL. - * - * Return value: a title string - **/ -const gchar* -midori_web_view_get_display_title (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), "about:blank"); - - MidoriWebViewPrivate* priv = web_view->priv; - - if (priv->title) - return priv->title; - if (priv->uri) - return priv->uri; - return "about:blank"; -} - -/** - * midori_web_view_get_link_uri: - * @web_view: a #MidoriWebView - * - * Retrieves the uri of the currently focused link, particularly while the - * mouse hovers a link or a context menu is being opened. - * - * Return value: an URI string, or %NULL if there is no link focussed - **/ -const gchar* -midori_web_view_get_link_uri (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - MidoriWebViewPrivate* priv = web_view->priv; - return priv->link_uri; -} - -/** - * midori_web_view_get_zoom_level: - * @web_view: a #MidoriWebView - * - * Retrieves the current zoom level. - * - * Return value: the zoom level, always 1 if not supported - **/ -gfloat -midori_web_view_get_zoom_level (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), 1); - - if (g_object_class_find_property (G_OBJECT_GET_CLASS (web_view), - "zoom-level")) - { - gfloat zoom_level; - g_object_get (web_view, "zoom-level", &zoom_level, NULL); - return zoom_level; - } - return 1; -} diff --git a/src/midori-webview.h b/src/midori-webview.h deleted file mode 100644 index 71cab23f..00000000 --- a/src/midori-webview.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - 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. -*/ - -#ifndef __MIDORI_WEB_VIEW_H__ -#define __MIDORI_WEB_VIEW_H__ - -#include - -#include -#include "midori-websettings.h" - -G_BEGIN_DECLS - -#define MIDORI_TYPE_WEB_VIEW \ - (midori_web_view_get_type ()) -#define MIDORI_WEB_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_VIEW, MidoriWebView)) -#define MIDORI_WEB_VIEW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_VIEW, MidoriWebViewClass)) -#define MIDORI_IS_WEB_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_VIEW)) -#define MIDORI_IS_WEB_VIEW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_VIEW)) -#define MIDORI_WEB_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_VIEW, MidoriWebViewClass)) - -typedef struct _MidoriWebView MidoriWebView; -typedef struct _MidoriWebViewPrivate MidoriWebViewPrivate; -typedef struct _MidoriWebViewClass MidoriWebViewClass; - -struct _MidoriWebView -{ - WebKitWebView parent_instance; - - MidoriWebViewPrivate* priv; -}; - -struct _MidoriWebViewClass -{ - WebKitWebViewClass parent_class; - - /* Signals */ - void - (*progress_started) (MidoriWebView* web_view, - guint progress); - void - (*progress_changed) (MidoriWebView* web_view, - guint progress); - void - (*progress_done) (MidoriWebView* web_view, - guint progress); - void - (*load_done) (MidoriWebView* web_view, - WebKitWebFrame* frame); - void - (*statusbar_text_changed) (MidoriWebView* web_view, - const gchar* text); - void - (*element_motion) (MidoriWebView* web_view, - const gchar* link_uri); - void - (*close) (MidoriWebView* web_view); - void - (*new_tab) (MidoriWebView* web_view, - const gchar* uri); - void - (*new_window) (MidoriWebView* web_view, - const gchar* uri); - void - (*create_web_view) (MidoriWebView* web_view, - MidoriWebView* new_web_view); -}; - -GType -midori_web_view_get_type (void); - -GtkWidget* -midori_web_view_new (void); - -void -midori_web_view_set_settings (MidoriWebView* web_view, - MidoriWebSettings* web_settings); - -GtkWidget* -midori_web_view_get_proxy_menu_item (MidoriWebView* web_view); - -GtkWidget* -midori_web_view_get_proxy_tab_label (MidoriWebView* web_view); - -KatzeXbelItem* -midori_web_view_get_proxy_xbel_item (MidoriWebView* web_view); - -gboolean -midori_web_view_is_loading (MidoriWebView* web_view); - -gint -midori_web_view_get_progress (MidoriWebView* web_view); - -const gchar* -midori_web_view_get_display_uri (MidoriWebView* web_view); - -const gchar* -midori_web_view_get_display_title (MidoriWebView* web_view); - -const gchar* -midori_web_view_get_link_uri (MidoriWebView* web_view); - -gfloat -midori_web_view_get_zoom_level (MidoriWebView* web_view); - -G_END_DECLS - -#endif /* __MIDORI_WEB_VIEW_H__ */ diff --git a/src/search.c b/src/search.c deleted file mode 100644 index 26afcb5e..00000000 --- a/src/search.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - Copyright (C) 2007 Christian Dywan - - 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 "search.h" - -#include "sokoke.h" -#include - -#include -#include - -GList* search_engines_new(void) -{ - return NULL; -} - -void search_engines_free(GList* searchEngines) -{ - g_list_foreach(searchEngines, (GFunc)search_engine_free, NULL); - g_list_free(searchEngines); -} - -gboolean search_engines_from_file(GList** searchEngines, const gchar* filename - , GError** error) -{ - g_return_val_if_fail(!g_list_nth(*searchEngines, 0), FALSE); - GKeyFile* keyFile = g_key_file_new(); - g_key_file_load_from_file(keyFile, filename, G_KEY_FILE_KEEP_COMMENTS, error); - /*g_key_file_load_from_data_dirs(keyFile, sFilename, NULL - , G_KEY_FILE_KEEP_COMMENTS, error);*/ - gchar** engines = g_key_file_get_groups(keyFile, NULL); - guint i; - for(i = 0; engines[i] != NULL; i++) - { - SearchEngine* engine = search_engine_new(); - search_engine_set_short_name(engine, engines[i]); - engine->description = g_key_file_get_string(keyFile, engines[i], "description", NULL); - engine->url = g_key_file_get_string(keyFile, engines[i], "url", NULL); - engine->inputEncoding = g_key_file_get_string(keyFile, engines[i], "input-encoding", NULL); - engine->icon = g_key_file_get_string(keyFile, engines[i], "icon", NULL); - engine->keyword = g_key_file_get_string(keyFile, engines[i], "keyword", NULL); - *searchEngines = g_list_prepend(*searchEngines, engine); - } - *searchEngines = g_list_reverse(*searchEngines); - g_strfreev(engines); - g_key_file_free(keyFile); - return !(error && *error); -} - -static void key_file_set_string(GKeyFile* keyFile, const gchar* group - , const gchar* key, const gchar* string) -{ - g_return_if_fail(group); - if(string) - g_key_file_set_string(keyFile, group, key, string); -} - -gboolean search_engines_to_file(GList* searchEngines, const gchar* filename - , GError** error) -{ - GKeyFile* keyFile = g_key_file_new(); - guint n = g_list_length(searchEngines); - guint i; - for(i = 0; i < n; i++) - { - SearchEngine* engine = (SearchEngine*)g_list_nth_data(searchEngines, i); - const gchar* name = search_engine_get_short_name(engine); - key_file_set_string(keyFile, name, "description", engine->description); - key_file_set_string(keyFile, name, "url", engine->url); - key_file_set_string(keyFile, name, "input-encoding", engine->inputEncoding); - key_file_set_string(keyFile, name, "icon", engine->icon); - key_file_set_string(keyFile, name, "keyword", engine->keyword); - } - gboolean bSaved = sokoke_key_file_save_to_file(keyFile, filename, error); - g_key_file_free(keyFile); - - return bSaved; -} - -SearchEngine* search_engine_new() -{ - SearchEngine* engine = g_new0(SearchEngine, 1); - engine->shortName = g_strdup(""); - return engine; -} - -void search_engine_free(SearchEngine* engine) -{ - g_return_if_fail(engine); - g_free(engine->shortName); - g_free(engine->description); - g_free(engine->url); - g_free(engine->inputEncoding); - g_free(engine->icon); - g_free(engine->keyword); - g_free(engine); -} - -SearchEngine* search_engine_copy(SearchEngine* engine) -{ - g_return_val_if_fail(engine, NULL); - SearchEngine* copy = search_engine_new(); - search_engine_set_short_name(copy, engine->shortName); - search_engine_set_description(copy, engine->description); - search_engine_set_url(copy, engine->url); - search_engine_set_input_encoding(copy, engine->inputEncoding); - search_engine_set_icon(copy, engine->icon); - search_engine_set_keyword(copy, engine->keyword); - return engine; -} - -GType search_engine_get_type() -{ - static GType type = 0; - if(!type) - type = g_pointer_type_register_static("search_engine"); - return type; -} - -G_CONST_RETURN gchar* search_engine_get_short_name(SearchEngine* engine) -{ - g_return_val_if_fail(engine, NULL); - return engine->shortName; -} - -G_CONST_RETURN gchar* search_engine_get_description(SearchEngine* engine) -{ - g_return_val_if_fail(engine, NULL); - return engine->description; -} - -G_CONST_RETURN gchar* search_engine_get_url(SearchEngine* engine) -{ - g_return_val_if_fail(engine, NULL); - return engine->url; -} - -G_CONST_RETURN gchar* search_engine_get_input_encoding(SearchEngine* engine) -{ - g_return_val_if_fail(engine, NULL); - return engine->inputEncoding; -} - -G_CONST_RETURN gchar* search_engine_get_icon(SearchEngine* engine) -{ - g_return_val_if_fail(engine, NULL); - return engine->icon; -} - -G_CONST_RETURN gchar* search_engine_get_keyword(SearchEngine* engine) -{ - g_return_val_if_fail(engine, NULL); - return engine->keyword; -} - -void search_engine_set_short_name(SearchEngine* engine, const gchar* shortName) -{ - g_return_if_fail(engine); - g_return_if_fail(shortName); - katze_assign(engine->shortName, g_strdup(shortName)); -} - -void search_engine_set_description(SearchEngine* engine, const gchar* description) -{ - g_return_if_fail(engine); - katze_assign(engine->description, g_strdup(description)); -} - -void search_engine_set_url(SearchEngine* engine, const gchar* url) -{ - g_return_if_fail(engine); - katze_assign(engine->url, g_strdup(url)); -} - -void search_engine_set_input_encoding(SearchEngine* engine, const gchar* inputEncoding) -{ - g_return_if_fail(engine); - katze_assign(engine->inputEncoding, g_strdup(inputEncoding)); -} - -void search_engine_set_icon(SearchEngine* engine, const gchar* icon) -{ - g_return_if_fail(engine); - katze_assign(engine->icon, g_strdup(icon)); -} - -void search_engine_set_keyword(SearchEngine* engine, const gchar* keyword) -{ - g_return_if_fail(engine); - katze_assign(engine->keyword, g_strdup(keyword)); -} diff --git a/src/search.h b/src/search.h deleted file mode 100644 index c8aa7093..00000000 --- a/src/search.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2007 Christian Dywan - - 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. -*/ - -#ifndef __SEARCH_H__ -#define __SEARCH_H__ 1 - -#include -#include - -// Note: This structure is entirely private. -typedef struct -{ - gchar* shortName; - gchar* description; - gchar* url; - gchar* inputEncoding; - gchar* icon; - gchar* keyword; -} SearchEngine; - -GList* -search_engines_new(void); - -void -search_engines_free(GList*); - -gboolean -search_engines_from_file(GList**, const gchar*, GError**); - -gboolean -search_engines_to_file(GList*, const gchar*, GError**); - -SearchEngine* -search_engine_new(void); - -void -search_engine_free(SearchEngine*); - -SearchEngine* -search_engine_copy(SearchEngine*); - -GType -search_engine_get_type(); - -#define G_TYPE_SEARCH_ENGINE search_engine_get_type() - -G_CONST_RETURN gchar* -search_engine_get_short_name(SearchEngine*); - -G_CONST_RETURN gchar* -search_engine_get_description(SearchEngine*); - -G_CONST_RETURN gchar* -search_engine_get_url(SearchEngine*); - -G_CONST_RETURN gchar* -search_engine_get_input_encoding(SearchEngine*); - -G_CONST_RETURN gchar* -search_engine_get_icon(SearchEngine*); - -G_CONST_RETURN gchar* -search_engine_get_keyword(SearchEngine*); - -void -search_engine_set_short_name(SearchEngine*, const gchar*); - -void -search_engine_set_description(SearchEngine*, const gchar*); - -void -search_engine_set_url(SearchEngine*, const gchar*); - -void -search_engine_set_input_encoding(SearchEngine*, const gchar*); - -void -search_engine_set_icon(SearchEngine*, const gchar*); - -void -search_engine_set_keyword(SearchEngine*, const gchar*); - -#endif /* !__SEARCH_H__ */ diff --git a/src/sokoke.c b/src/sokoke.c deleted file mode 100644 index 157252d5..00000000 --- a/src/sokoke.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - 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 "sokoke.h" - -#include "search.h" - -#include "config.h" -#include "main.h" - -#ifdef HAVE_UNISTD_H - #include -#endif -#include -#include -#include -#include - -gchar* -sokoke_magic_uri (const gchar* uri, const gchar* default_search_uri) -{ - // Add file:// if we have a local path - if (g_path_is_absolute (uri)) - return g_strconcat ("file://", uri, NULL); - // Construct an absolute path if the file is relative - if (g_file_test (uri, G_FILE_TEST_EXISTS) && g_file_test (uri, G_FILE_TEST_IS_REGULAR)) - { - gchar* current_dir = g_get_current_dir (); - gchar* result = g_strconcat ("file://", current_dir, G_DIR_SEPARATOR_S, uri, NULL); - g_free (current_dir); - return result; - } - // Do we need to add a protocol? - if (!strstr (uri, "://")) - { - // Do we have a domain, ip address or localhost? - if (strchr (uri, '.') != NULL || !strcmp (uri, "localhost")) - return g_strconcat ("http://", uri, NULL); - // We don't want to search? So return early. - if (!default_search_uri) - return g_strdup (uri); - gchar* search; - const gchar* search_uri = NULL; - // Do we have a keyword and a string? - gchar** parts = g_strsplit (uri, " ", 2); - if (parts[0] && parts[1]) - { - guint n = g_list_length (searchEngines); - guint i; - for (i = 0; i < n; i++) - { - SearchEngine* search_engine = (SearchEngine*)g_list_nth_data ( - searchEngines, i); - if (!strcmp (search_engine_get_keyword (search_engine), - parts[0])) - search_uri = search_engine->url; - } - if (search_uri) - search = g_strdup_printf (search_uri, parts[1]); - } - // We only have a word or there is no matching keyword, so search for it - if (!search_uri) - search = g_strdup_printf (default_search_uri, uri); - return search; - } - return g_strdup (uri); -} - -void -sokoke_entry_setup_completion (GtkEntry* entry) -{ - /* TODO: The current behavior works only with the beginning of strings - But we want to match "localhost" with "loc" and "hos" */ - GtkEntryCompletion* completion = gtk_entry_completion_new (); - gtk_entry_completion_set_model (completion, - GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING))); - gtk_entry_completion_set_text_column (completion, 0); - gtk_entry_completion_set_minimum_key_length (completion, 3); - gtk_entry_set_completion (entry, completion); - gtk_entry_completion_set_popup_completion (completion, FALSE); //... -} - -void -sokoke_entry_append_completion (GtkEntry* entry, const gchar* text) -{ - GtkEntryCompletion* completion = gtk_entry_get_completion (entry); - GtkTreeModel* completion_store = gtk_entry_completion_get_model (completion); - GtkTreeIter iter; - gtk_list_store_insert (GTK_LIST_STORE (completion_store), &iter, 0); - gtk_list_store_set (GTK_LIST_STORE (completion_store), &iter, 0, text, -1); -} - -void -sokoke_combo_box_add_strings (GtkComboBox* combobox, - const gchar* label_first, ...) -{ - // Add a number of strings to a combobox, terminated with NULL - // This works only for text comboboxes - va_list args; - va_start (args, label_first); - - const gchar* label; - for (label = label_first; label; label = va_arg (args, const gchar*)) - gtk_combo_box_append_text (combobox, label); - - va_end (args); -} - -void sokoke_widget_set_visible (GtkWidget* widget, gboolean visible) -{ - // Show or hide the widget - if (visible) - gtk_widget_show (widget); - else - gtk_widget_hide (widget); -} - -void -sokoke_container_show_children (GtkContainer* container) -{ - // Show every child but not the container itself - gtk_container_foreach (container, (GtkCallback)(gtk_widget_show_all), NULL); -} - -void -sokoke_widget_set_tooltip_text (GtkWidget* widget, const gchar* text) -{ - #if GTK_CHECK_VERSION(2, 12, 0) - gtk_widget_set_tooltip_text (widget, text); - #else - static GtkTooltips* tooltips; - if (!tooltips) - tooltips = gtk_tooltips_new (); - gtk_tooltips_set_tip (tooltips, widget, text, NULL); - #endif -} - -void -sokoke_tool_item_set_tooltip_text (GtkToolItem* toolitem, const gchar* text) -{ - if (text && *text) - { - #if GTK_CHECK_VERSION(2, 12, 0) - gtk_tool_item_set_tooltip_text (toolitem, text); - #else - static GtkTooltips* tooltips = NULL; - if (G_UNLIKELY (!tooltips)) - tooltips = gtk_tooltips_new(); - - gtk_tool_item_set_tooltip (toolitem, tooltips, text, NULL); - #endif - } -} - -typedef struct -{ - GtkWidget* widget; - SokokeMenuPos position; -} SokokePopupInfo; - -static void -sokoke_widget_popup_position_menu (GtkMenu* menu, - gint* x, - gint* y, - gboolean* push_in, - gpointer user_data) -{ - gint wx, wy; - gint menu_width; - GtkRequisition menu_req; - GtkRequisition widget_req; - SokokePopupInfo* info = user_data; - GtkWidget* widget = info->widget; - - // Retrieve size and position of both widget and menu - if (GTK_WIDGET_NO_WINDOW (widget)) - { - gdk_window_get_position (widget->window, &wx, &wy); - wx += widget->allocation.x; - wy += widget->allocation.y; - } - else - gdk_window_get_origin (widget->window, &wx, &wy); - gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); - gtk_widget_size_request (widget, &widget_req); - menu_width = menu_req.width; - gint widget_height = widget_req.height; // Better than allocation.height - - // Calculate menu position - if (info->position == SOKOKE_MENU_POSITION_CURSOR) - ; // Do nothing? - else if (info->position == SOKOKE_MENU_POSITION_RIGHT) - { - *x = wx + widget->allocation.width - menu_width; - *y = wy + widget_height; - } else if (info->position == SOKOKE_MENU_POSITION_LEFT) - { - *x = wx; - *y = wy + widget_height; - } - - *push_in = TRUE; -} - - -void -sokoke_widget_popup (GtkWidget* widget, - GtkMenu* menu, - GdkEventButton* event, - SokokeMenuPos pos) -{ - int button, event_time; - if (event) - { - button = event->button; - event_time = event->time; - } - else - { - button = 0; - event_time = gtk_get_current_event_time (); - } - - if (!gtk_menu_get_attach_widget(menu)) - gtk_menu_attach_to_widget (menu, widget, NULL); - - if (widget) - { - SokokePopupInfo info = { widget, pos }; - gtk_menu_popup (menu, NULL, NULL, - sokoke_widget_popup_position_menu, &info, - button, event_time); - } - else - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, event_time); -} - -typedef enum -{ - SOKOKE_DESKTOP_UNTESTED, - SOKOKE_DESKTOP_XFCE, - SOKOKE_DESKTOP_UNKNOWN -} SokokeDesktop; - -static SokokeDesktop -sokoke_get_desktop (void) -{ - static SokokeDesktop desktop = SOKOKE_DESKTOP_UNTESTED; - if (G_UNLIKELY (desktop == SOKOKE_DESKTOP_UNTESTED)) - { - // Are we running in Xfce? - gint result; gchar* out; gchar* err; - gboolean success = g_spawn_command_line_sync ( - "xprop -root _DT_SAVE_MODE | grep -q xfce4", - &out, &err, &result, NULL); - if (success && !result) - desktop = SOKOKE_DESKTOP_XFCE; - else - desktop = SOKOKE_DESKTOP_UNKNOWN; - } - - return desktop; -} - -GtkWidget* -sokoke_xfce_header_new (const gchar* icon, - const gchar* title) -{ - // Create an xfce header with icon and title - // This returns NULL if the desktop is not xfce - if (sokoke_get_desktop () == SOKOKE_DESKTOP_XFCE) - { - GtkWidget* entry = gtk_entry_new (); - gchar* markup; - GtkWidget* xfce_heading = gtk_event_box_new (); - gtk_widget_modify_bg (xfce_heading, GTK_STATE_NORMAL, - &entry->style->base[GTK_STATE_NORMAL]); - GtkWidget* hbox = gtk_hbox_new (FALSE, 12); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); - GtkWidget* image = gtk_image_new_from_icon_name (icon, - GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); - GtkWidget* label = gtk_label_new (NULL); - gtk_widget_modify_fg (label, GTK_STATE_NORMAL - , &entry->style->text[GTK_STATE_NORMAL]); - markup = g_strdup_printf ("%s", - title); - gtk_label_set_markup (GTK_LABEL (label), markup); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_container_add (GTK_CONTAINER (xfce_heading), hbox); - g_free (markup); - return xfce_heading; - } - return NULL; -} - -GtkWidget* -sokoke_superuser_warning_new (void) -{ - // Create a horizontal bar with a security warning - // This returns NULL if the user is no superuser - #ifdef HAVE_UNISTD_H - if (G_UNLIKELY (!geteuid ())) // effective superuser? - { - GtkWidget* hbox = gtk_event_box_new (); - gtk_widget_modify_bg (hbox, GTK_STATE_NORMAL, - &hbox->style->bg[GTK_STATE_SELECTED]); - GtkWidget* label = gtk_label_new ( - _("Warning: You are using a superuser account!")); - gtk_misc_set_padding (GTK_MISC (label), 0, 2); - gtk_widget_modify_fg (GTK_WIDGET (label), GTK_STATE_NORMAL, - >K_WIDGET (label)->style->fg[GTK_STATE_SELECTED]); - gtk_widget_show (label); - gtk_container_add (GTK_CONTAINER(hbox), GTK_WIDGET (label)); - gtk_widget_show (hbox); - return hbox; - } - #endif - return NULL; -} - -GtkWidget* -sokoke_hig_frame_new (const gchar* title) -{ - // Create a frame with no actual frame but a bold label and indentation - GtkWidget* frame = gtk_frame_new (NULL); - gchar* title_bold = g_strdup_printf ("%s", title); - GtkWidget* label = gtk_label_new (NULL); - gtk_label_set_markup (GTK_LABEL (label), title_bold); - g_free (title_bold); - gtk_frame_set_label_widget (GTK_FRAME (frame), label); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE); - return frame; -} - -void -sokoke_widget_set_pango_font_style (GtkWidget* widget, - PangoStyle style) -{ - // Conveniently change the pango font style - // For some reason we need to reset if we actually want the normal style - if (style == PANGO_STYLE_NORMAL) - gtk_widget_modify_font (widget, NULL); - else - { - PangoFontDescription* font_description = pango_font_description_new (); - pango_font_description_set_style (font_description, PANGO_STYLE_ITALIC); - gtk_widget_modify_font (widget, font_description); - pango_font_description_free (font_description); - } -} - -static gboolean -sokoke_on_entry_focus_in_event (GtkEntry* entry, - GdkEventFocus* event, - gpointer userdata) -{ - gint default_text = GPOINTER_TO_INT ( - g_object_get_data (G_OBJECT (entry), "sokoke_has_default")); - if (default_text) - { - gtk_entry_set_text (entry, ""); - g_object_set_data (G_OBJECT(entry), "sokoke_has_default", - GINT_TO_POINTER (0)); - sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), - PANGO_STYLE_NORMAL); - } - return FALSE; -} - -static gboolean -sokoke_on_entry_focus_out_event (GtkEntry* entry, - GdkEventFocus* event, - gpointer userdata) -{ - const gchar* text = gtk_entry_get_text (entry); - if (text && !*text) - { - const gchar* defaultText = (const gchar*)g_object_get_data ( - G_OBJECT (entry), "sokoke_default_text"); - gtk_entry_set_text (entry, defaultText); - g_object_set_data (G_OBJECT(entry), - "sokoke_has_default", GINT_TO_POINTER (1)); - sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), - PANGO_STYLE_ITALIC); - } - return FALSE; -} - -void -sokoke_entry_set_default_text (GtkEntry* entry, - const gchar* default_text) -{ - // Note: The default text initially overwrites any previous text - gchar* old_value = g_object_get_data (G_OBJECT (entry), - "sokoke_default_text"); - if (!old_value) - { - g_object_set_data (G_OBJECT (entry), "sokoke_has_default", - GINT_TO_POINTER (1)); - sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), - PANGO_STYLE_ITALIC); - gtk_entry_set_text (entry, default_text); - } - g_object_set_data (G_OBJECT (entry), "sokoke_default_text", - (gpointer)default_text); - g_signal_connect (entry, "focus-in-event", - G_CALLBACK (sokoke_on_entry_focus_in_event), NULL); - g_signal_connect (entry, "focus-out-event", - G_CALLBACK (sokoke_on_entry_focus_out_event), NULL); -} - -gchar* -sokoke_key_file_get_string_default (GKeyFile* key_file, - const gchar* group, - const gchar* key, - const gchar* default_value, - GError** error) -{ - gchar* value = g_key_file_get_string (key_file, group, key, error); - return value == NULL ? g_strdup (default_value) : value; -} - -gint -sokoke_key_file_get_integer_default (GKeyFile* key_file, - const gchar* group, - const gchar* key, - const gint default_value, - GError** error) -{ - if (!g_key_file_has_key (key_file, group, key, NULL)) - return default_value; - return g_key_file_get_integer (key_file, group, key, error); -} - -gdouble -sokoke_key_file_get_double_default (GKeyFile* key_file, - const gchar* group, - const gchar* key, - const gdouble default_value, - GError** error) -{ - if (!g_key_file_has_key (key_file, group, key, NULL)) - return default_value; - return g_key_file_get_double (key_file, group, key, error); -} - -gboolean -sokoke_key_file_get_boolean_default (GKeyFile* key_file, - const gchar* group, - const gchar* key, - const gboolean default_value, - GError** error) -{ - if (!g_key_file_has_key (key_file, group, key, NULL)) - return default_value; - return g_key_file_get_boolean (key_file, group, key, error); -} - -gboolean -sokoke_key_file_save_to_file (GKeyFile* key_file, - const gchar* filename, - GError** error) -{ - gchar* data = g_key_file_to_data (key_file, NULL, error); - if (!data) - return FALSE; - FILE* fp; - if (!(fp = fopen (filename, "w"))) - { - *error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_ACCES, - _("Writing failed.")); - return FALSE; - } - fputs (data, fp); - fclose (fp); - g_free (data); - return TRUE; -} - -void -sokoke_widget_get_text_size (GtkWidget* widget, - const gchar* text, - gint* width, - gint* height) -{ - PangoLayout* layout = gtk_widget_create_pango_layout (widget, text); - pango_layout_get_pixel_size (layout, width, height); - g_object_unref (layout); -} diff --git a/src/sokoke.h b/src/sokoke.h deleted file mode 100644 index 89e3ba2e..00000000 --- a/src/sokoke.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - 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. -*/ - -#ifndef __SOKOKE_H__ -#define __SOKOKE_H__ 1 - -#include - -// Many themes need this hack for small toolbars to work -#define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON - -gchar* -sokoke_magic_uri (const gchar* uri, - const gchar* search); - -void -sokoke_entry_setup_completion (GtkEntry* entry); - -void -sokoke_entry_append_completion (GtkEntry* entry, - const gchar* text); - -typedef enum { - SOKOKE_MENU_POSITION_CURSOR = 0, - SOKOKE_MENU_POSITION_LEFT, - SOKOKE_MENU_POSITION_RIGHT -} SokokeMenuPos; - -void -sokoke_combo_box_add_strings (GtkComboBox* combobox, - const gchar* label_first, ...); - -void -sokoke_widget_set_visible (GtkWidget* widget, - gboolean visible); - -void -sokoke_container_show_children (GtkContainer* container); - -void -sokoke_widget_set_tooltip_text (GtkWidget* widget, - const gchar* text); - -void -sokoke_tool_item_set_tooltip_text (GtkToolItem* toolitem, - const gchar* text); - -void -sokoke_widget_popup (GtkWidget* widget, - GtkMenu* menu, - GdkEventButton* event, - SokokeMenuPos pos); - -GtkWidget* -sokoke_xfce_header_new (const gchar* icon, - const gchar* title); - -GtkWidget* -sokoke_superuser_warning_new (void); - -GtkWidget* -sokoke_hig_frame_new (const gchar* title); - -void -sokoke_widget_set_pango_font_style (GtkWidget* widget, - PangoStyle style); - -void -sokoke_entry_set_default_text(GtkEntry*, const gchar*); - -gchar* -sokoke_key_file_get_string_default (GKeyFile* key_file, - const gchar* group, - const gchar* key, - const gchar* default_value, - GError** error); - -gint -sokoke_key_file_get_integer_default (GKeyFile* key_file, - const gchar* group, - const gchar* key, - const gint default_value, - GError** error); - -gdouble -sokoke_key_file_get_double_default (GKeyFile* key_file, - const gchar* group, - const gchar* key, - gdouble default_value, - GError** error); - -gboolean -sokoke_key_file_get_boolean_default (GKeyFile* key_file, - const gchar* group, - const gchar* key, - gboolean default_value, - GError** error); - -gboolean -sokoke_key_file_save_to_file (GKeyFile* key_file, - const gchar* filename, - GError** error); - -void -sokoke_widget_get_text_size (GtkWidget* widget, - const gchar* text, - gint* width, - gint* height); - -#endif /* !__SOKOKE_H__ */ diff --git a/src/webSearch.c b/src/webSearch.c deleted file mode 100644 index 000c66ed..00000000 --- a/src/webSearch.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - Copyright (C) 2007 Christian Dywan - - 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 "webSearch.h" - -#include "search.h" - -#include "main.h" -#include "sokoke.h" - -#include -#include -#include - -static GdkPixbuf* -load_web_icon (const gchar* icon, GtkIconSize size, GtkWidget* widget) -{ - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - GdkPixbuf* pixbuf = NULL; - if (icon && *icon) - { - // TODO: We want to allow http as well, maybe also base64? - const gchar* icon_ready = g_str_has_prefix (icon, "file://") - ? &icon[7] : icon; - GtkStockItem stock_id; - if (gtk_stock_lookup (icon, &stock_id)) - pixbuf = gtk_widget_render_icon (widget, icon_ready, size, NULL); - else - { - gint width, height; - gtk_icon_size_lookup (size, &width, &height); - if (gtk_widget_has_screen (widget)) - { - GdkScreen* screen = gtk_widget_get_screen (widget); - pixbuf = gtk_icon_theme_load_icon ( - gtk_icon_theme_get_for_screen (screen), icon, - MAX (width, height), GTK_ICON_LOOKUP_USE_BUILTIN, NULL); - } - } - if (!pixbuf) - pixbuf = gdk_pixbuf_new_from_file_at_size (icon_ready, 16, 16, NULL); - } - if (!pixbuf) - pixbuf = gtk_widget_render_icon (widget, GTK_STOCK_FIND, size, NULL); - return pixbuf; -} - -void update_searchEngine(guint index, GtkWidget* search) -{ - guint n = g_list_length(searchEngines); - // Display a default icon in case we have no engines - if(!n) - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(search), SEXY_ICON_ENTRY_PRIMARY - , GTK_IMAGE(gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU))); - // Change the icon and default text according to the chosen engine - else - { - // Reset in case the index is out of range - if(index >= n) - index = 0; - SearchEngine* engine = (SearchEngine*)g_list_nth_data(searchEngines, index); - GdkPixbuf* pixbuf = load_web_icon(search_engine_get_icon(engine) - , GTK_ICON_SIZE_MENU, search); - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(search) - , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(gtk_image_new_from_pixbuf(pixbuf))); - g_object_unref(pixbuf); - sokoke_entry_set_default_text(GTK_ENTRY(search) - , search_engine_get_short_name(engine)); - // config->searchEngine = index; - } -} - -void on_webSearch_engine_activate(GtkWidget* widget, MidoriBrowser* browser) -{ - guint index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(widget), "engine")); - update_searchEngine(index, widget); -} - -void on_webSearch_icon_released(GtkWidget* widget, SexyIconEntryPosition* pos - , gint button, MidoriBrowser* browser) -{ - GtkWidget* menu = gtk_menu_new(); - guint n = g_list_length(searchEngines); - GtkWidget* menuitem; - if(n) - { - guint i; - for(i = 0; i < n; i++) - { - SearchEngine* engine = (SearchEngine*)g_list_nth_data(searchEngines, i); - menuitem = gtk_image_menu_item_new_with_label( - search_engine_get_short_name(engine)); - GdkPixbuf* pixbuf = load_web_icon(search_engine_get_icon(engine) - , GTK_ICON_SIZE_MENU, menuitem); - GtkWidget* icon = gtk_image_new_from_pixbuf(pixbuf); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), icon); - g_object_unref(pixbuf); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - g_object_set_data(G_OBJECT(menuitem), "engine", GUINT_TO_POINTER(i)); - g_signal_connect(menuitem, "activate" - , G_CALLBACK(on_webSearch_engine_activate), browser); - gtk_widget_show(menuitem); - } - } - else - { - menuitem = gtk_image_menu_item_new_with_label(_("Empty")); - gtk_widget_set_sensitive(menuitem, FALSE); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); - } - - /*menuitem = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); - GtkAction* action = gtk_action_group_get_action( - browser->actiongroup, "ManageSearchEngines"); - menuitem = gtk_action_create_menu_item(action); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem);*/ - sokoke_widget_popup(widget, GTK_MENU(menu), - NULL, SOKOKE_MENU_POSITION_LEFT); -} - -static void on_webSearch_engines_render_icon(GtkTreeViewColumn* column - , GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter - , GtkWidget* treeview) -{ - SearchEngine* searchEngine; - gtk_tree_model_get(model, iter, ENGINES_COL_ENGINE, &searchEngine, -1); - - // TODO: Would it be better to not do this on every redraw? - const gchar* icon = search_engine_get_icon(searchEngine); - if(icon) - { - GdkPixbuf* pixbuf = load_web_icon(icon, GTK_ICON_SIZE_DND, treeview); - g_object_set(renderer, "pixbuf", pixbuf, NULL); - if(pixbuf) - g_object_unref(pixbuf); - } - else - g_object_set(renderer, "pixbuf", NULL, NULL); -} - -static void on_webSearch_engines_render_text(GtkTreeViewColumn* column - , GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter - , GtkWidget* treeview) -{ - SearchEngine* searchEngine; - gtk_tree_model_get(model, iter, ENGINES_COL_ENGINE, &searchEngine, -1); - const gchar* name = search_engine_get_short_name(searchEngine); - const gchar* description = search_engine_get_description(searchEngine); - gchar* markup = g_markup_printf_escaped("%s\n%s", name, description); - g_object_set(renderer, "markup", markup, NULL); - g_free(markup); -} - -static void webSearch_toggle_edit_buttons(gboolean sensitive, CWebSearch* webSearch) -{ - gtk_widget_set_sensitive(webSearch->edit, sensitive); - gtk_widget_set_sensitive(webSearch->remove, sensitive); -} - -static void on_webSearch_shortName_changed(GtkWidget* widget, GtkWidget* dialog) -{ - const gchar* text = gtk_entry_get_text(GTK_ENTRY(widget)); - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog) - , GTK_RESPONSE_ACCEPT, text && *text); -} - -const gchar* STR_NON_NULL(const gchar* string) -{ - return string ? string : ""; -} - -static void webSearch_editEngine_dialog_new(gboolean newEngine, CWebSearch* webSearch) -{ - GtkWidget* dialog = gtk_dialog_new_with_buttons( - newEngine ? _("Add search engine") : _("Edit search engine") - , GTK_WINDOW(webSearch->window) - , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR - , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL - , newEngine ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT - , NULL); - gtk_window_set_icon_name(GTK_WINDOW(dialog) - , newEngine ? GTK_STOCK_ADD : GTK_STOCK_REMOVE); - gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 5); - GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - - SearchEngine* searchEngine; - GtkTreeModel* liststore; - GtkTreeIter iter; - if(newEngine) - { - searchEngine = search_engine_new(); - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog) - , GTK_RESPONSE_ACCEPT, FALSE); - } - else - { - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(webSearch->treeview)); - gtk_tree_selection_get_selected(selection, &liststore, &iter); - gtk_tree_model_get(liststore, &iter, ENGINES_COL_ENGINE, &searchEngine, -1); - } - - GtkWidget* hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - GtkWidget* label = gtk_label_new_with_mnemonic(_("_Name:")); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_shortName = gtk_entry_new(); - g_signal_connect(entry_shortName, "changed" - , G_CALLBACK(on_webSearch_shortName_changed), dialog); - gtk_entry_set_activates_default(GTK_ENTRY(entry_shortName), TRUE); - if(!newEngine) - gtk_entry_set_text(GTK_ENTRY(entry_shortName) - , search_engine_get_short_name(searchEngine)); - gtk_box_pack_start(GTK_BOX(hbox), entry_shortName, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - - hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - label = gtk_label_new_with_mnemonic(_("_Description:")); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_description = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry_description), TRUE); - if(!newEngine) - gtk_entry_set_text(GTK_ENTRY(entry_description) - , STR_NON_NULL(search_engine_get_description(searchEngine))); - gtk_box_pack_start(GTK_BOX(hbox), entry_description, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - - hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - label = gtk_label_new_with_mnemonic(_("_URL:")); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_url = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry_url), TRUE); - if(!newEngine) - gtk_entry_set_text(GTK_ENTRY(entry_url) - , STR_NON_NULL(search_engine_get_url(searchEngine))); - gtk_box_pack_start(GTK_BOX(hbox), entry_url, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - - hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - label = gtk_label_new_with_mnemonic(_("_Icon (name or file):")); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_icon = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry_icon), TRUE); - if(!newEngine) - gtk_entry_set_text(GTK_ENTRY(entry_icon) - , STR_NON_NULL(search_engine_get_icon(searchEngine))); - gtk_box_pack_start(GTK_BOX(hbox), entry_icon, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - - hbox = gtk_hbox_new(FALSE, 8); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - label = gtk_label_new_with_mnemonic(_("_Keyword:")); - gtk_size_group_add_widget(sizegroup, label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - GtkWidget* entry_keyword = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(entry_keyword), TRUE); - if(!newEngine) - gtk_entry_set_text(GTK_ENTRY(entry_keyword) - , STR_NON_NULL(search_engine_get_keyword(searchEngine))); - gtk_box_pack_start(GTK_BOX(hbox), entry_keyword, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - gtk_widget_show_all(hbox); - - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - { - search_engine_set_short_name(searchEngine - , gtk_entry_get_text(GTK_ENTRY(entry_shortName))); - search_engine_set_description(searchEngine - , gtk_entry_get_text(GTK_ENTRY(entry_description))); - search_engine_set_url(searchEngine - , gtk_entry_get_text(GTK_ENTRY(entry_url))); - /*search_engine_set_input_encoding(searchEngine - , gtk_entry_get_text(GTK_ENTRY(entry_inputEncoding)));*/ - search_engine_set_icon(searchEngine - , gtk_entry_get_text(GTK_ENTRY(entry_icon))); - search_engine_set_keyword(searchEngine - , gtk_entry_get_text(GTK_ENTRY(entry_keyword))); - - if(newEngine) - { - searchEngines = g_list_append(searchEngines, searchEngine); - liststore = gtk_tree_view_get_model(GTK_TREE_VIEW(webSearch->treeview)); - gtk_list_store_append(GTK_LIST_STORE(liststore), &iter); - } - gtk_list_store_set(GTK_LIST_STORE(liststore), &iter - , ENGINES_COL_ENGINE, searchEngine, -1); - webSearch_toggle_edit_buttons(TRUE, webSearch); - } - gtk_widget_destroy(dialog); -} - -static void on_webSearch_add(GtkWidget* widget, CWebSearch* webSearch) -{ - webSearch_editEngine_dialog_new(TRUE, webSearch); -} - -static void on_webSearch_edit(GtkWidget* widget, CWebSearch* webSearch) -{ - webSearch_editEngine_dialog_new(FALSE, webSearch); -} - -static void on_webSearch_remove(GtkWidget* widget, CWebSearch* webSearch) -{ - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(webSearch->treeview)); - GtkTreeModel* liststore; - GtkTreeIter iter; - gtk_tree_selection_get_selected(selection, &liststore, &iter); - SearchEngine* searchEngine; - gtk_tree_model_get(liststore, &iter, ENGINES_COL_ENGINE, &searchEngine, -1); - gtk_list_store_remove(GTK_LIST_STORE(liststore), &iter); - search_engine_free(searchEngine); - searchEngines = g_list_remove(searchEngines, searchEngine); - //update_searchEngine(config->searchEngine, webSearch->browser); - webSearch_toggle_edit_buttons(g_list_nth(searchEngines, 0) != NULL, webSearch); - // FIXME: we want to allow undo of some kind -} - -GtkWidget* webSearch_manageSearchEngines_dialog_new(MidoriBrowser* browser) -{ - const gchar* dialogTitle = _("Manage search engines"); - GtkWidget* dialog = gtk_dialog_new_with_buttons(dialogTitle - , GTK_WINDOW(browser) - , GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR - , GTK_STOCK_HELP - , GTK_RESPONSE_HELP - , GTK_STOCK_CLOSE - , GTK_RESPONSE_CLOSE - , NULL); - gtk_window_set_icon_name(GTK_WINDOW(dialog), GTK_STOCK_PROPERTIES); - // TODO: Implement some kind of help function - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog) - , GTK_RESPONSE_HELP, FALSE); //... - gint iWidth, iHeight; - sokoke_widget_get_text_size(dialog, "M", &iWidth, &iHeight); - gtk_window_set_default_size(GTK_WINDOW(dialog), iWidth * 45, -1); - g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog); - // TODO: Do we want tooltips for explainations or can we omit that? - // TODO: We need mnemonics - // TODO: Take multiple windows into account when applying changes - GtkWidget* xfce_heading; - if((xfce_heading = sokoke_xfce_header_new( - gtk_window_get_icon_name(GTK_WINDOW(dialog)), dialogTitle))) - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), xfce_heading, FALSE, FALSE, 0); - GtkWidget* hbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 12); - GtkTreeViewColumn* column; - GtkCellRenderer* renderer_text; GtkCellRenderer* renderer_pixbuf; - GtkListStore* liststore = gtk_list_store_new(ENGINES_COL_N - , G_TYPE_SEARCH_ENGINE); - GtkWidget* treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore)); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); - column = gtk_tree_view_column_new(); - renderer_pixbuf = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start(column, renderer_pixbuf, FALSE); - gtk_tree_view_column_set_cell_data_func(column, renderer_pixbuf - , (GtkTreeCellDataFunc)on_webSearch_engines_render_icon, treeview, NULL); - renderer_text = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(column, renderer_text, TRUE); - gtk_tree_view_column_set_cell_data_func(column, renderer_text - , (GtkTreeCellDataFunc)on_webSearch_engines_render_text, treeview, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled) - , GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(scrolled), treeview); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); - gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 5); - guint n = g_list_length(searchEngines); - guint i; - for(i = 0; i < n; i++) - { - SearchEngine* searchEngine = (SearchEngine*)g_list_nth_data(searchEngines, i); - gtk_list_store_insert_with_values(GTK_LIST_STORE(liststore), NULL, i - , ENGINES_COL_ENGINE, searchEngine, -1); - } - g_object_unref(liststore); - CWebSearch* webSearch = g_new0(CWebSearch, 1); - webSearch->browser = browser; - webSearch->window = dialog; - webSearch->treeview = treeview; - g_signal_connect(dialog, "response", G_CALLBACK(g_free), webSearch); - GtkWidget* vbox = gtk_vbox_new(FALSE, 4); - gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); - GtkWidget* button = gtk_button_new_from_stock(GTK_STOCK_ADD); - g_signal_connect(button, "clicked", G_CALLBACK(on_webSearch_add), webSearch); - gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); - button = gtk_button_new_from_stock(GTK_STOCK_EDIT); - g_signal_connect(button, "clicked", G_CALLBACK(on_webSearch_edit), webSearch); - gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); - webSearch->edit = button; - button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); - g_signal_connect(button, "clicked", G_CALLBACK(on_webSearch_remove), webSearch); - gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); - webSearch->remove = button; - button = gtk_label_new(""); // This is an invisible separator - gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 12); - button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); - gtk_widget_set_sensitive(button, FALSE); //... - gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0); - button = gtk_button_new_from_stock(GTK_STOCK_GO_UP); - gtk_widget_set_sensitive(button, FALSE); //... - gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0); - webSearch_toggle_edit_buttons(n > 0, webSearch); - gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); - return dialog; -} - -gboolean on_webSearch_key_down(GtkWidget* widget, GdkEventKey* event, MidoriBrowser* browser) -{ - GdkModifierType state = (GdkModifierType)0; - gint x, y; gdk_window_get_pointer(NULL, &x, &y, &state); - if(!(state & GDK_CONTROL_MASK)) - return FALSE; - switch(event->keyval) - { - case GDK_Up: - //update_searchEngine(config->searchEngine - 1, browser); - return TRUE; - case GDK_Down: - //update_searchEngine(config->searchEngine + 1, browser); - return TRUE; - } - return FALSE; -} - -gboolean on_webSearch_scroll(GtkWidget* webView, GdkEventScroll* event, MidoriBrowser* browser) -{ - if(event->direction == GDK_SCROLL_DOWN) - ;//update_searchEngine(config->searchEngine + 1, browser); - else if(event->direction == GDK_SCROLL_UP) - ;//update_searchEngine(config->searchEngine - 1, browser); - return TRUE; -} - -void on_webSearch_activate(GtkWidget* widget, MidoriBrowser* browser) -{ - const gchar* keywords = gtk_entry_get_text(GTK_ENTRY(widget)); - gchar* url; - SearchEngine* searchEngine = (SearchEngine*)g_list_nth_data(searchEngines, 0/*config->searchEngine*/); - if(searchEngine) - url = searchEngine->url; - else // The location search is our fallback - url = "";//config->locationSearch; - gchar* search; - if(strstr(url, "%s")) - search = g_strdup_printf(url, keywords); - else - search = g_strconcat(url, " ", keywords, NULL); - sokoke_entry_append_completion(GTK_ENTRY(widget), keywords); - GtkWidget* webView = midori_browser_get_current_web_view(browser); - webkit_web_view_open(WEBKIT_WEB_VIEW(webView), search); - g_free(search); -} diff --git a/src/webSearch.h b/src/webSearch.h deleted file mode 100644 index cefa89be..00000000 --- a/src/webSearch.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2007 Christian Dywan - - 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. -*/ - -#ifndef __WEBSEARCH_H__ -#define __WEBSEARCH_H__ 1 - -#include "midori-browser.h" - -#include -#include -#include - -// -- Types - -typedef struct -{ - MidoriBrowser* browser; - GtkWidget* window; - GtkWidget* treeview; - GtkWidget* edit; - GtkWidget* remove; -} CWebSearch; - -enum -{ - ENGINES_COL_ENGINE, - ENGINES_COL_N -}; - -// -- Declarations - -void -update_searchEngine(guint, GtkWidget*); - -void -on_webSearch_icon_released(GtkWidget*, SexyIconEntryPosition*, gint, MidoriBrowser*); - -void -on_webSearch_engine_activate(GtkWidget*, MidoriBrowser*); - -void -on_webSearch_activate(GtkWidget*, MidoriBrowser*); - -GtkWidget* -webSearch_manageSearchEngines_dialog_new(MidoriBrowser*); - -gboolean -on_webSearch_key_down(GtkWidget*, GdkEventKey*, MidoriBrowser*); - -gboolean -on_webSearch_scroll(GtkWidget*, GdkEventScroll*, MidoriBrowser*); - -#endif /* !__WEBSEARCH_H__ */ diff --git a/src/wscript_build b/src/wscript_build deleted file mode 100644 index df741850..00000000 --- a/src/wscript_build +++ /dev/null @@ -1,9 +0,0 @@ -#! /usr/bin/env python -# WAF build script for midori - -obj = bld.create_obj ('cc', 'program') -obj.target = 'midori' -obj.includes = '.. ../katze' -obj.find_sources_in_dirs ('.') -obj.uselib = 'GTK WEBKIT LIBXML LIBSEXY' -obj.uselib_local = 'katze' diff --git a/wscript b/wscript index 6f4b9562..862d587f 100644 --- a/wscript +++ b/wscript @@ -23,8 +23,7 @@ def configure (conf): conf.check_tool ('compiler_cc') if not Params.g_options.disable_nls: conf.check_tool ('intltool') - # FIXME if we have intltool but not msgfmt the build breaks - if conf.env['INTLTOOL']: + if conf.env['INTLTOOL'] and conf.env['POCOM']: nls = 'yes' conf.define ('ENABLE_NLS', 1) conf.define ('MIDORI_LOCALEDIR', 'LOCALEDIR', 0) @@ -69,7 +68,7 @@ def set_options (opt): help='Disables native language support', dest='disable_nls') def build (bld): - bld.add_subdirs ('katze src data') + bld.add_subdirs ('katze midori data') if bld.env ()['INTLTOOL']: bld.add_subdirs ('po')