Introduce MidoriWebList, second step of refactoring web search

This commit is contained in:
Christian Dywan 2008-06-14 02:23:33 +02:00
parent 86129a03da
commit 3ac8bdb438
15 changed files with 652 additions and 382 deletions

View file

@ -28,7 +28,11 @@ if bld.env ()['CONVERT']:
'-background', 'transparent',
'-geometry', format, '-extent', format,
srcdir + '/data/midori.svg',
blddir + '/icons/' + format + '/midori.png'])
blddir + '/icons/' + format + '/midori.png'],
stderr=subprocess.PIPE)
if not convert.wait ():
install_files ('DATADIR', 'icons/hicolor/' + format + '/apps',
blddir + '/icons/' + format + '/midori.png')
else:
Params.pprint ('BLUE', "Optimized icons could not be created.")
break

View file

@ -19,6 +19,7 @@ bin_PROGRAMS = \
midori_SOURCES = \
main.c main.h \
midori-webitem.c midori-webitem.h \
midori-weblist.c midori-weblist.h \
midori-app.c midori-app.h \
midori-browser.c midori-browser.h \
midori-panel.c midori-panel.h \
@ -31,5 +32,4 @@ midori_SOURCES = \
webSearch.c webSearch.h \
gjs.c gjs.h \
sokoke.c sokoke.h \
search.c search.h \
compat.c compat.h

View file

