Complete move of webSearch, third step of refactoring web search

This commit is contained in:
Christian Dywan 2008-06-15 04:02:56 +02:00
parent 3ac8bdb438
commit 7df5d483f9
13 changed files with 1166 additions and 714 deletions

View 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

View 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));

View 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;

View 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);
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)

735
midori/midori-searchentry.c Normal file
View File

@ -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;
}

View File

@ -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__ */

View 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);
}

View 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);
}
/**

View 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;
}

View 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__ */

View File

@ -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);
}

View File

@ -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__ */

View 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