diff --git a/midori/Makefile.am b/midori/Makefile.am index 55db4c0c..fe0c9e5a 100644 --- a/midori/Makefile.am +++ b/midori/Makefile.am @@ -29,7 +29,7 @@ midori_SOURCES = \ midori-webview.c midori-webview.h \ midori-websettings.c midori-websettings.h \ midori-preferences.c midori-preferences.h \ - webSearch.c webSearch.h \ + midori-searchentry.c midori-searchentry.h \ gjs.c gjs.h \ sokoke.c sokoke.h \ compat.c compat.h diff --git a/midori/main.c b/midori/main.c index de04460a..ee78f140 100644 --- a/midori/main.c +++ b/midori/main.c @@ -509,10 +509,7 @@ main (int argc, stock_items_init (); - MidoriApp* app = midori_app_new (); - midori_app_set_settings (app, settings); - - MidoriTrash* trash = midori_app_get_trash (app); + MidoriTrash* trash = midori_trash_new (10); guint n = katze_xbel_folder_get_n_items (xbel_trash); guint i; for (i = 0; i < n; i++) @@ -521,9 +518,16 @@ main (int argc, midori_trash_prepend_xbel_item (trash, item); } + MidoriApp* app = g_object_new (MIDORI_TYPE_APP, + "settings", settings, + "trash", trash, + "search-engines", search_engines, + NULL); + MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER, "settings", settings, "trash", trash, + "search-engines", search_engines, NULL); midori_app_add_browser (app, browser); gtk_widget_show (GTK_WIDGET (browser)); diff --git a/midori/midori-app.c b/midori/midori-app.c index df406911..6cab3403 100644 --- a/midori/midori-app.c +++ b/midori/midori-app.c @@ -11,6 +11,8 @@ #include "midori-app.h" +#include "midori-weblist.h" + #include #include @@ -24,6 +26,7 @@ struct _MidoriApp MidoriWebSettings* settings; MidoriTrash* trash; + MidoriWebList* search_engines; }; G_DEFINE_TYPE (MidoriApp, midori_app, G_TYPE_OBJECT) @@ -37,7 +40,8 @@ enum PROP_SETTINGS, PROP_TRASH, PROP_BROWSER, - PROP_BROWSER_COUNT + PROP_BROWSER_COUNT, + PROP_SEARCH_ENGINES }; enum { @@ -138,6 +142,15 @@ midori_app_class_init (MidoriAppClass* class) _("The current number of browsers"), 0, G_MAXUINT, 0, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_SEARCH_ENGINES, + g_param_spec_object ( + "search-engines", + _("Search Engines"), + _("The list of search engines"), + MIDORI_TYPE_WEB_LIST, + G_PARAM_READWRITE)); } static GObject* @@ -163,6 +176,7 @@ midori_app_init (MidoriApp* app) app->settings = midori_web_settings_new (); app->trash = midori_trash_new (10); + app->search_engines = midori_web_list_new (); } static void @@ -199,6 +213,11 @@ midori_app_set_property (GObject* object, g_object_ref (app->trash); /* FIXME: Propagate trash to all browsers */ break; + case PROP_SEARCH_ENGINES: + katze_object_assign (app->search_engines, g_value_get_object (value)); + g_object_ref (app->search_engines); + /* FIXME: Propagate search engines to all browsers */ + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -227,6 +246,9 @@ midori_app_get_property (GObject* object, case PROP_BROWSER_COUNT: g_value_set_uint (value, g_list_length (app->browsers)); break; + case PROP_SEARCH_ENGINES: + g_value_set_object (value, app->search_engines); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/midori/midori-browser.c b/midori/midori-browser.c index 5ef05de8..5947520f 100644 --- a/midori/midori-browser.c +++ b/midori/midori-browser.c @@ -13,8 +13,6 @@ #include "midori-browser.h" -#include "webSearch.h" - #include "main.h" #include "sokoke.h" #include "midori-webview.h" @@ -23,6 +21,7 @@ #include "midori-addons.h" #include "midori-console.h" #include "midori-trash.h" +#include "midori-searchentry.h" #include #include @@ -72,6 +71,7 @@ struct _MidoriBrowserPrivate KatzeXbelItem* proxy_xbel_folder; MidoriTrash* trash; + MidoriWebList* search_engines; }; #define MIDORI_BROWSER_GET_PRIVATE(obj) \ @@ -88,7 +88,8 @@ enum PROP_STATUSBAR, PROP_SETTINGS, PROP_STATUSBAR_TEXT, - PROP_TRASH + PROP_TRASH, + PROP_SEARCH_ENGINES }; enum @@ -503,7 +504,160 @@ midori_web_view_destroy_cb (GtkWidget* widget, } static void -_midori_browser_will_quit (MidoriBrowser* browser) +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 gint +_midori_browser_add_tab (MidoriBrowser* browser, + GtkWidget* widget) +{ + MidoriBrowserPrivate* priv; + GtkWidget* scrolled; + GtkWidget* child; + GObjectClass* gobject_class; + GtkWidget* label; + GtkWidget* menuitem; + KatzeXbelItem* xbel_item; + guint n; + + priv = browser->priv; + 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); + 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); + + label = NULL; + 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) + { + 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); + } + + 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; +} + +static gint +_midori_browser_add_uri (MidoriBrowser* browser, + const gchar* uri) +{ + MidoriBrowserPrivate* priv; + GtkWidget* web_view; + + priv = browser->priv; + 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); +} + +static 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); +} + +static void +_midori_browser_quit (MidoriBrowser* browser) { /* Nothing to do */ } @@ -702,10 +856,10 @@ midori_browser_class_init (MidoriBrowserClass* class) 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_will_quit; + 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; @@ -806,6 +960,20 @@ midori_browser_class_init (MidoriBrowserClass* class) MIDORI_TYPE_TRASH, G_PARAM_READWRITE)); + /** + * MidoriBrowser:search-engines: + * + * The list of search engines to be used for web search. + */ + g_object_class_install_property (gobject_class, + PROP_SEARCH_ENGINES, + g_param_spec_object ( + "search-engines", + _("Search Engines"), + _("The list of search engines to be used for web search"), + MIDORI_TYPE_WEB_LIST, + G_PARAM_READWRITE)); + g_type_class_add_private (class, sizeof (MidoriBrowserPrivate)); } @@ -1334,7 +1502,7 @@ midori_browser_location_key_press_event_cb (GtkWidget* widget, { g_object_get (priv->settings, "location-entry-search", &location_entry_search, NULL); - gchar* new_uri = sokoke_magic_uri (uri, NULL/*search_engines*/); + gchar* new_uri = sokoke_magic_uri (uri, priv->search_engines); if (!new_uri) new_uri = g_strdup (location_entry_search); g_free (location_entry_search); @@ -1848,13 +2016,19 @@ static void _action_manage_search_engines_activate (GtkAction* action, MidoriBrowser* browser) { + MidoriBrowserPrivate* priv; + static GtkWidget* dialog = NULL; + /* Show the Manage search engines dialog. Create it if necessary. */ - static GtkWidget* dialog; - if (GTK_IS_DIALOG (dialog)) + if (dialog) gtk_window_present (GTK_WINDOW (dialog)); else { - dialog = webSearch_manageSearchEngines_dialog_new (browser); + priv = browser->priv; + dialog = midori_search_entry_get_dialog ( + MIDORI_SEARCH_ENTRY (priv->search)); + g_signal_connect (dialog, "destroy", + G_CALLBACK (gtk_widget_destroyed), &dialog); gtk_widget_show (dialog); } } @@ -1882,24 +2056,6 @@ _action_tab_next_activate (GtkAction* action, 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/*[]*/ = /*{ @@ -2558,6 +2714,46 @@ midori_browser_realize_cb (GtkStyle* style, MidoriBrowser* browser) } } +static void +midori_browser_search_activate (GtkWidget* widget, + MidoriBrowser* browser) +{ + MidoriBrowserPrivate* priv; + MidoriWebList* search_engines; + const gchar* keywords; + guint last_web_search; + MidoriWebItem* web_item; + const gchar* url; + gchar* location_entry_search; + + priv = browser->priv; + search_engines = priv->search_engines; + keywords = gtk_entry_get_text (GTK_ENTRY (widget)); + g_object_get (priv->settings, "last-web-search", &last_web_search, NULL); + web_item = midori_web_list_get_nth_item (search_engines, last_web_search); + if (web_item) + { + location_entry_search = NULL; + url = midori_web_item_get_uri (web_item); + } + else /* The location entry search is our fallback */ + { + g_object_get (priv->settings, "location-entry-search", + &location_entry_search, NULL); + url = location_entry_search; + } + 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* web_view = midori_browser_get_current_web_view (browser); + webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), search); + g_free (search); + g_free (location_entry_search); +} + static void midori_browser_init (MidoriBrowser* browser) { @@ -2694,25 +2890,15 @@ midori_browser_init (MidoriBrowser* browser) 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); + priv->search = midori_search_entry_new (); /* TODO: Make this actively resizable or enlarge to fit contents? The interface is somewhat awkward and ought to be rethought 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); + g_signal_connect (priv->search, "activate", + G_CALLBACK (midori_browser_search_activate), browser); + g_signal_connect (priv->search, "focus-out-event", + G_CALLBACK (midori_browser_search_focus_out_event_cb), browser); toolitem = gtk_tool_item_new (); gtk_container_add (GTK_CONTAINER (toolitem), priv->search); gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1); @@ -3005,6 +3191,8 @@ midori_browser_finalize (GObject* object) g_object_unref (priv->settings); if (priv->trash) g_object_unref (priv->trash); + if (priv->search_engines) + g_object_unref (priv->search_engines); G_OBJECT_CLASS (midori_browser_parent_class)->finalize (object); } @@ -3044,7 +3232,8 @@ _midori_browser_set_toolbar_style (MidoriBrowser* browser, static void _midori_browser_update_settings (MidoriBrowser* browser) { - MidoriBrowserPrivate* priv = browser->priv; + MidoriBrowserPrivate* priv; + MidoriWebItem* web_item; gboolean remember_last_window_size; gint last_window_width, last_window_height; @@ -3055,6 +3244,8 @@ _midori_browser_update_settings (MidoriBrowser* browser) MidoriToolbarStyle toolbar_style; gint last_web_search; gchar* last_pageholder_uri; + + priv = browser->priv; g_object_get (priv->settings, "remember-last-window-size", &remember_last_window_size, "last-window-width", &last_window_width, @@ -3094,7 +3285,14 @@ _midori_browser_update_settings (MidoriBrowser* browser) small_toolbar ? GTK_ICON_SIZE_SMALL_TOOLBAR : GTK_ICON_SIZE_LARGE_TOOLBAR); - update_searchEngine (last_web_search, priv->search); + if (priv->search_engines) + { + web_item = midori_web_list_get_nth_item (priv->search_engines, + last_web_search); + if (web_item) + midori_search_entry_set_current_item (MIDORI_SEARCH_ENTRY (priv->search), + web_item); + } gtk_paned_set_position (GTK_PANED (gtk_widget_get_parent (priv->panel)), last_panel_position); @@ -3191,6 +3389,15 @@ midori_browser_set_property (GObject* object, /* FIXME: Connect to updates */ _midori_browser_update_actions (browser); break; + case PROP_SEARCH_ENGINES: + ; /* FIXME: Disconnect handlers */ + katze_object_assign (priv->search_engines, g_value_get_object (value)); + g_object_ref (priv->search_engines); + g_object_set (priv->search, "search-engines", + priv->search_engines, NULL); + /* FIXME: Connect to updates */ + _midori_browser_update_actions (browser); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3229,6 +3436,9 @@ midori_browser_get_property (GObject* object, case PROP_TRASH: g_value_set_object (value, priv->trash); break; + case PROP_SEARCH_ENGINES: + g_value_set_object (value, priv->search_engines); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3268,104 +3478,10 @@ gint midori_browser_add_tab (MidoriBrowser* browser, GtkWidget* widget) { - g_return_val_if_fail (GTK_IS_WIDGET (widget), -1); + gint index; - 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; + g_signal_emit (browser, signals[ADD_TAB], 0, widget, &index); + return index; } /** @@ -3429,15 +3545,10 @@ gint midori_browser_add_uri (MidoriBrowser* browser, const gchar* uri) { - MidoriBrowserPrivate* priv = browser->priv; + gint index; - 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); + g_signal_emit (browser, signals[ADD_URI], 0, uri, &index); + return index; } /** @@ -3451,11 +3562,7 @@ 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); + g_signal_emit (browser, signals[ACTIVATE_ACTION], 0, name); } /** @@ -3614,6 +3721,10 @@ midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser) * @browser: a #MidoriBrowser * * Quits the browser, including any other browser windows. + * + * This function relys on the application implementing + * the MidoriBrowser::quit signal. If the browser was added + * to the MidoriApp, this is handled automatically. **/ void midori_browser_quit (MidoriBrowser* browser) diff --git a/midori/midori-searchentry.c b/midori/midori-searchentry.c new file mode 100644 index 00000000..e3c30566 --- /dev/null +++ b/midori/midori-searchentry.c @@ -0,0 +1,735 @@ +/* + 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-searchentry.h" + +#include "sokoke.h" + +#include +#include +#include + +struct _MidoriSearchEntry +{ + SexyIconEntry parent_instance; + + GtkWidget* dialog; + GtkWidget* treeview; + GtkWidget* edit_button; + GtkWidget* remove_button; + + MidoriWebList* search_engines; + MidoriWebItem* current_item; +}; + +G_DEFINE_TYPE (MidoriSearchEntry, midori_search_entry, SEXY_TYPE_ICON_ENTRY) + +enum +{ + PROP_0, + + PROP_SEARCH_ENGINES, + PROP_CURRENT_ITEM, + PROP_DIALOG +}; + +static void +midori_search_entry_finalize (GObject* object); + +static void +midori_search_entry_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_search_entry_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static void +midori_search_entry_class_init (MidoriSearchEntryClass* class) +{ + GObjectClass* gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_search_entry_finalize; + gobject_class->set_property = midori_search_entry_set_property; + gobject_class->get_property = midori_search_entry_get_property; + + g_object_class_install_property (gobject_class, + PROP_SEARCH_ENGINES, + g_param_spec_object ( + "search-engines", + _("Search Engines"), + _("The list of search engines"), + MIDORI_TYPE_WEB_LIST, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_CURRENT_ITEM, + g_param_spec_object ( + "current-item", + _("Current Item"), + _("The currently selected item"), + MIDORI_TYPE_WEB_ITEM, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_DIALOG, + g_param_spec_object ( + "dialog", + _("Dialog"), + _("A dialog to manage search engines"), + GTK_TYPE_DIALOG, + G_PARAM_READABLE)); +} + +static void +midori_search_entry_engine_activate_cb (GtkWidget* widget, + MidoriSearchEntry* search_entry) +{ + MidoriWebItem* web_item; + + web_item = (MidoriWebItem*)g_object_get_data (G_OBJECT (widget), "engine"); + midori_search_entry_set_current_item (search_entry, web_item); +} + +static void +midori_search_entry_icon_released_cb (GtkWidget* widget, + SexyIconEntryPosition* pos, + gint button) +{ + MidoriSearchEntry* search_entry; + MidoriWebList* search_engines; + GtkWidget* menu; + guint n, i; + GtkWidget* menuitem; + MidoriWebItem* web_item; + GdkPixbuf* pixbuf; + GtkWidget* icon; + + search_entry = MIDORI_SEARCH_ENTRY (widget); + search_engines = search_entry->search_engines; + menu = gtk_menu_new (); + n = midori_web_list_get_length (search_engines); + if (n) + { + for (i = 0; i < n; i++) + { + web_item = midori_web_list_get_nth_item (search_engines, i); + menuitem = gtk_image_menu_item_new_with_label ( + midori_web_item_get_name (web_item)); + pixbuf = sokoke_web_icon (midori_web_item_get_icon (web_item), + GTK_ICON_SIZE_MENU, menuitem); + 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", web_item); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_search_entry_engine_activate_cb), widget); + 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 gboolean +midori_search_entry_key_press_event_cb (GtkWidget* widget, + GdkEventKey* event) +{ + GdkModifierType state; + 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; +} + +static gboolean +midori_search_entry_scroll_event_cb (GtkWidget* widget, + GdkEventScroll* event) +{ + 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; +} + +static void +midori_search_entry_init (MidoriSearchEntry* search_entry) +{ + search_entry->dialog = NULL; + + search_entry->search_engines = midori_web_list_new (); + search_entry->current_item = NULL; + + sexy_icon_entry_set_icon_highlight (SEXY_ICON_ENTRY (search_entry), + SEXY_ICON_ENTRY_PRIMARY, TRUE); + g_object_connect (search_entry, + "signal::icon-released", + midori_search_entry_icon_released_cb, NULL, + "signal::key-press-event", + midori_search_entry_key_press_event_cb, NULL, + "signal::scroll-event", + midori_search_entry_scroll_event_cb, NULL, + NULL); +} + +static void +midori_search_entry_finalize (GObject* object) +{ + MidoriSearchEntry* search_entry = MIDORI_SEARCH_ENTRY (object); + + g_object_unref (search_entry->search_engines); + + G_OBJECT_CLASS (midori_search_entry_parent_class)->finalize (object); +} + +static void +midori_search_entry_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriSearchEntry* search_entry = MIDORI_SEARCH_ENTRY (object); + + switch (prop_id) + { + case PROP_SEARCH_ENGINES: + search_entry->search_engines = g_value_get_object (value); + break; + case PROP_CURRENT_ITEM: + search_entry->current_item = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_search_entry_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriSearchEntry* search_entry = MIDORI_SEARCH_ENTRY (object); + + switch (prop_id) + { + case PROP_SEARCH_ENGINES: + g_value_set_object (value, search_entry->search_engines); + break; + case PROP_CURRENT_ITEM: + g_value_set_object (value, search_entry->current_item); + break; + case PROP_DIALOG: + g_value_set_object (value, midori_search_entry_get_dialog (search_entry)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_search_entry_new: + * + * Creates a new #MidoriSearchEntry. + * + * Return value: a new #MidoriSearchEntry + **/ +GtkWidget* +midori_search_entry_new (void) +{ + GtkWidget* search_entry = g_object_new (MIDORI_TYPE_SEARCH_ENTRY, NULL); + + return search_entry; +} + +/** + * midori_search_entry_get_search_engines: + * @search_entry: a #MidoriSearchEntry + * + * Retrieves the list of search engines. + * + * Return value: the list of search engines + **/ +MidoriWebList* +midori_search_entry_get_search_engines (MidoriSearchEntry* search_entry) +{ + g_return_val_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry), NULL); + + return search_entry->search_engines; +} + +/** + * midori_search_entry_set_search_engines: + * @search_entry: a #MidoriSearchEntry + * @search_engines: a list of search engines + * + * Sets the list of search engines. + **/ +void +midori_search_entry_set_search_engines (MidoriSearchEntry* search_entry, + MidoriWebList* search_engines) +{ + g_return_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry)); + + g_object_ref (search_engines); + katze_object_assign (search_entry->search_engines, search_engines); + g_object_notify (G_OBJECT (search_entry), "search-engines"); +} + +/** + * midori_search_entry_set_current_item: + * @search_entry: a #MidoriSearchEntry + * @item: a #MidoriWebItem + * + * Looks up the specified item in the list of search engines and makes + * it the currently selected item. + * + * This function fails if @item is not in the current list. + **/ +void +midori_search_entry_set_current_item (MidoriSearchEntry* search_entry, + MidoriWebItem* web_item) +{ + GdkPixbuf* pixbuf; + + g_return_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry)); + g_return_if_fail (MIDORI_IS_WEB_ITEM (web_item)); + + pixbuf = sokoke_web_icon (midori_web_item_get_icon (web_item), + GTK_ICON_SIZE_MENU, GTK_WIDGET (search_entry)); + sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (search_entry), + SEXY_ICON_ENTRY_PRIMARY, + GTK_IMAGE (gtk_image_new_from_pixbuf (pixbuf))); + g_object_unref (pixbuf); + sokoke_entry_set_default_text (GTK_ENTRY (search_entry), + midori_web_item_get_name (web_item)); + search_entry->current_item = web_item; + g_object_notify (G_OBJECT (search_entry), "current-item"); +} + +/** + * midori_search_entry_get_current_item: + * @search_entry: a #MidoriSearchEntry + * + * Retrieves the currently selected item. + * + * Return value: the selected web item, or %NULL + **/ +MidoriWebItem* +midori_search_entry_get_current_item (MidoriSearchEntry* search_entry) +{ + g_return_val_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry), NULL); + + return search_entry->current_item; +} + +static void +midori_search_entry_dialog_render_icon_cb (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + MidoriWebItem* web_item; + const gchar* icon; + GdkPixbuf* pixbuf; + + gtk_tree_model_get (model, iter, 0, &web_item, -1); + + icon = midori_web_item_get_icon (web_item); + if (icon) + { + pixbuf = sokoke_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 +midori_search_entry_dialog_render_text (GtkTreeViewColumn* column, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + GtkWidget* treeview) +{ + MidoriWebItem* web_item; + const gchar* name; + const gchar* description; + gchar* markup; + + gtk_tree_model_get (model, iter, 0, &web_item, -1); + name = midori_web_item_get_name (web_item); + description = midori_web_item_get_description (web_item); + markup = g_markup_printf_escaped ("%s\n%s", name, description); + g_object_set (renderer, "markup", markup, NULL); + g_free (markup); +} + +static void +midori_search_entry_editor_name_changed_cb (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 +midori_search_entry_get_editor (MidoriSearchEntry* search_entry, + gboolean new_engine, + GtkWindow* transient_for) +{ + MidoriWebList* search_engines; + GtkWidget* dialog; + GtkSizeGroup* sizegroup; + MidoriWebItem* web_item; + GtkWidget* hbox; + GtkWidget* label; + GtkTreeModel* liststore; + GtkTreeIter iter; + GtkWidget* treeview; + GtkTreeSelection* selection; + GtkWidget* entry_name; + GtkWidget* entry_description; + GtkWidget* entry_uri; + GtkWidget* entry_icon; + GtkWidget* entry_token; + + search_engines = search_entry->search_engines; + treeview = search_entry->treeview; + + dialog = gtk_dialog_new_with_buttons ( + new_engine ? _("Add search engine") : _("Edit search engine"), + transient_for ? GTK_WINDOW (transient_for) : NULL, + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + new_engine ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_window_set_icon_name (GTK_WINDOW (dialog), + new_engine ? 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); + sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + if (new_engine) + { + web_item = midori_web_item_new (); + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GTK_RESPONSE_ACCEPT, FALSE); + } + else + { + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + gtk_tree_selection_get_selected (selection, &liststore, &iter); + gtk_tree_model_get (liststore, &iter, 0, &web_item, -1); + } + + hbox = gtk_hbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + 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); + entry_name = gtk_entry_new (); + g_signal_connect (entry_name, "changed", + G_CALLBACK (midori_search_entry_editor_name_changed_cb), dialog); + gtk_entry_set_activates_default (GTK_ENTRY (entry_name), TRUE); + if (!new_engine) + gtk_entry_set_text (GTK_ENTRY (entry_name), + STR_NON_NULL (midori_web_item_get_name (web_item))); + gtk_box_pack_start (GTK_BOX (hbox), entry_name, 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); + entry_description = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_description), TRUE); + if (!new_engine) + gtk_entry_set_text (GTK_ENTRY (entry_description) + , STR_NON_NULL (midori_web_item_get_description (web_item))); + 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); + entry_uri = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE); + if (!new_engine) + gtk_entry_set_text (GTK_ENTRY (entry_uri) + , STR_NON_NULL (midori_web_item_get_uri (web_item))); + 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); + + 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); + entry_icon = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_icon), TRUE); + if (!new_engine) + gtk_entry_set_text (GTK_ENTRY (entry_icon) + , STR_NON_NULL (midori_web_item_get_icon (web_item))); + 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 (_("_Token:")); + gtk_size_group_add_widget (sizegroup, label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + entry_token = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry_token), TRUE); + if (!new_engine) + gtk_entry_set_text (GTK_ENTRY (entry_token) + , STR_NON_NULL (midori_web_item_get_token (web_item))); + gtk_box_pack_start (GTK_BOX (hbox), entry_token, 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) + { + g_object_set (web_item, + "name", gtk_entry_get_text (GTK_ENTRY (entry_name)), + "description", gtk_entry_get_text (GTK_ENTRY (entry_description)), + "uri", gtk_entry_get_text (GTK_ENTRY (entry_uri)), + "icon", gtk_entry_get_text (GTK_ENTRY (entry_icon)), + "token", gtk_entry_get_text (GTK_ENTRY (entry_token)), + NULL); + + if (new_engine) + { + midori_web_list_add_item (search_engines, web_item); + liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); + gtk_list_store_append (GTK_LIST_STORE (liststore), &iter); + } + gtk_list_store_set (GTK_LIST_STORE (liststore), &iter, + 0, web_item, -1); + } + gtk_widget_destroy (dialog); +} + +static void +midori_search_entry_dialog_add_cb (GtkWidget* widget, + MidoriSearchEntry* search_entry) +{ + midori_search_entry_get_editor (search_entry, TRUE, + GTK_WINDOW (search_entry->dialog)); +} + +static void +midori_search_entry_dialog_edit_cb (GtkWidget* widget, + MidoriSearchEntry* search_entry) +{ + midori_search_entry_get_editor (search_entry, FALSE, + GTK_WINDOW (search_entry->dialog)); +} + +static void +midori_search_entry_dialog_remove_cb (GtkWidget* widget, + MidoriSearchEntry* search_entry) +{ + GtkWidget* treeview; + GtkTreeSelection* selection; + GtkTreeModel* liststore; + GtkTreeIter iter; + MidoriWebItem* web_item; + MidoriWebList* search_engines; + + treeview = search_entry->treeview; + search_engines = search_entry->search_engines; + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + gtk_tree_selection_get_selected (selection, &liststore, &iter); + gtk_tree_model_get (liststore, &iter, 0, &web_item, -1); + gtk_list_store_remove (GTK_LIST_STORE (liststore), &iter); + g_object_unref (web_item); + midori_web_list_remove_item (search_engines, web_item); + /* FIXME: we want to allow undo of some kind */ +} + +/** + * midori_search_entry_get_dialog: + * @search_entry: a #MidoriSearchEntry + * + * Obtains a dialog that provides an interface for managing + * the list of search engines. + * + * A new dialog is created each time, so it may be a good idea + * to store the pointer for the life time of the dialog. + * + * Return value: a dialog + **/ +GtkWidget* +midori_search_entry_get_dialog (MidoriSearchEntry* search_entry) +{ + const gchar* dialog_title; + GtkWidget* toplevel; + GtkWidget* dialog; + gint width, height; + GtkWidget* xfce_heading; + GtkWidget* hbox; + GtkTreeViewColumn* column; + GtkCellRenderer* renderer_text; + GtkCellRenderer* renderer_pixbuf; + GtkListStore* liststore; + GtkWidget* treeview; + GtkWidget* scrolled; + guint n, i; + MidoriWebItem* web_item; + GtkWidget* vbox; + GtkWidget* button; + + g_return_val_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry), NULL); + + dialog_title = _("Manage search engines"); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (search_entry)); + dialog = gtk_dialog_new_with_buttons (dialog_title, + toplevel ? GTK_WINDOW (toplevel) : NULL, + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_HELP, GTK_RESPONSE_HELP, + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, + NULL); + search_entry->dialog = dialog; + 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); + sokoke_widget_get_text_size (dialog, "M", &width, &height); + gtk_window_set_default_size (GTK_WINDOW (dialog), width * 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? + We need mnemonics */ + if ((xfce_heading = sokoke_xfce_header_new ( + gtk_window_get_icon_name (GTK_WINDOW (dialog)), dialog_title))) + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + xfce_heading, FALSE, FALSE, 0); + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, + TRUE, TRUE, 12); + liststore = gtk_list_store_new (1, MIDORI_TYPE_WEB_ITEM); + treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore)); + search_entry->treeview = treeview; + 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_search_entry_dialog_render_icon_cb, + 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)midori_search_entry_dialog_render_text, + treeview, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + 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); + n = midori_web_list_get_length (search_entry->search_engines); + for (i = 0; i < n; i++) + { + web_item = midori_web_list_get_nth_item (search_entry->search_engines, i); + gtk_list_store_insert_with_values (GTK_LIST_STORE (liststore), + NULL, i, 0, web_item, -1); + } + g_object_unref (liststore); + vbox = gtk_vbox_new (FALSE, 4); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 4); + button = gtk_button_new_from_stock (GTK_STOCK_ADD); + g_signal_connect (button, "clicked", + G_CALLBACK (midori_search_entry_dialog_add_cb), search_entry); + 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 (midori_search_entry_dialog_edit_cb), search_entry); + gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); + search_entry->edit_button = button; + if (!n) + gtk_widget_set_sensitive (button, FALSE); + button = gtk_button_new_from_stock (GTK_STOCK_REMOVE); + g_signal_connect (button, "clicked", + G_CALLBACK (midori_search_entry_dialog_remove_cb), search_entry); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + if (!n) + gtk_widget_set_sensitive (button, FALSE); + search_entry->remove_button = 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); + gtk_widget_show_all (GTK_DIALOG (dialog)->vbox); + + /* TODO: Connect to MidoriWebList::add_item and ::remove_item */ + + return dialog; +} diff --git a/midori/midori-searchentry.h b/midori/midori-searchentry.h new file mode 100644 index 00000000..f9295085 --- /dev/null +++ b/midori/midori-searchentry.h @@ -0,0 +1,61 @@ +/* + 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_SEARCH_ENTRY_H__ +#define __MIDORI_SEARCH_ENTRY_H__ + +#include "midori-weblist.h" + +#include +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_SEARCH_ENTRY \ + (midori_search_entry_get_type ()) +#define MIDORI_SEARCH_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_SEARCH_ENTRY, MidoriSearchEntry)) +#define MIDORI_SEARCH_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_SEARCH_ENTRY, MidoriSearchEntryClass)) +#define MIDORI_IS_SEARCH_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_SEARCH_ENTRY)) +#define MIDORI_IS_SEARCH_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_SEARCH_ENTRY)) +#define MIDORI_SEARCH_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_SEARCH_ENTRY, MidoriSearchEntryClass)) + +typedef struct _MidoriSearchEntry MidoriSearchEntry; +typedef struct _MidoriSearchEntryClass MidoriSearchEntryClass; + +struct _MidoriSearchEntryClass +{ + SexyIconEntryClass parent_class; +}; + +GType +midori_search_entry_get_type (void); + +GtkWidget* +midori_search_entry_new (void); + +MidoriWebItem* +midori_search_entry_get_current_item (MidoriSearchEntry* search_entry); + +void +midori_search_entry_set_current_item (MidoriSearchEntry* search_entry, + MidoriWebItem* name); + +GtkWidget* +midori_search_entry_get_dialog (MidoriSearchEntry* search_entry); + +G_END_DECLS + +#endif /* __MIDORI_SEARCH_ENTRY_H__ */ diff --git a/midori/midori-webitem.c b/midori/midori-webitem.c index bf74aff3..b74bbff1 100644 --- a/midori/midori-webitem.c +++ b/midori/midori-webitem.c @@ -114,12 +114,20 @@ midori_web_item_class_init (MidoriWebItemClass* class) static void midori_web_item_init (MidoriWebItem* web_item) { - // Nothing to do here + /* Nothing to do here */ } static void midori_web_item_finalize (GObject* object) { + MidoriWebItem* web_item = MIDORI_WEB_ITEM (object); + + g_free (web_item->name); + g_free (web_item->description); + g_free (web_item->uri); + g_free (web_item->icon); + g_free (web_item->token); + G_OBJECT_CLASS (midori_web_item_parent_class)->finalize (object); } diff --git a/midori/midori-weblist.c b/midori/midori-weblist.c index 6976204d..6d1f9a26 100644 --- a/midori/midori-weblist.c +++ b/midori/midori-weblist.c @@ -35,6 +35,21 @@ static guint signals[LAST_SIGNAL]; static void midori_web_list_finalize (GObject* object); +static void +_midori_web_list_add_item (MidoriWebList* web_list, + MidoriWebItem* web_item) +{ + g_object_ref (web_item); + web_list->items = g_list_append (web_list->items, web_item); +} + +static void +_midori_web_list_remove_item (MidoriWebList* web_list, + MidoriWebItem* web_item) +{ + web_list->items = g_list_remove (web_list->items, web_item); +} + static void midori_web_list_class_init (MidoriWebListClass* class) { @@ -60,8 +75,8 @@ midori_web_list_class_init (MidoriWebListClass* class) G_TYPE_NONE, 1, MIDORI_TYPE_WEB_ITEM); - class->add_item = midori_web_list_add_item; - class->remove_item = midori_web_list_remove_item; + class->add_item = _midori_web_list_add_item; + class->remove_item = _midori_web_list_remove_item; GObjectClass* gobject_class = G_OBJECT_CLASS (class); gobject_class->finalize = midori_web_list_finalize; @@ -111,8 +126,7 @@ void midori_web_list_add_item (MidoriWebList* web_list, MidoriWebItem* web_item) { - g_object_ref (web_item); - web_list->items = g_list_append (web_list->items, web_item); + g_signal_emit (web_list, signals[ADD_ITEM], 0, web_item); } /** @@ -126,7 +140,7 @@ void midori_web_list_remove_item (MidoriWebList* web_list, MidoriWebItem* web_item) { - web_list->items = g_list_remove (web_list->items, web_item); + g_signal_emit (web_list, signals[REMOVE_ITEM], 0, web_item); } /** diff --git a/midori/sokoke.c b/midori/sokoke.c index 3f5afeca..b7024e91 100644 --- a/midori/sokoke.c +++ b/midori/sokoke.c @@ -473,3 +473,39 @@ sokoke_widget_get_text_size (GtkWidget* widget, pango_layout_get_pixel_size (layout, width, height); g_object_unref (layout); } + +GdkPixbuf* +sokoke_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; +} diff --git a/midori/sokoke.h b/midori/sokoke.h index 2fa36bf0..a2b14afc 100644 --- a/midori/sokoke.h +++ b/midori/sokoke.h @@ -109,4 +109,9 @@ sokoke_widget_get_text_size (GtkWidget* widget, gint* width, gint* height); +GdkPixbuf* +sokoke_web_icon (const gchar* icon, + GtkIconSize size, + GtkWidget* widget); + #endif /* !__SOKOKE_H__ */ diff --git a/midori/webSearch.c b/midori/webSearch.c deleted file mode 100644 index 36b2d226..00000000 --- a/midori/webSearch.c +++ /dev/null @@ -1,487 +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 "webSearch.h" - -#include "search.h" - -#include "main.h" -#include "sokoke.h" - -#include "midori-webitem.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) -{ - MidoriWebList* search_engines = midori_web_list_new (); /* FIXME */ - guint n = midori_web_list_get_length (search_engines); - MidoriWebItem* web_item; - /* 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; - web_item = midori_web_list_get_nth_item (search_engines, index); - GdkPixbuf* pixbuf = load_web_icon (midori_web_item_get_icon (web_item), - 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), - midori_web_item_get_name (web_item)); - /* 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) -{ - MidoriWebList* search_engines = midori_web_list_new (); /* FIXME */ - GtkWidget* menu = gtk_menu_new(); - guint n = midori_web_list_get_length (search_engines); - GtkWidget* menuitem; - MidoriWebItem* web_item; - if(n) - { - guint i; - for(i = 0; i < n; i++) - { - web_item = midori_web_list_get_nth_item (search_engines, i); - menuitem = gtk_image_menu_item_new_with_label ( - midori_web_item_get_name (web_item)); - GdkPixbuf* pixbuf = load_web_icon (midori_web_item_get_icon (web_item), - 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) -{ - MidoriWebItem* web_item; - gtk_tree_model_get(model, iter, ENGINES_COL_ENGINE, &web_item, -1); - - /* TODO: Would it be better to not do this on every redraw? */ - const gchar* icon = midori_web_item_get_icon (web_item); - 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) -{ - MidoriWebItem* web_item; - gtk_tree_model_get(model, iter, ENGINES_COL_ENGINE, &web_item, -1); - const gchar* name = midori_web_item_get_name (web_item); - const gchar* description = midori_web_item_get_description (web_item); - 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) -{ - MidoriWebList* search_engines = midori_web_list_new (); /* FIXME */ - 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); - - MidoriWebItem* web_item; - GtkTreeModel* liststore; - GtkTreeIter iter; - if(newEngine) - { - web_item = midori_web_item_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, &web_item, -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) - , STR_NON_NULL (midori_web_item_get_name (web_item))); - 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 (midori_web_item_get_description (web_item))); - 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 (midori_web_item_get_uri (web_item))); - 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 (midori_web_item_get_icon (web_item))); - 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(midori_web_item_get_token (web_item))); - 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) - { - midori_web_item_set_name (web_item - , gtk_entry_get_text(GTK_ENTRY(entry_shortName))); - midori_web_item_set_description (web_item - , gtk_entry_get_text(GTK_ENTRY(entry_description))); - midori_web_item_set_uri (web_item - , gtk_entry_get_text(GTK_ENTRY(entry_url))); - /*search_engine_set_input_encoding(searchEngine - , gtk_entry_get_text(GTK_ENTRY(entry_inputEncoding)));*/ - midori_web_item_set_icon (web_item - , gtk_entry_get_text(GTK_ENTRY(entry_icon))); - midori_web_item_set_token (web_item - , gtk_entry_get_text(GTK_ENTRY(entry_keyword))); - - if(newEngine) - { - midori_web_list_add_item (search_engines, web_item); - 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, web_item, -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) -{ - MidoriWebList* search_engines = midori_web_list_new (); /* FIXME */ - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(webSearch->treeview)); - GtkTreeModel* liststore; - GtkTreeIter iter; - gtk_tree_selection_get_selected(selection, &liststore, &iter); - MidoriWebItem* web_item; - gtk_tree_model_get(liststore, &iter, ENGINES_COL_ENGINE, &web_item, -1); - gtk_list_store_remove(GTK_LIST_STORE(liststore), &iter); - g_object_unref (web_item); - midori_web_list_remove_item (search_engines, web_item); - /*update_searchEngine(config->searchEngine, webSearch->browser); */ - webSearch_toggle_edit_buttons(midori_web_list_get_length(search_engines), webSearch); - /* FIXME: we want to allow undo of some kind */ -} - -GtkWidget* webSearch_manageSearchEngines_dialog_new(MidoriBrowser* browser) -{ - MidoriWebList* search_engines = midori_web_list_new (); /* FIXME */ - 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? - We need mnemonics - 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 - , MIDORI_TYPE_WEB_ITEM); - 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 = midori_web_list_get_length (search_engines); - guint i; - for(i = 0; i < n; i++) - { - MidoriWebItem* web_item = midori_web_list_get_nth_item (search_engines, i); - gtk_list_store_insert_with_values(GTK_LIST_STORE(liststore), NULL, i - , ENGINES_COL_ENGINE, web_item, -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) -{ - MidoriWebList* search_engines = midori_web_list_new (); /* FIXME */ - const gchar* keywords = gtk_entry_get_text(GTK_ENTRY(widget)); - const gchar* url; - MidoriWebItem* web_item = midori_web_list_get_nth_item (search_engines, 0/*config->searchEngine*/); - if (web_item) - url = midori_web_item_get_uri (web_item); - 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 deleted file mode 100644 index 01e8df93..00000000 --- a/midori/webSearch.h +++ /dev/null @@ -1,57 +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 - -typedef struct -{ - MidoriBrowser* browser; - GtkWidget* window; - GtkWidget* treeview; - GtkWidget* edit; - GtkWidget* remove; -} CWebSearch; - -enum -{ - ENGINES_COL_ENGINE, - ENGINES_COL_N -}; - -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/po/POTFILES.in b/po/POTFILES.in index 24033dc6..bb0358a2 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -13,8 +13,8 @@ midori/midori-webview.c midori/midori-preferences.c midori/midori-webitem.c midori/midori-weblist.c +midori/midori-searchentry.c midori/sokoke.c -midori/webSearch.c midori/gjs.c katze/katze-throbber.c katze/katze-utils.c