@ -12,26 +12,25 @@
#include "main.h"
#include "sokoke.h"
#include "search.h"
#include "midori-app.h"
#include "midori-websettings.h"
#include "midori-trash.h"
#include "midori-browser.h"
#include "midori-weblist.h"
#include "gjs.h"
#include <katze/katze.h>
#include <string.h>
#include <gtk/gtk.h>
#if HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef ENABLE_NLS
#include <libintl.h>
#endif
// -- stock icons
static void stock_items_init(void)
{
static GtkStockItem items[] =
@ -57,17 +56,20 @@ static void stock_items_init(void)
{ GTK_STOCK_LEAVE_FULLSCREEN, N_("_Leave Fullscreen"), 0, 0, NULL },
#endif
};
GtkIconSource* icon_source;
GtkIconSet* icon_set;
GtkIconFactory* factory = gtk_icon_factory_new ();
guint i;
for (i = 0; i < (guint)G_N_ELEMENTS (items); i++)
{
GtkIconSource* iconSource = gtk_icon_source_new();
gtk_icon_source_set_icon_name(iconSource, items[i].stock_id);
GtkIconSet* iconSet = gtk_icon_set_new();
gtk_icon_set_add_source(iconSet, iconSource);
gtk_icon_source_free(iconSource);
gtk_icon_factory_add(factory, items[i].stock_id, iconSet);
gtk_icon_set_unref(iconSet);
icon_source = gtk_icon_source_new ();
gtk_icon_source_set_icon_name (icon_source, items[i].stock_id);
icon_set = gtk_icon_set_new ();
gtk_icon_set_add_source (icon_set, icon_source);
gtk_icon_source_free (icon_source);
gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
gtk_icon_set_unref (icon_set);
}
gtk_stock_add_static (items, G_N_ELEMENTS (items));
gtk_icon_factory_add_default (factory);
@ -90,6 +92,17 @@ settings_new_from_file (const gchar* filename)
MidoriWebSettings* settings = midori_web_settings_new ();
GKeyFile* key_file = g_key_file_new ();
GError* error = NULL;
GObjectClass* class;
guint i, n_properties;
GParamSpec** pspecs;
GParamSpec* pspec;
GType type;
const gchar* property;
gchar* string;
gint integer;
gfloat number;
gboolean boolean;
if (!g_key_file_load_from_file (key_file, filename,
G_KEY_FILE_KEEP_COMMENTS, &error))
{
@ -98,19 +111,18 @@ settings_new_from_file (const gchar* filename)
error->message);
g_error_free (error);
}
GObjectClass* class = G_OBJECT_GET_CLASS (settings);
guint i, n_properties;
GParamSpec** pspecs = g_object_class_list_properties (class, &n_properties);
class = G_OBJECT_GET_CLASS (settings);
pspecs = g_object_class_list_properties (class, &n_properties);
for (i = 0; i < n_properties; i++)
{
GParamSpec* pspec = pspecs[i];
pspec = pspecs[i];
if (!(pspec->flags & G_PARAM_WRITABLE))
continue;
GType type = G_PARAM_SPEC_TYPE (pspec);
const gchar* property = g_param_spec_get_name (pspec);
type = G_PARAM_SPEC_TYPE (pspec);
property = g_param_spec_get_name (pspec);
if (type == G_TYPE_PARAM_STRING)
{
gchar* string = sokoke_key_file_get_string_default (key_file,
string = sokoke_key_file_get_string_default (key_file,
"settings", property,
G_PARAM_SPEC_STRING (pspec)->default_value, NULL);
g_object_set (settings, property, string, NULL);
@ -118,21 +130,21 @@ settings_new_from_file (const gchar* filename)
}
else if (type == G_TYPE_PARAM_INT)
{
gint integer = sokoke_key_file_get_integer_default (key_file,
integer = sokoke_key_file_get_integer_default (key_file,
"settings", property,
G_PARAM_SPEC_INT (pspec)->default_value, NULL);
g_object_set (settings, property, integer, NULL);
}
else if (type == G_TYPE_PARAM_FLOAT)
{
gfloat number = sokoke_key_file_get_double_default (key_file,
number = sokoke_key_file_get_double_default (key_file,
"settings", property,
G_PARAM_SPEC_FLOAT (pspec)->default_value, NULL);
g_object_set (settings, property, number, NULL);
}
else if (type == G_TYPE_PARAM_BOOLEAN)
{
gboolean boolean = sokoke_key_file_get_boolean_default (key_file,
boolean = sokoke_key_file_get_boolean_default (key_file,
"settings", property,
G_PARAM_SPEC_BOOLEAN (pspec)->default_value, NULL);
g_object_set (settings, property, boolean, NULL);
@ -167,15 +179,22 @@ settings_save_to_file (MidoriWebSettings* settings,
const gchar* filename,
GError** error)
{
GKeyFile* key_file = g_key_file_new ();
GObjectClass* class = G_OBJECT_GET_CLASS (settings);
GKeyFile* key_file;
GObjectClass* class;
guint i, n_properties;
GParamSpec** pspecs = g_object_class_list_properties (class, &n_properties);
GParamSpec** pspecs;
GParamSpec* pspec;
GType type;
const gchar* property;
key_file = g_key_file_new ();
class = G_OBJECT_GET_CLASS (settings);
pspecs = g_object_class_list_properties (class, &n_properties);
for (i = 0; i < n_properties; i++)
{
GParamSpec* pspec = pspecs[i];
GType type = G_PARAM_SPEC_TYPE (pspec);
const gchar* property = g_param_spec_get_name (pspec);
pspec = pspecs[i];
type = G_PARAM_SPEC_TYPE (pspec);
property = g_param_spec_get_name (pspec);
if (!(pspec->flags & G_PARAM_WRITABLE))
{
gchar* comment = g_strdup_printf ("# %s", property);
@ -226,25 +245,105 @@ settings_save_to_file (MidoriWebSettings* settings,
return saved;
}
int
main (int argc, char** argv)
static MidoriWebList*
search_engines_new_from_file (const gchar* filename,
GError** error)
{
MidoriStartup load_on_startup;
gchar* homepage;
MidoriWebList* search_engines;
GKeyFile* key_file;
gchar** engines;
guint i, j, n_properties;
MidoriWebItem* web_item;
GParamSpec** pspecs;
const gchar* property;
gchar* value;
locale_init ();
g_set_application_name (_("midori"));
search_engines = midori_web_list_new ();
key_file = g_key_file_new ();
g_key_file_load_from_file (key_file, filename,
G_KEY_FILE_KEEP_COMMENTS, error);
/*g_key_file_load_from_data_dirs(keyFile, sFilename, NULL
, G_KEY_FILE_KEEP_COMMENTS, error);*/
engines = g_key_file_get_groups (key_file, NULL);
for (i = 0; engines[i] != NULL; i++)
{
web_item = midori_web_item_new ();
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (web_item),
&n_properties);
for (j = 0; j < n_properties; j++)
{
property = g_param_spec_get_name (pspecs[j]);
value = g_key_file_get_string (key_file, engines[i],
property, NULL);
g_object_set (web_item, property, value, NULL);
g_free (value);
}
midori_web_list_add_item (search_engines, web_item);
}
g_strfreev (engines);
g_key_file_free (key_file);
return search_engines;
}
// Parse cli options
gboolean version = FALSE;
static gboolean
search_engines_save_to_file (MidoriWebList* search_engines,
const gchar* filename,
GError** error)
{
GKeyFile* key_file;
guint n, i, j, n_properties;
MidoriWebItem* web_item;
const gchar* name;
GParamSpec** pspecs;
const gchar* property;
gchar* value;
gboolean saved;
key_file = g_key_file_new ();
n = midori_web_list_get_length (search_engines);
for (i = 0; i < n; i++)
{
web_item = midori_web_list_get_nth_item (search_engines, i);
name = midori_web_item_get_name (web_item);
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (web_item),
&n_properties);
for (j = 0; j < n_properties; j++)
{
property = g_param_spec_get_name (pspecs[j]);
g_object_get (web_item, property, &value, NULL);
if (value)
g_key_file_set_string (key_file, name, property, value);
g_free (value);
}
}
saved = sokoke_key_file_save_to_file (key_file, filename, error);
g_key_file_free (key_file);
return saved;
}
int
main (int argc,
char** argv)
{
gboolean version;
GError* error;
GOptionEntry entries[] =
{
{ "version", 'v', 0, G_OPTION_ARG_NONE, &version,
N_("Display program version"), NULL },
{ NULL }
};
MidoriStartup load_on_startup;
gchar* homepage;
MidoriWebList* search_engines;
GError* error = NULL;
locale_init ();
g_set_application_name (_("midori"));
/* Parse cli options */
version = FALSE;
error = NULL;
if (!gtk_init_with_args (&argc, &argv, _("[URL]"), entries,
GETTEXT_PACKAGE, &error))
{
@ -273,7 +372,7 @@ main (int argc, char** argv)
return 0;
}
// Standalone gjs support
/* Standalone gjs support */
if (argc > 1 && argv[1] && g_str_has_suffix (argv[1], ".js"))
{
JSGlobalContextRef js_context = gjs_global_context_new ();
@ -286,7 +385,7 @@ main (int argc, char** argv)
return 1;
}
// Load configuration files
/* Load configuration files */
GString* error_messages = g_string_new (NULL);
gchar* config_path = g_build_filename (g_get_user_config_dir (),
PACKAGE_NAME, NULL);
@ -298,11 +397,11 @@ main (int argc, char** argv)
gtk_accel_map_load (config_file);
katze_assign (config_file, g_build_filename (config_path, "search", NULL));
error = NULL;
searchEngines = search_engines_new ();
if (!search_engines_from_file (&searchEngines, config_file, &error))
search_engines = search_engines_new_from_file (config_file, &error);
if (error)
{
// FIXME: We may have a "file empty" error, how do we recognize that?
/*if (error->code != G_FILE_ERROR_NOENT)
/* FIXME: We may have a "file empty" error, how do we recognize that?
if (error->code != G_FILE_ERROR_NOENT)
g_string_append_printf (error_messages,
_("The search engines couldn't be loaded. %s\n"),
error->message); */
@ -347,25 +446,26 @@ main (int argc, char** argv)
}
g_free (config_file);
// In case of errors
/* In case of errors */
if (error_messages->len)
{
GtkWidget* dialog = gtk_message_dialog_new(NULL
, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_NONE
, _("The following errors occured:"));
GtkWidget* dialog = gtk_message_dialog_new (
NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_NONE,
_("The following errors occured:"));
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
gtk_window_set_title (GTK_WINDOW (dialog), g_get_application_name ());
// FIXME: Use custom program icon
/* FIXME: Use custom program icon */
gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser");
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog)
, "%s", error_messages->str);
gtk_dialog_add_buttons(GTK_DIALOG(dialog)
, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL
, "_Ignore", GTK_RESPONSE_ACCEPT
, NULL);
gtk_message_dialog_format_secondary_text (
GTK_MESSAGE_DIALOG (dialog), "%s", error_messages->str);
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
"_Ignore", GTK_RESPONSE_ACCEPT,
NULL);
if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT)
{
search_engines_free(searchEngines);
g_object_unref (settings);
g_object_unref (search_engines);
katze_xbel_item_unref (bookmarks);
katze_xbel_item_unref (_session);
katze_xbel_item_unref (xbel_trash);
@ -378,8 +478,8 @@ main (int argc, char** argv)
}
g_string_free (error_messages, TRUE);
// TODO: Handle any number of separate uris from argv
// Open as many tabs as we have uris, seperated by pipes
/* TODO: Handle any number of separate uris from argv
Open as many tabs as we have uris, seperated by pipes */
gchar* uri = argc > 1 ? strtok (g_strdup (argv[1]), "|") : NULL;
while (uri != NULL)
{
@ -435,15 +535,15 @@ main (int argc, char** argv)
KatzeXbelItem* item = katze_xbel_folder_get_nth_item (_session, i);
midori_browser_add_xbel_item (browser, item);
}
// FIXME: Switch to the last active page
/* FIXME: Switch to the last active page */
KatzeXbelItem* item = katze_xbel_folder_get_nth_item (_session, 0);
if (!strcmp (katze_xbel_bookmark_get_href (item), ""))
midori_browser_activate_action (browser, "Location");
katze_xbel_item_unref (_session);
// Load extensions
/* Load extensions */
JSGlobalContextRef js_context = gjs_global_context_new ();
// FIXME: We want to honor system installed addons as well
/* FIXME: We want to honor system installed addons as well */
gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME,
"extensions", NULL);
GDir* addon_dir = g_dir_open (addon_path, 0, NULL);
@ -456,8 +556,8 @@ main (int argc, char** argv)
gchar* exception = NULL;
gjs_script_from_file (js_context, fullname, &exception);
if (exception)
// FIXME: Do we want to print this somewhere else?
// FIXME Convert the filename to UTF8
/* FIXME: Do we want to print this somewhere else? */
/* FIXME Convert the filename to UTF8 */
printf ("%s - Exception: %s\n", filename, exception);
g_free (fullname);
}
@ -468,18 +568,19 @@ main (int argc, char** argv)
JSGlobalContextRelease (js_context);
// Save configuration files
/* Save configuration files */
config_path = g_build_filename (g_get_user_config_dir(), PACKAGE_NAME,
NULL);
g_mkdir_with_parents (config_path, 0755);
config_file = g_build_filename (config_path, "search", NULL);
error = NULL;
if (!search_engines_to_file (searchEngines, config_file, &error))
if (!search_engines_save_to_file (search_engines, config_file, &error))
{
g_warning (_("The search engines couldn't be saved. %s"), error->message);
g_warning (_("The search engines couldn't be saved. %s"),
error->message);
g_error_free (error);
}
search_engines_free(searchEngines);
g_object_unref (search_engines);
g_free (config_file);
config_file = g_build_filename (config_path, "bookmarks.xbel", NULL);
error = NULL;

View file

@ -19,23 +19,22 @@
#include <glib/gi18n.h>
// FIXME: Remove these globals
/* FIXME: Remove these globals */
GList* searchEngines; // Items of type 'SearchEngine'
KatzeXbelItem* bookmarks;
// Custom stock items
/* Custom stock items
// We should distribute these
// Names should match with epiphany and/ or xdg spec
/* NOTE: Those uncommented were replaced with remotely related icons
in order to reduce the amount of warnings :D */
We should distribute these
Names should match with epiphany and/ or xdg spec
NOTE: Those uncommented were replaced with remotely related icons
in order to reduce the amount of warnings */
#define STOCK_BOOKMARK GTK_STOCK_FILE // "stock_bookmark" "bookmark-web"
#define STOCK_FORM_FILL GTK_STOCK_JUSTIFY_FILL // "insert-text" "form-fill"
#define STOCK_BOOKMARK GTK_STOCK_FILE /* "stock_bookmark" "bookmark-web" */
#define STOCK_FORM_FILL GTK_STOCK_JUSTIFY_FILL /* "insert-text" "form-fill" */
#define STOCK_NEWSFEED GTK_STOCK_INDEX
// We assume that these legacy icon names are usually present
/* We assume that these legacy icon names are usually present */
#define STOCK_BOOKMARK_ADD "stock_add-bookmark"
#define STOCK_HOMEPAGE GTK_STOCK_HOME
@ -51,7 +50,7 @@ KatzeXbelItem* bookmarks;
#define STOCK_USER_TRASH "gnome-stock-trash"
#define STOCK_WINDOW_NEW "stock_new-window"
// For backwards compatibility
/* For backwards compatibility */
#if !GTK_CHECK_VERSION(2, 10, 0)
#define GTK_STOCK_SELECT_ALL "gtk-select-all"

View file

@ -414,12 +414,12 @@ midori_web_view_populate_popup_cb (GtkWidget* web_view,
const gchar* uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view));
if (uri)
{
// TODO: bookmark link
/* TODO: bookmark link */
}
if (webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view)))
{
// TODO: view selection source
/* TODO: view selection source */
}
if (!uri && !webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view)))
@ -505,7 +505,7 @@ midori_web_view_destroy_cb (GtkWidget* widget,
static void
_midori_browser_will_quit (MidoriBrowser* browser)
{
// Nothing to do
/* Nothing to do */
}
static void
@ -843,7 +843,7 @@ _action_open_activate (GtkAction* action,
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_OPEN);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (browser));
// base the start folder on the current web view's uri if it is local
/* base the start folder on the current web view's uri if it is local */
GtkWidget* web_view = midori_browser_get_current_web_view (browser);
if (web_view)
g_object_get (web_view, "uri", &uri, NULL);
@ -1114,7 +1114,7 @@ static void
midori_browser_menu_trash_item_activate_cb (GtkWidget* menuitem,
MidoriBrowser* browser)
{
// Create a new web view with an uri which has been closed before
/* Create a new web view with an uri which has been closed before */
KatzeXbelItem* item = g_object_get_data (G_OBJECT (menuitem),
"KatzeXbelItem");
const gchar* uri = katze_xbel_bookmark_get_href (item);
@ -1139,7 +1139,7 @@ midori_browser_menu_trash_activate_cb (GtkWidget* widget,
const gchar* title = katze_xbel_item_get_title (item);
const gchar* uri = katze_xbel_bookmark_get_href (item);
menuitem = gtk_image_menu_item_new_with_label (title ? title : uri);
// FIXME: Get the real icon
/* FIXME: Get the real icon */
GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE,
GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
@ -1169,7 +1169,7 @@ static void
_action_preferences_activate (GtkAction* action,
MidoriBrowser* browser)
{
// Show the preferences dialog. Create it if necessary.
/* Show the preferences dialog. Create it if necessary. */
static GtkWidget* dialog = NULL;
if (GTK_IS_DIALOG (dialog))
gtk_window_present (GTK_WINDOW (dialog));
@ -1223,7 +1223,7 @@ _action_reload_stop_activate (GtkAction* action,
gchar* stock_id;
g_object_get (action, "stock-id", &stock_id, NULL);
GtkWidget* web_view = midori_browser_get_current_web_view (browser);
// Refresh or stop, depending on the stock id
/* Refresh or stop, depending on the stock id */
if (!strcmp (stock_id, GTK_STOCK_REFRESH))
{
/*GdkModifierType state = (GdkModifierType)0;
@ -1334,10 +1334,12 @@ 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, location_entry_search);
gchar* new_uri = sokoke_magic_uri (uri, NULL/*search_engines*/);
if (!new_uri)
new_uri = g_strdup (location_entry_search);
g_free (location_entry_search);
// TODO: Use new_uri intermediately when completion is better
/* TODO Completion should be generated from history, that is
/* TODO: Use new_uri intermediately when completion is better
Completion should be generated from history, that is
the uri as well as the title. */
sokoke_entry_append_completion (GTK_ENTRY (widget), uri);
GtkWidget* web_view = midori_browser_get_current_web_view (browser);
@ -1525,7 +1527,7 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
katze_xbel_bookmark_set_href (bookmark,
gtk_entry_get_text (GTK_ENTRY (entry_uri)));
// FIXME: We want to choose a folder
/* FIXME: We want to choose a folder */
if (new_bookmark)
{
katze_xbel_folder_append_item (bookmarks, bookmark);
@ -1537,8 +1539,8 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
katze_xbel_item_ref (bookmark);
}
// FIXME: update navigationbar
// FIXME: Update panel in other windows
/* FIXME: update navigationbar */
/* FIXME: Update panel in other windows */
}
gtk_widget_destroy (dialog);
}
@ -1697,7 +1699,7 @@ midori_browser_bookmarks_item_render_icon_cb (GtkTreeViewColumn* column,
return;
}
// TODO: Would it be better to not do this on every redraw?
/* TODO: Would it be better to not do this on every redraw? */
GdkPixbuf* pixbuf = NULL;
if (katze_xbel_item_is_bookmark (item))
pixbuf = gtk_widget_render_icon (treeview, STOCK_BOOKMARK,
@ -1746,12 +1748,12 @@ midori_browser_bookmark_menu_folder_activate_cb (GtkWidget* menuitem,
MidoriBrowser* browser)
{
GtkWidget* menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menuitem));
gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) gtk_widget_destroy, NULL);//...
gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) gtk_widget_destroy, NULL);
KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT (menuitem), "KatzeXbelItem");
_midori_browser_create_bookmark_menu (browser, folder, menu);
// Remove all menuitems when the menu is hidden.
// FIXME: We really *want* the line below, but it won't work like that
//g_signal_connect_after (menu, "hide", G_CALLBACK (gtk_container_foreach), gtk_widget_destroy);
/* Remove all menuitems when the menu is hidden.
FIXME: We really *want* the line below, but it won't work like that
g_signal_connect_after (menu, "hide", G_CALLBACK (gtk_container_foreach), gtk_widget_destroy); */
gtk_widget_show (menuitem);
}
@ -1763,9 +1765,9 @@ midori_browser_bookmarkbar_folder_activate_cb (GtkToolItem* toolitem,
KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data (
G_OBJECT (toolitem), "KatzeXbelItem");
_midori_browser_create_bookmark_menu (browser, folder, menu);
// Remove all menuitems when the menu is hidden.
// FIXME: We really *should* run the line below, but it won't work like that
/*g_signal_connect (menu, "hide", G_CALLBACK (gtk_container_foreach),
/* Remove all menuitems when the menu is hidden.
FIXME: We really *should* run the line below, but it won't work like that
g_signal_connect (menu, "hide", G_CALLBACK (gtk_container_foreach),
gtk_widget_destroy); */
sokoke_widget_popup (GTK_WIDGET (toolitem), GTK_MENU (menu),
NULL, SOKOKE_MENU_POSITION_LEFT);
@ -1800,7 +1802,7 @@ _midori_browser_create_bookmark_menu (MidoriBrowser* browser,
switch (katze_xbel_item_get_kind (item))
{
case KATZE_XBEL_ITEM_KIND_FOLDER:
// FIXME: what about katze_xbel_folder_is_folded?
/* FIXME: what about katze_xbel_folder_is_folded? */
menuitem = gtk_image_menu_item_new_with_label (title);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
gtk_image_new_from_stock (GTK_STOCK_DIRECTORY,
@ -1846,7 +1848,7 @@ static void
_action_manage_search_engines_activate (GtkAction* action,
MidoriBrowser* browser)
{
// Show the Manage search engines dialog. Create it if necessary.
/* Show the Manage search engines dialog. Create it if necessary. */
static GtkWidget* dialog;
if (GTK_IS_DIALOG (dialog))
gtk_window_present (GTK_WINDOW (dialog));
@ -1873,7 +1875,7 @@ _action_tab_next_activate (GtkAction* action,
{
MidoriBrowserPrivate* priv = browser->priv;
// Advance one tab or jump to the first one if we are at the last one
/* Advance one tab or jump to the first one if we are at the last one */
gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
if (n == gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)) - 1)
n = -1;
@ -1935,10 +1937,10 @@ static void
midori_browser_location_changed_cb (GtkWidget* widget,
MidoriBrowser* browser)
{
// Preserve changes to the uri
/*const gchar* newUri = gtk_entry_get_text(GTK_ENTRY(widget));
katze_xbel_bookmark_set_href(browser->sessionItem, newUri);*/
// FIXME: If we want this feature, this is the wrong approach
/* Preserve changes to the uri
const gchar* new_uri = gtk_entry_get_text (GTK_ENTRY (widget));
katze_xbel_bookmark_set_href(browser->sessionItem, new_uri);
FIXME: If we want this feature, this is the wrong approach */
}
static void
@ -1960,7 +1962,7 @@ _action_open_in_panel_activate (GtkAction* action,
GtkWidget* web_view = midori_browser_get_current_web_view (browser);
const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view));
// FIXME: Don't assign the uri here, update it properly while navigating
/* FIXME: Don't assign the uri here, update it properly while navigating */
g_object_set (priv->settings, "last-pageholder-uri", uri, NULL);
gint n = midori_panel_page_num (MIDORI_PANEL (priv->panel),
priv->panel_pageholder);
@ -2111,7 +2113,7 @@ _action_undo_tab_close_activate (GtkAction* action,
{
MidoriBrowserPrivate* priv = browser->priv;
// Reopen the most recent trash item
/* Reopen the most recent trash item */
KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, 0);
gint n = midori_browser_add_xbel_item (browser, item);
midori_browser_set_current_page (browser, n);
@ -2417,7 +2419,7 @@ midori_browser_destroy_cb (MidoriBrowser* browser)
{
MidoriBrowserPrivate* priv = browser->priv;
// Destroy tabs first, so widgets can still see window elements on destroy
/* Destroy tabs first, so widgets can still see window elements on destroy */
gtk_container_foreach (GTK_CONTAINER (priv->notebook),
(GtkCallback) gtk_widget_destroy, NULL);
}
@ -2485,7 +2487,7 @@ static const gchar* ui_markup =
"<menuitem action='Search'/>"
"<menuitem action='OpenInPageholder'/>"
"<menu action='Trash'>"
// Closed tabs shall be prepended here
/* Closed tabs shall be prepended here */
"<separator/>"
"<menuitem action='TrashEmpty'/>"
"</menu>"
@ -2499,18 +2501,18 @@ static const gchar* ui_markup =
"<menuitem action='BookmarkAdd'/>"
"<menuitem action='BookmarksManage'/>"
"<separator/>"
// Bookmarks shall be appended here
/* Bookmarks shall be appended here */
"</menu>"
"<menu action='Tools'>"
"<menuitem action='ManageSearchEngines'/>"
// Panel items shall be appended here
/* Panel items shall be appended here */
"</menu>"
"<menu action='Window'>"
"<menuitem action='TabPrevious'/>"
"<menuitem action='TabNext'/>"
"<menuitem action='TabOverview'/>"
"<separator/>"
// All open tabs shall be appended here
/* All open tabs shall be appended here */
"</menu>"
"<menu action='Help'>"
"<menuitem action='HelpContents'/>"
@ -2563,7 +2565,7 @@ midori_browser_init (MidoriBrowser* browser)
MidoriBrowserPrivate* priv = browser->priv;
// Setup the window metrics
/* Setup the window metrics */
g_signal_connect (browser, "realize",
G_CALLBACK (midori_browser_realize_cb), browser);
g_signal_connect (browser, "window-state-event",
@ -2578,7 +2580,7 @@ midori_browser_init (MidoriBrowser* browser)
gtk_container_add (GTK_CONTAINER (browser), vbox);
gtk_widget_show (vbox);
// Let us see some ui manager magic
/* Let us see some ui manager magic */
priv->action_group = gtk_action_group_new ("Browser");
gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE);
gtk_action_group_add_actions (priv->action_group,
@ -2593,14 +2595,14 @@ midori_browser_init (MidoriBrowser* browser)
GError* error = NULL;
if (!gtk_ui_manager_add_ui_from_string(ui_manager, ui_markup, -1, &error))
{
// TODO: Should this be a message dialog? When does this happen?
/* TODO: Should this be a message dialog? When does this happen? */
g_message ("User interface couldn't be created: %s", error->message);
g_error_free (error);
}
GtkAction* action;
// Make all actions except toplevel menus which lack a callback insensitive
// This will vanish once all actions are implemented
/* Make all actions except toplevel menus which lack a callback insensitive
This will vanish once all actions are implemented */
guint i;
for (i = 0; i < entries_n; i++)
{
@ -2616,9 +2618,9 @@ midori_browser_init (MidoriBrowser* browser)
gtk_action_set_sensitive (action, toggle_entries[i].callback != NULL);
}
//_action_set_active(browser, "Transferbar", config->toolbarTransfers);
/* _action_set_active(browser, "Transferbar", config->toolbarTransfers); */
// Create the menubar
/* Create the menubar */
priv->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar");
GtkWidget* menuitem = gtk_menu_item_new ();
gtk_widget_show (menuitem);
@ -2655,10 +2657,10 @@ midori_browser_init (MidoriBrowser* browser)
_action_set_sensitive (browser, "PrivateBrowsing", FALSE);
_action_set_sensitive (browser, "WorkOffline", FALSE);
// Create the navigationbar
/* Create the navigationbar */
priv->navigationbar = gtk_ui_manager_get_widget (
ui_manager, "/toolbar_navigation");
// FIXME: settings should be connected with screen changes
/* FIXME: settings should be connected with screen changes */
GtkSettings* gtk_settings = gtk_widget_get_settings (GTK_WIDGET (browser));
if (gtk_settings)
g_signal_connect (gtk_settings, "notify::gtk-toolbar-style",
@ -2671,7 +2673,7 @@ midori_browser_init (MidoriBrowser* browser)
priv->button_homepage = gtk_ui_manager_get_widget (
ui_manager, "/toolbar_navigation/Homepage");
// Location
/* Location */
priv->location = sexy_icon_entry_new ();
sokoke_entry_setup_completion (GTK_ENTRY (priv->location));
priv->location_icon = gtk_image_new ();
@ -2691,13 +2693,13 @@ midori_browser_init (MidoriBrowser* browser)
gtk_container_add (GTK_CONTAINER(toolitem), priv->location);
gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1);
// Search
/* Search */
priv->search = sexy_icon_entry_new ();
sexy_icon_entry_set_icon_highlight (SEXY_ICON_ENTRY (priv->search),
SEXY_ICON_ENTRY_PRIMARY, TRUE);
// TODO: Make this actively resizable or enlarge to fit contents?
// FIXME: The interface is somewhat awkward and ought to be rethought
// TODO: Display "show in context menu" search engines as "completion actions"
/* 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",
@ -2729,7 +2731,7 @@ midori_browser_init (MidoriBrowser* browser)
gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar),
GTK_TOOL_ITEM (priv->button_fullscreen), -1);
// Bookmarkbar
/* Bookmarkbar */
priv->bookmarkbar = gtk_toolbar_new ();
gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->bookmarkbar),
GTK_ICON_SIZE_MENU);
@ -2777,12 +2779,12 @@ midori_browser_init (MidoriBrowser* browser)
sokoke_container_show_children (GTK_CONTAINER (priv->bookmarkbar));
gtk_box_pack_start (GTK_BOX (vbox), priv->bookmarkbar, FALSE, FALSE, 0);
// Superuser warning
/* Superuser warning */
GtkWidget* hbox;
if ((hbox = sokoke_superuser_warning_new ()))
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
// Create the panel
/* Create the panel */
GtkWidget* hpaned = gtk_hpaned_new ();
g_signal_connect (hpaned, "notify::position",
G_CALLBACK (midori_panel_notify_position_cb),
@ -2797,7 +2799,7 @@ midori_browser_init (MidoriBrowser* browser)
G_CALLBACK (midori_panel_close_cb), browser);
gtk_paned_pack1 (GTK_PANED (hpaned), priv->panel, FALSE, FALSE);
// Bookmarks
/* Bookmarks */
GtkWidget* box = gtk_vbox_new (FALSE, 0);
GtkTreeViewColumn* column;
GtkCellRenderer* renderer_text;
@ -2844,14 +2846,14 @@ midori_browser_init (MidoriBrowser* browser)
box, toolbar,
"vcard", _("Bookmarks"));
// Transfers
/* Transfers */
GtkWidget* panel = midori_web_view_new ();
gtk_widget_show (panel);
midori_panel_append_page (MIDORI_PANEL (priv->panel),
panel, NULL,
"package", _("Transfers"));
// Console
/* Console */
priv->panel_console = midori_console_new ();
gtk_widget_show (priv->panel_console);
toolbar = midori_console_get_toolbar (MIDORI_CONSOLE (priv->panel_console));
@ -2860,14 +2862,14 @@ midori_browser_init (MidoriBrowser* browser)
priv->panel_console, toolbar,
"terminal", _("Console"));
// History
/* History */
panel = midori_web_view_new ();
gtk_widget_show (panel);
midori_panel_append_page (MIDORI_PANEL (priv->panel),
panel, NULL,
"document-open-recent", _("History"));
// Pageholder
/* Pageholder */
priv->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW,
"uri", "",
NULL);
@ -2876,7 +2878,7 @@ midori_browser_init (MidoriBrowser* browser)
priv->panel_pageholder, NULL,
GTK_STOCK_CONVERT, _("Pageholder"));
// Userscripts
/* Userscripts */
panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_SCRIPTS);
gtk_widget_show (panel);
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
@ -2884,7 +2886,7 @@ midori_browser_init (MidoriBrowser* browser)
midori_panel_append_page (MIDORI_PANEL (priv->panel),
panel, toolbar,
"", _("Userscripts"));
// Userstyles
/* Userstyles */
/*panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_STYLES);
gtk_widget_show (panel);
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
@ -2893,7 +2895,7 @@ midori_browser_init (MidoriBrowser* browser)
panel, toolbar,
"", _("Userstyles"));*/
// Notebook, containing all web_views
/* Notebook, containing all web_views */
priv->notebook = gtk_notebook_new ();
gtk_notebook_set_scrollable (GTK_NOTEBOOK (priv->notebook), TRUE);
gtk_paned_pack2 (GTK_PANED (hpaned), priv->notebook, FALSE, FALSE);
@ -2902,7 +2904,7 @@ midori_browser_init (MidoriBrowser* browser)
browser);
gtk_widget_show (priv->notebook);
// Incremental findbar
/* Incremental findbar */
priv->find = gtk_toolbar_new ();
gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->find), GTK_ICON_SIZE_MENU);
gtk_toolbar_set_style (GTK_TOOLBAR (priv->find), GTK_TOOLBAR_BOTH_HORIZ);
@ -2959,17 +2961,17 @@ midori_browser_init (MidoriBrowser* browser)
sokoke_container_show_children (GTK_CONTAINER (priv->find));
gtk_box_pack_start (GTK_BOX (vbox), priv->find, FALSE, FALSE, 0);
// Statusbar
// TODO: fix children overlapping statusbar border
/* Statusbar */
/* FIXME: children are overlapping the statusbar border */
priv->statusbar = gtk_statusbar_new ();
gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0);
priv->progressbar = gtk_progress_bar_new ();
// Setting the progressbar's height to 1 makes it fit in the statusbar
/* Setting the progressbar's height to 1 makes it fit in the statusbar */
gtk_widget_set_size_request (priv->progressbar, -1, 1);
gtk_box_pack_start (GTK_BOX (priv->statusbar), priv->progressbar,
FALSE, FALSE, 3);
// Extensions
/* Extensions */
panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_EXTENSIONS);
gtk_widget_show (panel);
toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
@ -3176,17 +3178,17 @@ midori_browser_set_property (GObject* object,
_midori_browser_update_settings (browser);
g_signal_connect (priv->settings, "notify",
G_CALLBACK (midori_browser_settings_notify), browser);
// FIXME: Assigning settings must be conditional, if web view or not
// FIXME: Assign settings only if the same settings object was used
/* FIXME: Assigning settings must be conditional, if web view or not */
/* FIXME: Assign settings only if the same settings object was used */
gtk_container_foreach (GTK_CONTAINER (priv->notebook),
(GtkCallback) midori_web_view_set_settings,
priv->settings);
break;
case PROP_TRASH:
; // FIXME: Disconnect handlers
; /* FIXME: Disconnect handlers */
katze_object_assign (priv->trash, g_value_get_object (value));
g_object_ref (priv->trash);
// FIXME: Connect to updates
/* FIXME: Connect to updates */
_midori_browser_update_actions (browser);
break;
default:
@ -3382,7 +3384,7 @@ midori_browser_remove_tab (MidoriBrowser* browser,
GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget);
gtk_container_remove (GTK_CONTAINER (priv->notebook), scrolled);
// FIXME: Remove the menuitem if this is a web view
/* FIXME: Remove the menuitem if this is a web view */
}
/**
@ -3602,7 +3604,7 @@ midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser)
if (!priv->proxy_xbel_folder)
{
priv->proxy_xbel_folder = katze_xbel_folder_new ();
// FIXME: Fill in xbel items of all present web views
/* FIXME: Fill in xbel items of all present web views */
}
return priv->proxy_xbel_folder;
}

