From: Christian Dywan Date: Fri, 2 May 2008 20:30:26 +0000 (+0200) Subject: First attempt at an extension interface. X-Git-Url: https://spindle.queued.net/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7039d48e480e84bcb272457101d30beee86b24e5;p=midori First attempt at an extension interface. --- diff --git a/src/midori-addons.c b/src/midori-addons.c index f2f38d22..c5cbe6e1 100644 --- a/src/midori-addons.c +++ b/src/midori-addons.c @@ -54,15 +54,34 @@ 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/scripts"); + "Put scripts in the folder ~/.local/share/midori/%s", + _folder_for_kind (priv->kind)); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } @@ -119,37 +138,6 @@ midori_addons_treeview_row_activated_cb (GtkTreeView* treeview, }*/ } -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 gchar* _js_string_utf8 (JSStringRef js_string) { @@ -173,7 +161,6 @@ _js_class_get_property_names_cb (JSContextRef js_context, gint i; for (i = 0; i < n_properties; i++) { - GType type = G_PARAM_SPEC_TYPE (pspecs[i]); const gchar* property = g_param_spec_get_name (pspecs[i]); JSStringRef js_property = JSStringCreateWithUTF8CString (property); JSPropertyNameAccumulatorAddName (js_properties, js_property); @@ -187,25 +174,83 @@ _js_class_has_property_cb (JSContextRef js_context, JSObjectRef js_object, JSStringRef js_property) { - GObject* object = JSObjectGetPrivate (js_object); bool result = false; + gchar* property = _js_string_utf8 (js_property); + GObject* object = JSObjectGetPrivate (js_object); if (object) { - gchar* property = _js_string_utf8 (js_property); if (g_object_class_find_property (G_OBJECT_GET_CLASS (object), property)) result = true; - g_free (property); } + else if (js_object == JSContextGetGlobalObject (js_context)) + { + gchar* property = _js_string_utf8 (js_property); + GType type = g_type_from_name (property); + result = type ? type : false; + } + g_free (property); return result; } +static JSObjectRef +_js_object_new (JSContextRef js_context, + gpointer object); + +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 JSObjectRef +_js_object_call_as_constructor_cb (JSContextRef js_context, + JSObjectRef js_object, + size_t n_arguments, + const JSValueRef js_arguments[], + JSValueRef* js_exception) +{ + gchar* type_name = JSObjectGetPrivate (js_object); + if (type_name) + { + GType type = g_type_from_name (type_name); + if (type) + { + GObject* object = g_object_new (type, NULL); + JSObjectRef js_object = _js_object_new (js_context, object); + return js_object; + } + } + return JSValueMakeNull (js_context); +} + static JSValueRef _js_class_get_property_cb (JSContextRef js_context, JSObjectRef js_object, JSStringRef js_property, JSValueRef* js_exception) { + if (js_object == JSContextGetGlobalObject (js_context)) + { + gchar* property = _js_string_utf8 (js_property); + GType type = g_type_from_name (property); + if (type) + { + JSClassDefinition js_class_def = kJSClassDefinitionEmpty; + js_class_def.className = g_strdup (property); + js_class_def.callAsConstructor = _js_object_call_as_constructor_cb; + JSClassRef js_class = JSClassCreate (&js_class_def); + return JSObjectMake (js_context, js_class, property); + } + g_free (property); + return JSValueMakeNull (js_context); + } GObject* object = JSObjectGetPrivate (js_object); JSValueRef js_result = NULL; if (object) @@ -221,27 +266,56 @@ _js_class_get_property_cb (JSContextRef js_context, *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); - JSStringRef js_string = JSStringCreateWithUTF8CString (value); - js_result = JSValueMakeString (js_context, js_string); + if (value) + { + JSStringRef js_string = JSStringCreateWithUTF8CString (value); + js_result = JSValueMakeString (js_context, js_string); + } } - else + else if (type == G_TYPE_PARAM_INT + || type == G_TYPE_PARAM_UINT) { - gchar* message = g_strdup_printf (_("%s.%s cannot be accessed"), - KATZE_OBJECT_NAME (object), property); - JSStringRef js_message = JSStringCreateWithUTF8CString (message); - *js_exception = JSValueMakeString (js_context, js_message); - JSStringRelease (js_message); - g_free (message); + 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 = _js_object_new (js_context, 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; + return js_result ? js_result : JSValueMakeNull (js_context); } static bool @@ -266,6 +340,8 @@ _js_class_set_property_cb (JSContextRef js_context, *js_exception = JSValueMakeString (js_context, js_message); JSStringRelease (js_message); g_free (message); + g_free (property); + return false; } if (!(pspec->flags & G_PARAM_WRITABLE)) { @@ -275,13 +351,42 @@ _js_class_set_property_cb (JSContextRef js_context, GType type = G_PARAM_SPEC_TYPE (pspec); if (type == G_TYPE_PARAM_STRING) { - JSStringRef js_string = JSValueToStringCopy (js_context, js_value, - js_exception); - if (js_string) + JSStringRef js_string_value = JSValueToStringCopy (js_context, + js_value, js_exception); + if (js_string_value) + { + gchar* string_value = _js_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 (object_value) + g_object_set (object, property, object_value, NULL); + else { - gchar* string = _js_string_utf8 (js_string); - g_object_set (object, property, string, NULL); - g_free (string); + gchar* message = g_strdup_printf (_("%s cannot be assigned to %s.%s"), + "[object]", KATZE_OBJECT_NAME (object), property); + JSStringRef js_message = JSStringCreateWithUTF8CString (message); + *js_exception = JSValueMakeString (js_context, js_message); + JSStringRelease (js_message); + g_free (message); } } else @@ -298,9 +403,49 @@ _js_class_set_property_cb (JSContextRef js_context, return result; } +static JSValueRef +_js_foo_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); + if (object) + { + if (!n_arguments) + { + gtk_widget_show (GTK_WIDGET (object)); + } + else if (n_arguments == 1) + { + JSObjectRef js_arg1 = JSValueToObject ( + js_context, js_arguments[0], NULL); + GObject* arg1 = JSObjectGetPrivate (js_arg1); + if (arg1) + gtk_container_add (GTK_CONTAINER (object), GTK_WIDGET (arg1)); + } + } + + return JSValueMakeUndefined (js_context); +} + +static void +_js_foo_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_foo_call_as_function_cb); + JSStringRelease (js_func); + _js_object_set_property (js_context, js_object, func, js_function); +} + static JSObjectRef _js_object_new (JSContextRef js_context, - GObject* object) + gpointer object) { JSClassDefinition js_class_def = kJSClassDefinitionEmpty; js_class_def.className = g_strdup (KATZE_OBJECT_NAME (object)); @@ -308,21 +453,17 @@ _js_object_new (JSContextRef js_context, 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; - // js_class_def.staticFunctions = JSStaticFunction*; JSClassRef js_class = JSClassCreate (&js_class_def); - return JSObjectMake (js_context, js_class, object); -} - -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); + JSObjectRef js_object = JSObjectMake (js_context, js_class, object); + if (GTK_IS_WIDGET (object)) + { + _js_foo_add_function (js_context, js_object, "show"); + } + if (GTK_IS_CONTAINER (object)) + { + _js_foo_add_function (js_context, js_object, "add"); + } + return js_object; } static JSValueRef @@ -331,21 +472,45 @@ _js_eval (JSContextRef js_context, gchar** exception) { JSStringRef js_script = JSStringCreateWithUTF8CString (script); - JSValueRef js_exception; + JSValueRef js_exception = NULL; JSValueRef js_value = JSEvaluateScript (js_context, js_script, - JSContextGetGlobalObject (js_context), - NULL, 0, &js_exception); + JSContextGetGlobalObject (js_context), NULL, 0, &js_exception); if (!js_value && exception) { JSStringRef js_message = JSValueToStringCopy (js_context, js_exception, NULL); *exception = _js_string_utf8 (js_message); JSStringRelease (js_message); + js_value = JSValueMakeNull (js_context); } JSStringRelease (js_script); return js_value; } +static bool +_js_check_syntax (JSContextRef js_context, + const gchar* script, + const gchar* source_id, + int line, + gchar** exception) +{ + JSStringRef js_script = JSStringCreateWithUTF8CString (script); + JSStringRef js_source_id = JSStringCreateWithUTF8CString (source_id); + JSValueRef js_exception = NULL; + bool result = JSCheckScriptSyntax (js_context, js_script, js_source_id, + line, &js_exception); + if (!result && exception) + { + JSStringRef js_message = JSValueToStringCopy (js_context, + js_exception, NULL); + *exception = _js_string_utf8 (js_message); + JSStringRelease (js_message); + } + JSStringRelease (js_source_id); + JSStringRelease (js_script); + return result; +} + static gboolean _js_document_load_script_file (JSContextRef js_context, const gchar* filename, @@ -368,19 +533,122 @@ _js_document_load_script_file (JSContextRef js_context, return result; } -static const gchar* _folder_for_kind (MidoriAddonKind kind) +static void +midori_addons_init (MidoriAddons* addons) { - switch (kind) + 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 JSValueRef +_js_info_call_as_function_cb (JSContextRef js_context, + JSObjectRef js_function, + JSObjectRef js_this, + size_t n_arguments, + const JSValueRef js_arguments[], + JSValueRef* js_exception) +{ + if (n_arguments > 0) { + JSStringRef js_string = JSValueToStringCopy ( + js_context, js_arguments[0], NULL); + gchar* string = _js_string_utf8 (js_string); + // FIXME: Do we want to print this somewhere else? + printf ("console.info: %s\n", string); + g_free (string); + JSStringRelease (js_string); + } + + return JSValueMakeUndefined (js_context); +} + +static void +_midori_addons_extensions_main (MidoriAddons* addons, + GtkWidget* web_widget) +{ + MidoriAddonsPrivate* priv = addons->priv; + + JSClassDefinition js_global_def = kJSClassDefinitionEmpty; + js_global_def.getPropertyNames = _js_class_get_property_names_cb; + js_global_def.hasProperty = _js_class_has_property_cb; + js_global_def.getProperty = _js_class_get_property_cb; + JSClassRef js_global_class = JSClassCreate (&js_global_def); + JSGlobalContextRef js_context = JSGlobalContextCreate (js_global_class); + JSClassDefinition js_class_def = kJSClassDefinitionEmpty; + js_class_def.className = g_strdup ("console"); + JSClassRef js_class = JSClassCreate (&js_class_def); + JSObjectRef js_console = JSObjectMake (js_context, js_class, NULL); + JSStringRef js_info = JSStringCreateWithUTF8CString ("info"); + JSObjectRef js_info_function = JSObjectMakeFunctionWithCallback ( + js_context, js_info, _js_info_call_as_function_cb); + JSObjectSetProperty (js_context, js_console, js_info, js_info_function, + kJSPropertyAttributeNone, NULL); + JSStringRelease (js_info); + _js_object_set_property (js_context, + JSContextGetGlobalObject (js_context), + "console", js_console); + + GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (web_widget)); + if (GTK_WIDGET_TOPLEVEL (browser)) { - case MIDORI_ADDON_EXTENSIONS: - return "extensions"; - case MIDORI_ADDON_USER_SCRIPTS: - return "scripts"; - case MIDORI_ADDON_USER_STYLES: - return "styles"; - default: - return NULL; + // FIXME: Midori should be backed up by a real GObject + JSClassDefinition js_class_def = kJSClassDefinitionEmpty; + js_class_def.className = g_strdup ("Midori"); + JSClassRef js_class = JSClassCreate (&js_class_def); + JSObjectRef js_midori = JSObjectMake (js_context, js_class, NULL); + _js_object_set_property (js_context, + JSContextGetGlobalObject (js_context), + "midori", js_midori); + JSObjectRef js_browser = _js_object_new (js_context, browser); + _js_object_set_property (js_context, + js_midori, + "browser", js_browser); } + + // 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 = NULL; + _js_document_load_script_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); + } + JSGlobalContextRelease (js_context); } static void @@ -392,13 +660,6 @@ midori_web_widget_window_object_cleared_cb (GtkWidget* web_widget, { MidoriAddonsPrivate* priv = addons->priv; - GObject* settings; - g_object_get (web_widget, "settings", &settings, NULL); - JSObjectRef js_settings = _js_object_new (js_context, settings); - _js_object_set_property (js_context, - JSContextGetGlobalObject (js_context), - KATZE_OBJECT_NAME (settings), js_settings); - // 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); @@ -453,7 +714,9 @@ midori_addons_new (GtkWidget* web_widget, MidoriAddonsPrivate* priv = addons->priv; priv->kind = kind; - if (kind == MIDORI_ADDON_USER_SCRIPTS) + if (kind == MIDORI_ADDON_EXTENSIONS) + _midori_addons_extensions_main (addons, web_widget); + else if (kind == MIDORI_ADDON_USER_SCRIPTS) g_signal_connect (web_widget, "window-object-cleared", G_CALLBACK (midori_web_widget_window_object_cleared_cb), addons); diff --git a/src/midori-browser.c b/src/midori-browser.c index e1b52f49..a8889a93 100644 --- a/src/midori-browser.c +++ b/src/midori-browser.c @@ -81,6 +81,10 @@ enum { PROP_0, + PROP_MENUBAR, + PROP_NAVIGATIONBAR, + PROP_TAB, + PROP_STATUSBAR, PROP_SETTINGS, PROP_STATUSBAR_TEXT, PROP_TRASH @@ -595,6 +599,62 @@ midori_browser_class_init (MidoriBrowserClass* class) GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + /** + * MidoriBrowser::menubar + * + * The menubar. + */ + g_object_class_install_property (gobject_class, + PROP_MENUBAR, + g_param_spec_object ( + "menubar", + _("Menubar"), + _("The menubar"), + GTK_TYPE_MENU_BAR, + G_PARAM_READABLE)); + + /** + * MidoriBrowser::navigationbar + * + * The navigationbar. + */ + g_object_class_install_property (gobject_class, + PROP_NAVIGATIONBAR, + g_param_spec_object ( + "navigationbar", + _("Navigationbar"), + _("The navigationbar"), + GTK_TYPE_TOOLBAR, + G_PARAM_READABLE)); + + /** + * MidoriBrowser::tab + * + * The current tab. + */ + g_object_class_install_property (gobject_class, + PROP_TAB, + g_param_spec_object ( + "tab", + _("Tab"), + _("The current tab"), + GTK_TYPE_WIDGET, + G_PARAM_READWRITE)); + + /** + * MidoriBrowser::statusbar + * + * The statusbar. + */ + 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 * @@ -607,7 +667,7 @@ midori_browser_class_init (MidoriBrowserClass* class) PROP_SETTINGS, g_param_spec_object ( "settings", - "Settings", + _("Settings"), _("The associated settings"), MIDORI_TYPE_WEB_SETTINGS, G_PARAM_READWRITE)); @@ -627,7 +687,7 @@ midori_browser_class_init (MidoriBrowserClass* class) PROP_STATUSBAR_TEXT, g_param_spec_string ( "statusbar-text", - "Statusbar Text", + _("Statusbar Text"), _("The text that is displayed in the statusbar"), "", flags)); @@ -646,7 +706,7 @@ midori_browser_class_init (MidoriBrowserClass* class) PROP_TRASH, g_param_spec_object ( "trash", - "Trash", + _("Trash"), _("The trash, collecting recently closed tabs and windows"), MIDORI_TYPE_TRASH, G_PARAM_READWRITE)); @@ -697,7 +757,7 @@ static void _action_tab_close_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* widget = midori_browser_get_current_page (browser); + GtkWidget* widget = midori_browser_get_current_tab (browser); GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); gtk_widget_destroy (scrolled); } @@ -2651,14 +2711,7 @@ midori_browser_init (MidoriBrowser* browser) priv->panel_pageholder, NULL, GTK_STOCK_CONVERT, _("Pageholder")); - // Addons - /*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"));*/ + // Userscripts panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_SCRIPTS); gtk_widget_show (panel); toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel)); @@ -2666,6 +2719,7 @@ midori_browser_init (MidoriBrowser* browser) 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)); @@ -2750,6 +2804,15 @@ midori_browser_init (MidoriBrowser* browser) 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); } @@ -2921,6 +2984,9 @@ midori_browser_set_property (GObject* object, 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; @@ -2962,6 +3028,18 @@ midori_browser_get_property (GObject* object, 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; @@ -3217,7 +3295,6 @@ midori_browser_set_current_page (MidoriBrowser* browser, 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); - printf ("_nth_page: %s\n", G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (widget))); if (widget && MIDORI_IS_WEB_VIEW (widget) && !strcmp (midori_web_view_get_display_uri ( MIDORI_WEB_VIEW (widget)), "")) @@ -3234,19 +3311,70 @@ midori_browser_set_current_page (MidoriBrowser* browser, * * If there is no page present at all, %NULL is returned. * - * Return value: the selected page, or %NULL + * Return value: the selected page, or -1 **/ -GtkWidget* +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)); - GtkWidget* widget = _midori_browser_child_for_scrolled (browser, - gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n)); - return widget; + 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; } /** @@ -3267,7 +3395,7 @@ 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_page (browser); + GtkWidget* web_view = midori_browser_get_current_tab (browser); return MIDORI_IS_WEB_VIEW (web_view) ? web_view : NULL; } diff --git a/src/midori-browser.h b/src/midori-browser.h index e7194235..6dda0b43 100644 --- a/src/midori-browser.h +++ b/src/midori-browser.h @@ -95,9 +95,16 @@ void midori_browser_set_current_page (MidoriBrowser* browser, gint n); -GtkWidget* +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); diff --git a/src/midori-websettings.c b/src/midori-websettings.c index 6f6ba7b3..4b1fdf4d 100644 --- a/src/midori-websettings.c +++ b/src/midori-websettings.c @@ -463,7 +463,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class) "close-buttons-on-tabs", _("Close Buttons on Tabs"), _("Whether tabs have close buttons"), - FALSE, + TRUE, flags)); g_object_class_install_property (gobject_class,