]> spindle.queued.net Git - midori/commitdiff
Complete move of webSearch, third step of refactoring web search
authorChristian Dywan <christian@twotoasts.de>
Sun, 15 Jun 2008 02:02:56 +0000 (04:02 +0200)
committerChristian Dywan <christian@twotoasts.de>
Sun, 15 Jun 2008 02:02:56 +0000 (04:02 +0200)
13 files changed:
midori/Makefile.am
midori/main.c
midori/midori-app.c
midori/midori-browser.c
midori/midori-searchentry.c [new file with mode: 0644]
midori/midori-searchentry.h [new file with mode: 0644]
midori/midori-webitem.c
midori/midori-weblist.c
midori/sokoke.c
midori/sokoke.h
midori/webSearch.c [deleted file]
midori/webSearch.h [deleted file]
po/POTFILES.in

index 55db4c0c7e0168028caceb5c86af735ba54b2a51..fe0c9e5a665221b7cb2df99d67675c97920c9229 100644 (file)
@@ -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
index de04460a66500d1153092a153409deb327672d79..ee78f140655a3941d8dc03987bc9c4780f644edc 100644 (file)
@@ -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));
index df406911074f6d28c89ece1e9669812f1eaa4fc7..6cab34035d5d3a4b763889c3f26c609989ceec89 100644 (file)
@@ -11,6 +11,8 @@
 
 #include "midori-app.h"
 
+#include "midori-weblist.h"
+
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 
@@ -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;
index 5ef05de8605bec579a8196edd0e371ef58dba690..5947520f8dbd8384b5079c6c6ebc4463e4c8516f 100644 (file)
@@ -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 <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
@@ -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 <christian@twotoasts.de>", 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);
-
-    MidoriBrowserPrivate* priv = browser->priv;
+    gint index;
 
-    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 (file)
index 0000000..e3c3056
--- /dev/null
@@ -0,0 +1,735 @@
+/*
+ Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See the file COPYING for the full license text.
+*/
+
+#include "midori-searchentry.h"
+
+#include "sokoke.h"
+
+#include <katze/katze.h>
+#include <gdk/gdkkeysyms.h>
+#include <glib/gi18n.h>
+
+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 ("<b>%s</b>\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 (file)
index 0000000..f929508
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See the file COPYING for the full license text.
+*/
+
+#ifndef __MIDORI_SEARCH_ENTRY_H__
+#define __MIDORI_SEARCH_ENTRY_H__
+
+#include "midori-weblist.h"
+
+#include <gtk/gtk.h>
+#include <libsexy/sexy.h>
+
+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__ */
index bf74aff39cf448b69bece639b3ce092632719bcb..b74bbff143e6a0f740f06c118323cddf00e46a9c 100644 (file)
@@ -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);
 }
 
index 6976204db7ed0ee3bab62f76d98432d91e7e9d00..6d1f9a268b05fd932f0ff7924dbe164b51faf755 100644 (file)
@@ -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);
 }
 
 /**
index 3f5afeca3c5daceac1727c52bdbafd843875c88a..b7024e917e1983f025be3e14f6e0d04b85543601 100644 (file)
@@ -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;
+}
index 2fa36bf019b64e78b84f146fe17b2718a7148e38..a2b14afc53ba782668b78a80544b15ebf977994f 100644 (file)
@@ -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 (file)
index 36b2d22..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- See the file COPYING for the full license text.
-*/
-
-#include "webSearch.h"
-
-#include "search.h"
-
-#include "main.h"
-#include "sokoke.h"
-
-#include "midori-webitem.h"
-
-#include <string.h>
-#include <gdk/gdkkeysyms.h>
-#include <glib/gi18n.h>
-
-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("<b>%s</b>\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 (file)
index 01e8df9..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- See the file COPYING for the full license text.
-*/
-
-#ifndef __WEBSEARCH_H__
-#define __WEBSEARCH_H__ 1
-
-#include "midori-browser.h"
-
-#include <gtk/gtk.h>
-#include <libsexy/sexy.h>
-#include <webkit/webkit.h>
-
-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__ */
index 24033dc68578b0f1a2c7f9ad7d18504b1d5b1134..bb0358a2323f2787e2cb9a098f1ff059f7a36783 100644 (file)
@@ -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