194
midori/midori-weblist.c Normal file
View file

@ -0,0 +1,194 @@
/*
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.
*/
#include "midori-weblist.h"
#include <glib/gi18n.h>
#include <string.h>
struct _MidoriWebList
{
GObject parent_instance;
GList* items;
};
G_DEFINE_TYPE (MidoriWebList, midori_web_list, G_TYPE_OBJECT)
enum {
ADD_ITEM,
REMOVE_ITEM,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static void
midori_web_list_finalize (GObject* object);
static void
midori_web_list_class_init (MidoriWebListClass* class)
{
signals[ADD_ITEM] = g_signal_new (
"add-item",
G_TYPE_FROM_CLASS (class),
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
G_STRUCT_OFFSET (MidoriWebListClass, add_item),
0,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MIDORI_TYPE_WEB_ITEM);
signals[REMOVE_ITEM] = g_signal_new (
"remove-item",
G_TYPE_FROM_CLASS (class),
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
G_STRUCT_OFFSET (MidoriWebListClass, remove_item),
0,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MIDORI_TYPE_WEB_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;
}
static void
midori_web_list_init (MidoriWebList* web_list)
{
web_list->items = NULL;
}
static void
midori_web_list_finalize (GObject* object)
{
MidoriWebList* web_list = MIDORI_WEB_LIST (object);
g_list_foreach (web_list->items, (GFunc)g_object_unref, NULL);
g_list_free (web_list->items);
G_OBJECT_CLASS (midori_web_list_parent_class)->finalize (object);
}
/**
* midori_web_list_new:
*
* Creates a new #MidoriWebList.
*
* Return value: a new #MidoriWebList
**/
MidoriWebList*
midori_web_list_new (void)
{
MidoriWebList* web_list = g_object_new (MIDORI_TYPE_WEB_LIST,
NULL);
return web_list;
}
/**
* midori_web_list_add_item:
* @web_list: a #MidoriWebList
* @web_item: a #MidoriWebItem
*
* Adds an item to the list.
**/
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);
}
/**
* midori_web_list_add_item:
* @web_list: a #MidoriWebList
* @web_item: a #MidoriWebItem
*
* Removes an item from the list.
**/
void
midori_web_list_remove_item (MidoriWebList* web_list,
MidoriWebItem* web_item)
{
web_list->items = g_list_remove (web_list->items, web_item);
}
/**
* midori_web_list_get_nth_item:
* @web_list: a #MidoriWebList
* @n: an index in the list
*
* Retrieves the item in @web_list at the index @n.
*
* Return value: an item, or %NULL
**/
MidoriWebItem*
midori_web_list_get_nth_item (MidoriWebList* web_list,
guint n)
{
g_return_val_if_fail (MIDORI_IS_WEB_LIST (web_list), 0);
return g_list_nth_data (web_list->items, n);
}
/**
* midori_web_list_find_token:
* @web_list: a #MidoriWebList
* @token: a token string
*
* Looks up an item in the list which has the specified token.
*
* Note that @token is by definition unique to one item.
*
* Return value: an item, or %NULL
**/
MidoriWebItem*
midori_web_list_find_token (MidoriWebList* web_list,
const gchar* token)
{
guint n, i;
MidoriWebItem* web_item;
g_return_val_if_fail (MIDORI_IS_WEB_LIST (web_list), NULL);
n = g_list_length (web_list->items);
for (i = 0; i < n; i++)
{
web_item = (MidoriWebItem*)g_list_nth_data (web_list->items, i);
if (!strcmp (midori_web_item_get_token (web_item), token))
return web_item;
}
return NULL;
}
/**
* midori_web_list_get_length:
* @web_list: a #MidoriWebList
*
* Retrieves the number of items in @web_list.
*
* Return value: the length of the list
**/
guint
midori_web_list_get_length (MidoriWebList* web_list)
{
g_return_val_if_fail (MIDORI_IS_WEB_LIST (web_list), 0);
return g_list_length (web_list->items);
}

