/*
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
+ Copyright (C) 2008 Dale Whittaker <dayul@users.sf.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
#include <gtk/gtk.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
+#include <sqlite3.h>
#if ENABLE_NLS
#include <libintl.h>
#endif
+#define MIDORI_HISTORY_ERROR g_quark_from_string("MIDORI_HISTORY_ERROR")
+
+typedef enum
+{
+ MIDORI_HISTORY_ERROR_DB_OPEN, /* Error opening the database file */
+ MIDORI_HISTORY_ERROR_EXEC_SQL, /* Error executing SQL statement */
+
+} MidoriHistoryError;
+
static void
stock_items_init (void)
{
return TRUE;
}
+/* Open database 'dbname' */
+static sqlite3*
+db_open (const char* dbname,
+ GError** error)
+{
+ sqlite3* db;
+
+ if (sqlite3_open (dbname, &db))
+ {
+ if (error)
+ {
+ *error = g_error_new (MIDORI_HISTORY_ERROR,
+ MIDORI_HISTORY_ERROR_DB_OPEN,
+ _("Error opening database: %s\n"),
+ sqlite3_errmsg (db));
+ }
+ sqlite3_close (db);
+ return NULL;
+ }
+ return (db);
+}
+
+/* Close database 'db' */
+static void
+db_close (sqlite3* db)
+{
+ sqlite3_close (db);
+}
+
+/* Execute an SQL statement and run 'callback' on the result data */
+static gboolean
+db_exec_callback (sqlite3* db,
+ const char* sqlcmd,
+ int (*callback)(void*, int, char**, char**),
+ void* cbarg,
+ GError** error)
+{
+ char* errmsg;
+
+ if (sqlite3_exec (db, sqlcmd, callback, cbarg, &errmsg) != SQLITE_OK)
+ {
+ if (error)
+ {
+ *error = g_error_new (MIDORI_HISTORY_ERROR,
+ MIDORI_HISTORY_ERROR_EXEC_SQL,
+ _("Error opening database: %s\n"),
+ errmsg);
+ }
+ sqlite3_free (errmsg);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Execute a SQL statement */
+static gboolean
+db_exec (sqlite3* db,
+ const char* sqlcmd,
+ GError** error)
+{
+ return (db_exec_callback (db, sqlcmd, NULL, NULL, error));
+}
+
+/* sqlite method for retrieving the date/ time */
+static int
+gettimestr (void* data,
+ int argc,
+ char** argv,
+ char** colname)
+{
+ KatzeItem* item = KATZE_ITEM (data);
+ (void) colname;
+
+ g_return_val_if_fail (argc == 1, 1);
+
+ katze_item_set_added (item, argv[0]);
+ return 0;
+}
+
+static void
+midori_history_remove_item_cb (KatzeArray* history,
+ KatzeItem* item,
+ sqlite3* db)
+{
+ gchar* sqlcmd;
+ gboolean success = TRUE;
+ GError* error = NULL;
+
+ g_return_if_fail (KATZE_IS_ITEM (item));
+
+ sqlcmd = g_strdup_printf ("DELETE FROM history WHERE uri = '%s' AND"
+ " title = '%s' AND date = '%s' AND visits = %d",
+ katze_item_get_uri (item),
+ katze_item_get_name (item),
+ katze_item_get_added (item),
+ katze_item_get_visits (item));
+ success = db_exec (db, sqlcmd, &error);
+ if (!success)
+ {
+ g_printerr (_("Failed to remove history item. %s\n"), error->message);
+ g_error_free (error);
+ return ;
+ }
+ g_free (sqlcmd);
+}
+
+static void
+midori_history_clear_before_cb (KatzeArray* item,
+ sqlite3* db)
+{
+ g_signal_handlers_block_by_func (item, midori_history_remove_item_cb, db);
+}
+
+static void
+midori_history_clear_cb (KatzeArray* history,
+ sqlite3* db)
+{
+ GError* error = NULL;
+
+ g_return_if_fail (KATZE_IS_ARRAY (history));
+
+ if (!db_exec (db, "DELETE FROM history", &error))
+ {
+ g_printerr (_("Failed to clear history. %s\n"), error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+midori_history_add_item_cb (KatzeArray* array,
+ KatzeItem* item,
+ sqlite3* db)
+{
+ gchar* sqlcmd;
+ gboolean success = TRUE;
+ GError* error = NULL;
+
+ g_return_if_fail (KATZE_IS_ITEM (item));
+
+ if (KATZE_IS_ARRAY (item))
+ {
+ g_signal_connect_after (item, "add-item",
+ G_CALLBACK (midori_history_add_item_cb), db);
+ g_signal_connect (item, "remove-item",
+ G_CALLBACK (midori_history_remove_item_cb), db);
+ g_signal_connect (item, "clear",
+ G_CALLBACK (midori_history_clear_before_cb), db);
+ return;
+ }
+
+ /* New item, set added to the current date/ time */
+ if (!katze_item_get_added (item))
+ {
+ if (!db_exec_callback (db, "SELECT datetime('now')",
+ gettimestr, item, &error))
+ {
+ g_printerr (_("Failed to add history item. %s\n"), error->message);
+ g_error_free (error);
+ return;
+ }
+ }
+ sqlcmd = g_strdup_printf ("INSERT INTO history VALUES"
+ "('%s', '%s', '%s', %d)",
+ katze_item_get_uri (item),
+ katze_item_get_name (item),
+ katze_item_get_added (item),
+ katze_item_get_visits (item));
+ success = db_exec (db, sqlcmd, &error);
+ g_free (sqlcmd);
+ if (!success)
+ {
+ g_printerr (_("Failed to add history item. %s\n"), error->message);
+ g_error_free (error);
+ return ;
+ }
+}
+
+static int
+midori_history_add_items (void* data,
+ int argc,
+ char** argv,
+ char** colname)
+{
+ KatzeItem* item;
+ KatzeArray* parent = NULL;
+ KatzeArray* array = KATZE_ARRAY (data);
+ gchar* newdate;
+ gint i, j, n;
+ gint ncols = 4;
+ gsize len;
+
+ g_return_val_if_fail (KATZE_IS_ARRAY (array), 1);
+
+ /* Test whether have the right number of columns */
+ g_return_val_if_fail (argc % ncols == 0, 1);
+
+ for (i = 0; i <= (argc - ncols); i++)
+ {
+ if (argv[i])
+ {
+ if (colname[i] && g_ascii_strcasecmp (colname[i], "uri") == 0 &&
+ colname[i + 1] && g_ascii_strcasecmp (colname[i + 1], "title") == 0 &&
+ colname[i + 2] && g_ascii_strcasecmp (colname[i + 2], "date") == 0 &&
+ colname[i + 3] && g_ascii_strcasecmp (colname[i + 3], "visits") == 0)
+ {
+ item = katze_item_new ();
+ katze_item_set_uri (item, argv[i]);
+ katze_item_set_name (item, argv[i + 1]);
+ katze_item_set_added (item, argv[i + 2]);
+ katze_item_set_visits (item, atoi (argv[i + 3]));
+
+ len = (g_strrstr (argv[i + 2], " ") - argv[i + 2]);
+ newdate = g_strndup (argv[i + 2], len);
+
+ n = katze_array_get_length (array);
+ for (j = 0; j < n; j++)
+ {
+ parent = katze_array_get_nth_item (array, j);
+ if (newdate && g_ascii_strcasecmp
+ (katze_item_get_added (KATZE_ITEM (parent)), newdate) == 0)
+ break;
+ }
+ if (j == n)
+ {
+ parent = katze_array_new (KATZE_TYPE_ARRAY);
+ katze_item_set_added (KATZE_ITEM (parent), newdate);
+ katze_array_add_item (array, parent);
+ }
+ g_free (newdate);
+
+ katze_array_add_item (parent, item);
+ }
+ }
+ }
+ return 0;
+}
+
+static sqlite3*
+midori_history_initialize (KatzeArray* array,
+ const gchar* filename,
+ GError** error)
+{
+ sqlite3* db;
+ KatzeItem* item;
+ gint i, n;
+
+ if ((db = db_open (filename, error)) == NULL)
+ return db;
+
+ if (!db_exec (db,
+ "CREATE TABLE IF NOT EXISTS "
+ "history(uri text, title text, date text, visits integer)",
+ error))
+ return NULL;
+
+ if (!db_exec_callback (db,
+ "SELECT uri, title, date, visits FROM history "
+ "ORDER BY strftime('%s', date) ASC",
+ midori_history_add_items,
+ array,
+ error))
+ return NULL;
+
+ n = katze_array_get_length (array);
+ for (i = 0; i < n; i++)
+ {
+ item = katze_array_get_nth_item (array, i);
+ g_signal_connect_after (item, "add-item",
+ G_CALLBACK (midori_history_add_item_cb), db);
+ g_signal_connect (item, "remove-item",
+ G_CALLBACK (midori_history_remove_item_cb), db);
+ g_signal_connect (item, "clear",
+ G_CALLBACK (midori_history_clear_before_cb), db);
+ }
+ return db;
+}
+
static gchar*
_simple_xml_element (const gchar* name,
const gchar* value)
gchar* homepage;
KatzeArray* search_engines;
KatzeArray* bookmarks;
+ KatzeArray* history;
KatzeArray* _session;
KatzeArray* trash;
MidoriBrowser* browser;
gchar* uri;
KatzeItem* item;
gchar* uri_ready;
+ sqlite3* db;
#if ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, MIDORI_LOCALEDIR);
g_error_free (error);
}
g_free (config_file);
+ config_file = g_build_filename (config_path, "history.db", NULL);
+ history = katze_array_new (KATZE_TYPE_ARRAY);
+ error = NULL;
+ if ((db = midori_history_initialize (history, config_file, &error)) == NULL)
+ {
+ g_string_append_printf (error_messages,
+ _("The history couldn't be loaded. %s\n"), error->message);
+ g_error_free (error);
+ }
+ g_free (config_file);
/* In case of errors */
if (error_messages->len)
g_object_unref (bookmarks);
g_object_unref (_session);
g_object_unref (trash);
+ g_object_unref (history);
g_string_free (error_messages, TRUE);
return 0;
}
g_signal_connect_after (trash, "add-item",
G_CALLBACK (midori_web_list_add_item_cb), NULL);
+ g_signal_connect_after (history, "add-item",
+ G_CALLBACK (midori_history_add_item_cb), db);
+ g_signal_connect_after (history, "clear",
+ G_CALLBACK (midori_history_clear_cb), db);
g_object_set (app, "settings", settings,
"bookmarks", bookmarks,
"trash", trash,
"search-engines", search_engines,
+ "history", history,
NULL);
browser = g_object_new (MIDORI_TYPE_BROWSER,
"bookmarks", bookmarks,
"trash", trash,
"search-engines", search_engines,
+ "history", history,
NULL);
midori_app_add_browser (app, browser);
gtk_widget_show (GTK_WIDGET (browser));
config_path = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME,
NULL);
g_mkdir_with_parents (config_path, 0755);
+ g_object_unref (history);
+ db_close (db);
config_file = g_build_filename (config_path, "search", NULL);
error = NULL;
if (!search_engines_save_to_file (search_engines, config_file, &error))
/*
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
+ Copyright (C) 2008 Dale Whittaker <dayul@users.sf.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
GtkWidget* menu_tools;
GtkWidget* menu_window;
GtkWidget* popup_bookmark;
+ GtkWidget* popup_history;
GtkWidget* throbber;
GtkWidget* navigationbar;
GtkWidget* button_tab_new;
GtkWidget* panel;
GtkWidget* panel_bookmarks;
+ GtkWidget* panel_history;
GtkWidget* panel_console;
GtkWidget* panel_pageholder;
GtkWidget* notebook;
KatzeArray* proxy_array;
KatzeArray* trash;
KatzeArray* search_engines;
+ KatzeArray* history;
};
G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW)
PROP_SETTINGS,
PROP_BOOKMARKS,
PROP_TRASH,
- PROP_SEARCH_ENGINES
+ PROP_SEARCH_ENGINES,
+ PROP_HISTORY
};
enum
GValue* value,
GParamSpec* pspec);
-
+static void
+midori_browser_new_history_item (MidoriBrowser* browser,
+ KatzeItem* item);
static GtkAction*
_action_by_name (MidoriBrowser* browser,
const gchar* title;
GtkAction* action;
gchar* window_title;
+ KatzeItem* item;
uri = midori_view_get_display_uri (MIDORI_VIEW (view));
title = midori_view_get_display_title (MIDORI_VIEW (view));
action = _action_by_name (browser, "Location");
midori_location_action_set_title_for_uri (
MIDORI_LOCATION_ACTION (action), title, uri);
+ if (midori_view_get_load_status (MIDORI_VIEW (view)) == MIDORI_LOAD_COMMITTED)
+ {
+ if (!browser->history)
+ return;
+
+ item = katze_item_new ();
+ katze_item_set_uri (item, uri);
+ katze_item_set_name (item, title);
+ katze_item_set_visits (item, -1);
+ midori_browser_new_history_item (browser, item);
+ }
if (view == midori_browser_get_current_tab (browser))
{
_("The list of search engines to be used for web search"),
KATZE_TYPE_ARRAY,
G_PARAM_READWRITE));
+
+ /**
+ * MidoriBrowser:history:
+ *
+ * The list of history items.
+ *
+ * This is actually a reference to a history instance,
+ * so if history should be used it must be initially set.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_HISTORY,
+ g_param_spec_object (
+ "history",
+ _("History"),
+ _("The list of history items"),
+ KATZE_TYPE_ARRAY,
+ G_PARAM_READWRITE));
}
static void
}
}
+static void
+midori_panel_history_row_activated_cb (GtkTreeView* treeview,
+ GtkTreePath* path,
+ GtkTreeViewColumn* column,
+ MidoriBrowser* browser)
+{
+ KatzeItem* item;
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ const gchar* uri;
+
+ model = gtk_tree_view_get_model (treeview);
+ if (gtk_tree_model_get_iter (model, &iter, path))
+ {
+ gtk_tree_model_get (model, &iter, 0, &item, -1);
+ if (KATZE_IS_ITEM (item))
+ {
+ uri = katze_item_get_uri (item);
+ _midori_browser_open_uri (browser, uri);
+ }
+ g_object_unref (item);
+ }
+}
+
+static void
+_midori_panel_history_popup (GtkWidget* widget,
+ GdkEventButton* event,
+ KatzeItem* item,
+ MidoriBrowser* browser)
+{
+ gboolean is_history_item = (KATZE_IS_ITEM (item) && !KATZE_IS_ARRAY (item));
+
+ _action_set_sensitive (browser, "HistoryOpen", is_history_item);
+ _action_set_sensitive (browser, "HistoryOpenTab", is_history_item);
+
+ sokoke_widget_popup (widget, GTK_MENU (browser->popup_history),
+ event, SOKOKE_MENU_POSITION_CURSOR);
+}
+
+static gboolean
+midori_panel_history_button_release_event_cb (GtkWidget* widget,
+ GdkEventButton* event,
+ MidoriBrowser* browser)
+{
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ KatzeItem* item;
+ const gchar* uri;
+ gint n;
+
+ if (event->button != 2 && event->button != 3)
+ return FALSE;
+
+ if (sokoke_tree_view_get_selected_iter (GTK_TREE_VIEW (widget),
+ &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter, 0, &item, -1);
+ uri = katze_item_get_uri (item);
+ if (event->button == 2)
+ {
+ if (uri && *uri)
+ {
+ n = midori_browser_add_uri (browser, uri);
+ midori_browser_set_current_page (browser, n);
+ }
+ }
+ else
+ _midori_panel_history_popup (widget, event, item, browser);
+
+ g_object_unref (item);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+midori_panel_history_popup_menu_cb (GtkWidget* widget,
+ MidoriBrowser* browser)
+{
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ KatzeItem* item;
+
+ if (sokoke_tree_view_get_selected_iter (GTK_TREE_VIEW (widget),
+ &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter, 0, &item, -1);
+ _midori_panel_history_popup (widget, NULL, item, browser);
+ g_object_unref (item);
+ }
+}
+
static void
_tree_store_insert_folder (GtkTreeStore* treestore,
GtkTreeIter* parent,
midori_browser_edit_bookmark_dialog_new (browser, NULL);
}
+static void
+midori_browser_history_render_icon_cb (GtkTreeViewColumn* column,
+ GtkCellRenderer* renderer,
+ GtkTreeModel* model,
+ GtkTreeIter* iter,
+ GtkWidget* treeview)
+{
+ KatzeItem* item;
+ GdkPixbuf* pixbuf = NULL;
+
+ gtk_tree_model_get (model, iter, 0, &item, -1);
+
+ if (G_UNLIKELY (!item))
+ return;
+ if (G_UNLIKELY (!katze_item_get_parent (item)))
+ {
+ gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
+ g_object_unref (item);
+ return;
+ }
+
+ if (KATZE_IS_ARRAY (item))
+ pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY,
+ GTK_ICON_SIZE_MENU, NULL);
+ else
+ pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_FILE,
+ GTK_ICON_SIZE_MENU, NULL);
+
+ g_object_set (renderer, "pixbuf", pixbuf, NULL);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+ g_object_unref (item);
+}
+
+static void
+midori_browser_history_render_text_cb (GtkTreeViewColumn* column,
+ GtkCellRenderer* renderer,
+ GtkTreeModel* model,
+ GtkTreeIter* iter,
+ GtkWidget* treeview)
+{
+ KatzeItem* item;
+
+ gtk_tree_model_get (model, iter, 0, &item, -1);
+
+ if (G_UNLIKELY (!item))
+ return;
+ if (G_UNLIKELY (!katze_item_get_parent (item)))
+ {
+ gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
+ g_object_unref (item);
+ return;
+ }
+
+ if (KATZE_IS_ARRAY (item))
+ g_object_set (renderer, "text", katze_item_get_added (item), NULL);
+ else
+ g_object_set (renderer, "text", katze_item_get_name (item), NULL);
+
+ g_object_unref (item);
+}
+
static void
_action_manage_search_engines_activate (GtkAction* action,
MidoriBrowser* browser)
}
}
+static void
+_action_history_open_activate (GtkAction* action,
+ MidoriBrowser* browser)
+{
+ GtkTreeView* tree_view;
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ KatzeItem* item;
+ const gchar* uri;
+
+ tree_view = GTK_TREE_VIEW (browser->panel_history);
+ if (sokoke_tree_view_get_selected_iter (tree_view, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter, 0, &item, -1);
+ uri = katze_item_get_uri (item);
+ if (uri && *uri)
+ _midori_browser_open_uri (browser, uri);
+ g_object_unref (item);
+ }
+}
+
+static void
+_action_history_open_tab_activate (GtkAction* action,
+ MidoriBrowser* browser)
+{
+ GtkTreeView* tree_view;
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ KatzeItem* item;
+ const gchar* uri;
+ gint n;
+
+ tree_view = GTK_TREE_VIEW (browser->panel_history);
+ if (sokoke_tree_view_get_selected_iter (tree_view, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter, 0, &item, -1);
+ uri = katze_item_get_uri (item);
+ if (uri && *uri)
+ {
+ n = midori_browser_add_item (browser, item);
+ _midori_browser_set_current_page_smartly (browser, n);
+ }
+ g_object_unref (item);
+ }
+}
+
+static void
+_action_history_delete_activate (GtkAction* action,
+ MidoriBrowser* browser)
+{
+ GtkTreeView* treeview;
+ GtkTreeModel* treemodel;
+ GtkTreeIter iter;
+ GtkTreeIter childiter;
+ KatzeItem* item;
+ KatzeItem* child;
+ KatzeArray* parent;
+ gint i, n;
+
+ treeview = GTK_TREE_VIEW (browser->panel_history);
+ if (sokoke_tree_view_get_selected_iter (treeview, &treemodel, &iter))
+ {
+ gtk_tree_model_get (treemodel, &iter, 0, &item, -1);
+
+ if (KATZE_IS_ARRAY (item))
+ {
+ n = katze_array_get_length (KATZE_ARRAY (item));
+ for (i = 0; i < n; i++)
+ {
+ child = katze_array_get_nth_item (KATZE_ARRAY (item), 0);
+ katze_array_remove_item (KATZE_ARRAY (item), child);
+ }
+ parent = katze_item_get_parent (item);
+ katze_array_remove_item (parent, item);
+ while (gtk_tree_model_iter_nth_child (treemodel, &childiter, &iter, 0))
+ gtk_tree_store_remove (GTK_TREE_STORE (treemodel), &childiter);
+ gtk_tree_store_remove (GTK_TREE_STORE (treemodel), &iter);
+ g_object_unref (item);
+ }
+ else
+ {
+ parent = katze_item_get_parent (item);
+ katze_array_remove_item (parent, item);
+ gtk_tree_store_remove (GTK_TREE_STORE (treemodel), &iter);
+ g_object_unref (item);
+ }
+ }
+}
+
+static void
+_action_history_clear_activate (GtkAction* action,
+ MidoriBrowser* browser)
+{
+ GtkTreeView* tree_view;
+ GtkTreeStore* store;
+ KatzeItem* item;
+ gint i, n;
+
+ if (!browser->history)
+ return;
+
+ tree_view = GTK_TREE_VIEW (browser->panel_history);
+ store = GTK_TREE_STORE (gtk_tree_view_get_model (tree_view));
+ gtk_tree_store_clear (store);
+
+ n = katze_array_get_length (browser->history);
+ for (i = 0; i < n; i++)
+ {
+ item = katze_array_get_nth_item (browser->history, i);
+ katze_array_clear (KATZE_ARRAY (item));
+ }
+ katze_array_clear (browser->history);
+}
+
static void
_action_undo_tab_close_activate (GtkAction* action,
MidoriBrowser* browser)
{ "BookmarkDelete", GTK_STOCK_DELETE,
NULL, "",
N_("Delete the selected bookmark"), G_CALLBACK (_action_bookmark_delete_activate) },
-
+ { "HistoryDelete", GTK_STOCK_DELETE,
+ NULL, "",
+ N_("Delete the selected history item"), G_CALLBACK (_action_history_delete_activate) },
+ { "HistoryClear", GTK_STOCK_CLEAR,
+ NULL, "",
+ N_("Clear the enitre history"), G_CALLBACK (_action_history_clear_activate) },
+ { "HistoryOpen", GTK_STOCK_OPEN,
+ NULL, "",
+ N_("Open the selected history item"), G_CALLBACK (_action_history_open_activate) },
+ { "HistoryOpenTab", STOCK_TAB_NEW,
+ N_("Open in New _Tab"), "",
+ N_("Open the selected history item in a new tab"), G_CALLBACK (_action_history_open_tab_activate) },
{ "Tools", NULL, N_("_Tools") },
{ "ManageSearchEngines", GTK_STOCK_PROPERTIES,
N_("_Manage Search Engines"), "<Ctrl><Alt>s",
"<menuitem action='BookmarkEdit'/>"
"<menuitem action='BookmarkDelete'/>"
"</popup>"
+ "<toolbar name='toolbar_history'>"
+ "<toolitem action='HistoryDelete'/>"
+ "<toolitem action='HistoryClear' position='bottom' />"
+ "</toolbar>"
+ "<popup name='popup_history'>"
+ "<menuitem action='HistoryOpen'/>"
+ "<menuitem action='HistoryOpenTab'/>"
+ "<separator/>"
+ "<menuitem action='HistoryDelete'/>"
+ "</popup>"
"</ui>";
static void
browser->bookmarks = NULL;
browser->trash = NULL;
browser->search_engines = NULL;
+ browser->history = NULL;
/* Setup the window metrics */
g_signal_connect (browser, "realize",
browser->popup_bookmark = gtk_ui_manager_get_widget (
ui_manager, "/popup_bookmark");
g_object_ref (browser->popup_bookmark);
+ browser->popup_history = gtk_ui_manager_get_widget (
+ ui_manager, "/popup_history");
+ g_object_ref (browser->popup_history);
browser->menu_tools = gtk_menu_item_get_submenu (GTK_MENU_ITEM (
gtk_ui_manager_get_widget (ui_manager, "/menubar/Tools")));
menuitem = gtk_separator_menu_item_new ();
STOCK_CONSOLE, _("Console"));
/* History */
- panel = midori_view_new ();
- gtk_widget_show (panel);
+ box = gtk_vbox_new (FALSE, 0);
+ treestore = gtk_tree_store_new (1, KATZE_TYPE_ITEM);
+ treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore));
+ 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_browser_history_render_icon_cb,
+ treeview, NULL);
+ renderer_text = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer_text,
+ (GtkTreeCellDataFunc)midori_browser_history_render_text_cb,
+ treeview, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+ g_object_unref (treestore);
+ g_object_connect (treeview,
+ "signal::row-activated",
+ midori_panel_history_row_activated_cb, browser,
+ "signal::button-release-event",
+ midori_panel_history_button_release_event_cb, browser,
+ "signal::popup-menu",
+ midori_panel_history_popup_menu_cb, browser,
+ NULL);
+ gtk_box_pack_start (GTK_BOX (box), treeview, TRUE, TRUE, 0);
+ browser->panel_history = treeview;
+ gtk_widget_show_all (box);
+ toolbar = gtk_ui_manager_get_widget (ui_manager, "/toolbar_history");
+ gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU);
+ gtk_widget_show (toolbar);
midori_panel_append_page (MIDORI_PANEL (browser->panel),
- panel, NULL,
+ box, toolbar,
STOCK_HISTORY, _("History"));
/* Pageholder */
g_object_unref (browser->trash);
if (browser->search_engines)
g_object_unref (browser->search_engines);
+ if (browser->history)
+ g_object_unref (browser->history);
G_OBJECT_CLASS (midori_browser_parent_class)->finalize (object);
}
_action_set_sensitive (browser, "BookmarkAdd", TRUE);
}
+static void
+_tree_store_insert_history_item (GtkTreeStore* treestore,
+ GtkTreeIter* parent,
+ KatzeItem* item)
+{
+ GtkTreeIter iter;
+ KatzeItem* child;
+ guint i, n;
+ GtkTreeIter* piter;
+
+ g_return_if_fail (KATZE_IS_ITEM (item));
+
+ if (KATZE_IS_ARRAY (item))
+ {
+ piter = parent;
+ if (katze_item_get_added (item))
+ {
+ gtk_tree_store_insert_with_values (treestore, &iter, parent, 0, 0, item, -1);
+ g_object_unref (item);
+ piter = &iter;
+ }
+ n = katze_array_get_length (KATZE_ARRAY (item));
+ for (i = 0; i < n; i++)
+ {
+ child = katze_array_get_nth_item (KATZE_ARRAY (item), i);
+ _tree_store_insert_history_item (treestore, piter, child);
+ }
+ }
+ else
+ {
+ gtk_tree_store_insert_with_values (treestore, &iter, parent, 0, 0, item, -1);
+ g_object_unref (item);
+ }
+}
+
+static void
+midori_browser_new_history_item (MidoriBrowser* browser,
+ KatzeItem* item)
+{
+ GtkTreeView* treeview;
+ GtkTreeModel* treemodel;
+ GtkTreeIter iter;
+ KatzeArray* parent;
+ gint i;
+ gboolean found;
+ time_t now;
+ gchar newdate [70];
+ gchar *today;
+ gsize len;
+
+ treeview = GTK_TREE_VIEW (browser->panel_history);
+ treemodel = gtk_tree_view_get_model (treeview);
+
+ now = time (NULL);
+ strftime (newdate, sizeof (newdate), "%Y-%m-%d %H:%M:%S", localtime (&now));
+ katze_item_set_added (item, newdate);
+
+ len = (g_strrstr (newdate, " ") - newdate);
+ today = g_strndup (newdate, len);
+
+ found = FALSE;
+ i = 0;
+ while (gtk_tree_model_iter_nth_child (treemodel, &iter, NULL, i++))
+ {
+ gtk_tree_model_get (treemodel, &iter, 0, &parent, -1);
+ if (g_ascii_strcasecmp (today,
+ katze_item_get_added (KATZE_ITEM (parent))) == 0)
+ {
+ found = TRUE;
+ break;
+ }
+ g_object_unref (parent);
+ }
+ if (!found)
+ {
+ parent = katze_array_new (KATZE_TYPE_ARRAY);
+ katze_item_set_added (KATZE_ITEM (parent), today);
+ katze_array_add_item (browser->history, parent);
+ katze_array_add_item (parent, item);
+ _tree_store_insert_history_item (GTK_TREE_STORE (treemodel), NULL,
+ KATZE_ITEM (parent));
+ }
+ else
+ {
+ _tree_store_insert_history_item (GTK_TREE_STORE (treemodel),
+ &iter, item);
+ katze_array_add_item (parent, item);
+ g_object_unref (parent);
+ }
+ g_free (today);
+
+}
+
+static void
+midori_browser_load_history (MidoriBrowser* browser)
+{
+ GtkTreeView* treeview;
+ GtkTreeModel* treemodel;
+
+ if (!browser->history)
+ return;
+
+ treeview = GTK_TREE_VIEW (browser->panel_history);
+ treemodel = gtk_tree_view_get_model (treeview);
+
+ _tree_store_insert_history_item (GTK_TREE_STORE (treemodel),
+ NULL, KATZE_ITEM (browser->history));
+}
+
static void
midori_browser_set_property (GObject* object,
guint prop_id,
_action_by_name (browser, "Search")), item);
}
break;
+ case PROP_HISTORY:
+ ; /* FIXME: Disconnect handlers */
+ katze_object_assign (browser->history, g_value_get_object (value));
+ midori_browser_load_history (browser);
+ /* FIXME: Connect to updates */
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_SEARCH_ENGINES:
g_value_set_object (value, browser->search_engines);
break;
+ case PROP_HISTORY:
+ g_value_set_object (value, browser->history);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;