75
midori/midori-weblist.h Normal file
View file

@ -0,0 +1,75 @@
/*
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_WEB_LIST_H__
#define __MIDORI_WEB_LIST_H__
#include "midori-webitem.h"
G_BEGIN_DECLS
#define MIDORI_TYPE_WEB_LIST \
(midori_web_list_get_type ())
#define MIDORI_WEB_LIST(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_LIST, MidoriWebList))
#define MIDORI_WEB_LIST_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_LIST, MidoriWebListClass))
#define MIDORI_IS_WEB_LIST(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_LIST))
#define MIDORI_IS_WEB_LIST_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_LIST))
#define MIDORI_WEB_LIST_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_LIST, MidoriWebListClass))
typedef struct _MidoriWebList MidoriWebList;
typedef struct _MidoriWebListClass MidoriWebListClass;
struct _MidoriWebListClass
{
GObjectClass parent_class;
/* Signals */
void
(*add_item) (MidoriWebList* web_list,
MidoriWebItem* web_item);
void
(*remove_item) (MidoriWebList* web_list,
MidoriWebItem* web_item);
};
GType
midori_web_list_get_type (void);
MidoriWebList*
midori_web_list_new (void);
void
midori_web_list_add_item (MidoriWebList* web_list,
MidoriWebItem* web_item);
void
midori_web_list_remove_item (MidoriWebList* web_list,
MidoriWebItem* web_item);
MidoriWebItem*
midori_web_list_get_nth_item (MidoriWebList* web_list,
guint n);
MidoriWebItem*
midori_web_list_find_token (MidoriWebList* web_list,
const gchar* token);
guint
midori_web_list_get_length (MidoriWebList* web_list);
G_END_DECLS
#endif /* __MIDORI_WEB_LIST_H__ */

View file

@ -1,95 +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 "search.h"
#include "midori-webitem.h"
#include "sokoke.h"
GList* search_engines_new(void)
{
return NULL;
}
void search_engines_free(GList* searchEngines)
{
g_list_foreach(searchEngines, (GFunc)g_object_unref, NULL);
g_list_free(searchEngines);
}
gboolean search_engines_from_file(GList** searchEngines, const gchar* filename
, GError** error)
{
g_return_val_if_fail(!g_list_nth(*searchEngines, 0), FALSE);
GKeyFile* keyFile = g_key_file_new();
g_key_file_load_from_file(keyFile, filename, G_KEY_FILE_KEEP_COMMENTS, error);
/*g_key_file_load_from_data_dirs(keyFile, sFilename, NULL
, G_KEY_FILE_KEEP_COMMENTS, error);*/
gchar** engines = g_key_file_get_groups(keyFile, NULL);
guint i;
for(i = 0; engines[i] != NULL; i++)
{
MidoriWebItem* web_item = midori_web_item_new ();
guint j, n_properties;
GParamSpec** pspecs = g_object_class_list_properties (
G_OBJECT_GET_CLASS (web_item), &n_properties);
for (j = 0; j < n_properties; j++)
{
const gchar* property = g_param_spec_get_name (pspecs[j]);
gchar* value = g_key_file_get_string (keyFile, engines[i],
property, NULL);
g_object_set (web_item, property, value, NULL);
g_free (value);
}
*searchEngines = g_list_prepend(*searchEngines, web_item);
}
*searchEngines = g_list_reverse(*searchEngines);
g_strfreev(engines);
g_key_file_free(keyFile);
return !(error && *error);
}
static void key_file_set_string(GKeyFile* keyFile, const gchar* group
, const gchar* key, const gchar* string)
{
g_return_if_fail(group);
if(string)
g_key_file_set_string(keyFile, group, key, string);
}
gboolean search_engines_to_file(GList* searchEngines, const gchar* filename
, GError** error)
{
GKeyFile* keyFile = g_key_file_new();
guint n = g_list_length(searchEngines);
guint i;
for(i = 0; i < n; i++)
{
MidoriWebItem* web_item = (MidoriWebItem*)g_list_nth_data(searchEngines, i);
const gchar* name = midori_web_item_get_name (web_item);
guint j, n_properties;
GParamSpec** pspecs = g_object_class_list_properties (
G_OBJECT_GET_CLASS (web_item), &n_properties);
for (j = 0; j < n_properties; j++)
{
const gchar* property = g_param_spec_get_name (pspecs[j]);
gchar* value;
g_object_get (web_item, property, &value, NULL);
key_file_set_string (keyFile, name, property, value);
g_free (value);
}
}
gboolean bSaved = sokoke_key_file_save_to_file(keyFile, filename, error);
g_key_file_free(keyFile);
return bSaved;
}

View file

@ -1,30 +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 __SEARCH_H__
#define __SEARCH_H__ 1
#include <glib.h>
#include <glib-object.h>
GList*
search_engines_new(void);
void
search_engines_free(GList*);
gboolean
search_engines_from_file(GList**, const gchar*, GError**);
gboolean
search_engines_to_file(GList*, const gchar*, GError**);
#endif /* !__SEARCH_H__ */

View file

@ -25,49 +25,56 @@
#include <glib/gprintf.h>
gchar*
sokoke_magic_uri (const gchar* uri, const gchar* default_search_uri)
sokoke_magic_uri (const gchar* uri,
MidoriWebList* search_engines)
{
// Add file:// if we have a local path
g_return_val_if_fail (uri, NULL);
if (search_engines)
{
g_return_val_if_fail (MIDORI_IS_WEB_LIST (search_engines), NULL);
}
gchar* current_dir;
gchar* result;
gchar* search;
const gchar* search_uri;
gchar** parts;
MidoriWebItem* web_item;
/* Add file:// if we have a local path */
if (g_path_is_absolute (uri))
return g_strconcat ("file://", uri, NULL);
// Construct an absolute path if the file is relative
if (g_file_test (uri, G_FILE_TEST_EXISTS) && g_file_test (uri, G_FILE_TEST_IS_REGULAR))
/* Construct an absolute path if the file is relative */
if (g_file_test (uri, G_FILE_TEST_EXISTS)
&& g_file_test (uri, G_FILE_TEST_IS_REGULAR))
{
gchar* current_dir = g_get_current_dir ();
gchar* result = g_strconcat ("file://", current_dir, G_DIR_SEPARATOR_S, uri, NULL);
current_dir = g_get_current_dir ();
result = g_strconcat ("file://", current_dir,
G_DIR_SEPARATOR_S, uri, NULL);
g_free (current_dir);
return result;
}
// Do we need to add a protocol?
/* Do we need to add a protocol? */
if (!strstr (uri, "://"))
{
// Do we have a domain, ip address or localhost?
/* Do we have a domain, ip address or localhost? */
if (strchr (uri, '.') != NULL || !strcmp (uri, "localhost"))
return g_strconcat ("http://", uri, NULL);
// We don't want to search? So return early.
if (!default_search_uri)
/* We don't want to search? So return early. */
if (!search_engines)
return g_strdup (uri);
gchar* search;
const gchar* search_uri = NULL;
// Do we have a keyword and a string?
gchar** parts = g_strsplit (uri, " ", 2);
search = NULL;
search_uri = NULL;
/* Do we have a keyword and a string? */
parts = g_strsplit (uri, " ", 2);
if (parts[0] && parts[1])
{
guint n = g_list_length (searchEngines);
guint i;
for (i = 0; i < n; i++)
{
MidoriWebItem* web_item = (MidoriWebItem*)g_list_nth_data (
searchEngines, i);
if (!strcmp (midori_web_item_get_token (web_item), parts[0]))
web_item = midori_web_list_find_token (search_engines, parts[0]);
if (web_item)
search_uri = midori_web_item_get_uri (web_item);
}
if (search_uri)
search = g_strdup_printf (search_uri, parts[1]);
}
// We only have a word or there is no matching keyword, so search for it
if (!search_uri)
search = g_strdup_printf (default_search_uri, uri);
return search;
}
return g_strdup (uri);
@ -84,7 +91,8 @@ sokoke_entry_setup_completion (GtkEntry* entry)
gtk_entry_completion_set_text_column (completion, 0);
gtk_entry_completion_set_minimum_key_length (completion, 3);
gtk_entry_set_completion (entry, completion);
gtk_entry_completion_set_popup_completion (completion, FALSE); //...
/* FIXME: Completion doesn't work well, so it's disabled */
gtk_entry_completion_set_popup_completion (completion, FALSE);
}
void
@ -101,8 +109,8 @@ void
sokoke_combo_box_add_strings (GtkComboBox* combobox,
const gchar* label_first, ...)
{
// Add a number of strings to a combobox, terminated with NULL
// This works only for text comboboxes
/* Add a number of strings to a combobox, terminated with NULL
This works only for text comboboxes */
va_list args;
va_start (args, label_first);
@ -115,7 +123,7 @@ sokoke_combo_box_add_strings (GtkComboBox* combobox,
void sokoke_widget_set_visible (GtkWidget* widget, gboolean visible)
{
// Show or hide the widget
/* Show or hide the widget */
if (visible)
gtk_widget_show (widget);
else
@ -125,7 +133,7 @@ void sokoke_widget_set_visible (GtkWidget* widget, gboolean visible)
void
sokoke_container_show_children (GtkContainer* container)
{
// Show every child but not the container itself
/* Show every child but not the container itself */
gtk_container_foreach (container, (GtkCallback)(gtk_widget_show_all), NULL);
}
@ -149,7 +157,7 @@ sokoke_widget_popup_position_menu (GtkMenu* menu,
SokokePopupInfo* info = user_data;
GtkWidget* widget = info->widget;
// Retrieve size and position of both widget and menu
/* Retrieve size and position of both widget and menu */
if (GTK_WIDGET_NO_WINDOW (widget))
{
gdk_window_get_position (widget->window, &wx, &wy);
@ -161,11 +169,11 @@ sokoke_widget_popup_position_menu (GtkMenu* menu,
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
gtk_widget_size_request (widget, &widget_req);
menu_width = menu_req.width;
gint widget_height = widget_req.height; // Better than allocation.height
gint widget_height = widget_req.height; /* Better than allocation.height */
// Calculate menu position
/* Calculate menu position */
if (info->position == SOKOKE_MENU_POSITION_CURSOR)
; // Do nothing?
; /* Do nothing? */
else if (info->position == SOKOKE_MENU_POSITION_RIGHT)
{
*x = wx + widget->allocation.width - menu_width;
@ -225,7 +233,7 @@ sokoke_get_desktop (void)
static SokokeDesktop desktop = SOKOKE_DESKTOP_UNTESTED;
if (G_UNLIKELY (desktop == SOKOKE_DESKTOP_UNTESTED))
{
// Are we running in Xfce?
/* Are we running in Xfce? */
gint result; gchar* out; gchar* err;
gboolean success = g_spawn_command_line_sync (
"xprop -root _DT_SAVE_MODE | grep -q xfce4",
@ -243,8 +251,8 @@ GtkWidget*
sokoke_xfce_header_new (const gchar* icon,
const gchar* title)
{
// Create an xfce header with icon and title
// This returns NULL if the desktop is not xfce
/* Create an xfce header with icon and title
This returns NULL if the desktop is not xfce */
if (sokoke_get_desktop () == SOKOKE_DESKTOP_XFCE)
{
GtkWidget* entry = gtk_entry_new ();
@ -274,10 +282,10 @@ sokoke_xfce_header_new (const gchar* icon,
GtkWidget*
sokoke_superuser_warning_new (void)
{
// Create a horizontal bar with a security warning
// This returns NULL if the user is no superuser
/* Create a horizontal bar with a security warning
This returns NULL if the user is no superuser */
#ifdef HAVE_UNISTD_H
if (G_UNLIKELY (!geteuid ())) // effective superuser?
if (G_UNLIKELY (!geteuid ())) /* effective superuser? */
{
GtkWidget* hbox = gtk_event_box_new ();
gtk_widget_modify_bg (hbox, GTK_STATE_NORMAL,
@ -299,7 +307,7 @@ sokoke_superuser_warning_new (void)
GtkWidget*
sokoke_hig_frame_new (const gchar* title)
{
// Create a frame with no actual frame but a bold label and indentation
/* Create a frame with no actual frame but a bold label and indentation */
GtkWidget* frame = gtk_frame_new (NULL);
gchar* title_bold = g_strdup_printf ("<b>%s</b>", title);
GtkWidget* label = gtk_label_new (NULL);
@ -314,8 +322,8 @@ void
sokoke_widget_set_pango_font_style (GtkWidget* widget,
PangoStyle style)
{
// Conveniently change the pango font style
// For some reason we need to reset if we actually want the normal style
/* Conveniently change the pango font style
For some reason we need to reset if we actually want the normal style */
if (style == PANGO_STYLE_NORMAL)
gtk_widget_modify_font (widget, NULL);
else
@ -368,7 +376,7 @@ void
sokoke_entry_set_default_text (GtkEntry* entry,
const gchar* default_text)
{
// Note: The default text initially overwrites any previous text
/* Note: The default text initially overwrites any previous text */
gchar* old_value = g_object_get_data (G_OBJECT (entry),
"sokoke_default_text");
if (!old_value)

View file

@ -12,14 +12,16 @@
#ifndef __SOKOKE_H__
#define __SOKOKE_H__ 1
#include "midori-weblist.h"
#include <gtk/gtk.h>
// Many themes need this hack for small toolbars to work
/* Many themes need this hack for small toolbars to work */
#define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON
gchar*
sokoke_magic_uri (const gchar* uri,
const gchar* search);
MidoriWebList* search_engines);
void
sokoke_entry_setup_completion (GtkEntry* entry);

View file

@ -29,7 +29,7 @@ load_web_icon (const gchar* icon, GtkIconSize size, GtkWidget* widget)
GdkPixbuf* pixbuf = NULL;
if (icon && *icon)
{
// TODO: We want to allow http as well, maybe also base64?
/* 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;
@ -57,18 +57,20 @@ load_web_icon (const gchar* icon, GtkIconSize size, GtkWidget* widget)
void update_searchEngine(guint index, GtkWidget* search)
{
guint n = g_list_length(searchEngines);
// Display a default icon in case we have no engines
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
/* Change the icon and default text according to the chosen engine */
else
{
// Reset in case the index is out of range
/* Reset in case the index is out of range */
if(index >= n)
index = 0;
MidoriWebItem* web_item = (MidoriWebItem*)g_list_nth_data (searchEngines, index);
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)
@ -76,7 +78,7 @@ void update_searchEngine(guint index, GtkWidget* search)
g_object_unref(pixbuf);
sokoke_entry_set_default_text (GTK_ENTRY (search),
midori_web_item_get_name (web_item));
// config->searchEngine = index;
/* config->searchEngine = index; */
}
}
@ -89,15 +91,17 @@ void on_webSearch_engine_activate(GtkWidget* widget, MidoriBrowser* browser)
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 = g_list_length(searchEngines);
guint n = midori_web_list_get_length (search_engines);
GtkWidget* menuitem;
MidoriWebItem* web_item;
if(n)
{
guint i;
for(i = 0; i < n; i++)
{
MidoriWebItem* web_item = (MidoriWebItem*)g_list_nth_data (searchEngines, 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),
@ -139,7 +143,7 @@ static void on_webSearch_engines_render_icon(GtkTreeViewColumn* column
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?
/* TODO: Would it be better to not do this on every redraw? */
const gchar* icon = midori_web_item_get_icon (web_item);
if (icon)
{
@ -185,6 +189,7 @@ const gchar* STR_NON_NULL(const gchar* 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)
@ -304,7 +309,7 @@ static void webSearch_editEngine_dialog_new(gboolean newEngine, CWebSearch* webS
if(newEngine)
{
searchEngines = g_list_append(searchEngines, web_item);
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);
}
@ -327,6 +332,7 @@ static void on_webSearch_edit(GtkWidget* widget, CWebSearch* 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;
@ -335,14 +341,15 @@ static void on_webSearch_remove(GtkWidget* widget, CWebSearch* webSearch)
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);
searchEngines = g_list_remove (searchEngines, web_item);
//update_searchEngine(config->searchEngine, webSearch->browser);
webSearch_toggle_edit_buttons(g_list_nth(searchEngines, 0) != NULL, webSearch);
// FIXME: we want to allow undo of some kind
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)
@ -353,16 +360,16 @@ GtkWidget* webSearch_manageSearchEngines_dialog_new(MidoriBrowser* browser)
, GTK_RESPONSE_CLOSE
, NULL);
gtk_window_set_icon_name(GTK_WINDOW(dialog), GTK_STOCK_PROPERTIES);
// TODO: Implement some kind of help function
/* TODO: Implement some kind of help function */
gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog)
, GTK_RESPONSE_HELP, FALSE); //...
, GTK_RESPONSE_HELP, FALSE);
gint iWidth, iHeight;
sokoke_widget_get_text_size(dialog, "M", &iWidth, &iHeight);
gtk_window_set_default_size(GTK_WINDOW(dialog), iWidth * 45, -1);
g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog);
// TODO: Do we want tooltips for explainations or can we omit that?
// TODO: We need mnemonics
// TODO: Take multiple windows into account when applying changes
/* 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)))
@ -391,11 +398,11 @@ GtkWidget* webSearch_manageSearchEngines_dialog_new(MidoriBrowser* browser)
gtk_container_add(GTK_CONTAINER(scrolled), treeview);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 5);
guint n = g_list_length(searchEngines);
guint n = midori_web_list_get_length (search_engines);
guint i;
for(i = 0; i < n; i++)
{
MidoriWebItem* web_item = (MidoriWebItem*)g_list_nth_data (searchEngines, 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);
}
@ -418,13 +425,13 @@ GtkWidget* webSearch_manageSearchEngines_dialog_new(MidoriBrowser* browser)
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
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_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_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);
@ -440,10 +447,10 @@ gboolean on_webSearch_key_down(GtkWidget* widget, GdkEventKey* event, MidoriBrow
switch(event->keyval)
{
case GDK_Up:
//update_searchEngine(config->searchEngine - 1, browser);
/* update_searchEngine(config->searchEngine - 1, browser); */
return TRUE;
case GDK_Down:
//update_searchEngine(config->searchEngine + 1, browser);
/* update_searchEngine(config->searchEngine + 1, browser); */
return TRUE;
}
return FALSE;
@ -452,21 +459,22 @@ gboolean on_webSearch_key_down(GtkWidget* widget, GdkEventKey* event, MidoriBrow
gboolean on_webSearch_scroll(GtkWidget* webView, GdkEventScroll* event, MidoriBrowser* browser)
{
if(event->direction == GDK_SCROLL_DOWN)
;//update_searchEngine(config->searchEngine + 1, browser);
; /* update_searchEngine(config->searchEngine + 1, browser); */
else if(event->direction == GDK_SCROLL_UP)
;//update_searchEngine(config->searchEngine - 1, browser);
; /* 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 = (MidoriWebItem*)g_list_nth_data (searchEngines, 0/*config->searchEngine*/);
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;
else /* The location search is our fallback */
url = ""; /* config->locationSearch; */
gchar* search;
if(strstr(url, "%s"))
search = g_strdup_printf(url, keywords);

View file

@ -18,8 +18,6 @@
#include <libsexy/sexy.h>
#include <webkit/webkit.h>
// -- Types
typedef struct
{
MidoriBrowser* browser;
@ -35,8 +33,6 @@ enum
ENGINES_COL_N
};
// -- Declarations
void
update_searchEngine(guint, GtkWidget*);

View file

@ -2,6 +2,8 @@
midori.desktop.in
midori/main.c
midori/midori-app.c
midori/midori-addons.c
midori/midori-console.c
midori/midori-browser.c
midori/midori-panel.c
@ -9,9 +11,11 @@ midori/midori-trash.c
midori/midori-websettings.c
midori/midori-webview.c
midori/midori-preferences.c
midori/search.c
midori/midori-webitem.c
midori/midori-weblist.c
midori/sokoke.c
midori/webSearch.c
midori/gjs.c
katze/katze-throbber.c
katze/katze-utils.c
katze/katze-xbel.c

View file

@ -21,6 +21,7 @@ blddir = '_build_'
def configure (conf):
conf.check_tool ('compiler_cc')
if not Params.g_options.disable_nls:
conf.check_tool ('intltool')
if conf.env['INTLTOOL'] and conf.env['POCOM']:
@ -53,6 +54,7 @@ def configure (conf):
conf.define ('GETTEXT_PACKAGE', APPNAME)
conf.write_config_header ('config.h')
conf.env['CCFLAGS'] += ['-DHAVE_CONFIG_H']
def set_options (opt):
opt.tool_options ('compiler_cc')