midori/panels/midori-history.c
Alexander Butenko 46b63639f6 Refactor history panel to match bookmark code.
The toolbar buttons are also taken care of.

The broken clock time warning was removed since it would be
awkward to have with the date formatting where there is not
even a widget available. Should be re-considered.
2010-07-21 23:31:45 +02:00

963 lines
30 KiB
C

/*
Copyright (C) 2008-2009 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-history.h"
#include "midori-app.h"
#include "midori-array.h"
#include "midori-browser.h"
#include "midori-stock.h"
#include "midori-view.h"
#include "midori-viewable.h"
#include "sokoke.h"
#include "gtkiconentry.h"
#include <glib/gi18n.h>
#include <string.h>
#include <gdk/gdkkeysyms.h>
#define COMPLETION_DELAY 200
void
midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
KatzeItem* bookmark,
gboolean new_bookmark,
gboolean is_folder);
struct _MidoriHistory
{
GtkVBox parent_instance;
GtkWidget* toolbar;
GtkWidget* bookmark;
GtkWidget* delete;
GtkWidget* clear;
GtkWidget* treeview;
MidoriApp* app;
KatzeArray* array;
gint filter_timeout;
gchar* filter;
};
struct _MidoriHistoryClass
{
GtkVBoxClass parent_class;
};
static void
midori_history_viewable_iface_init (MidoriViewableIface* iface);
G_DEFINE_TYPE_WITH_CODE (MidoriHistory, midori_history, GTK_TYPE_VBOX,
G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
midori_history_viewable_iface_init));
enum
{
PROP_0,
PROP_APP
};
static void
midori_history_finalize (GObject* object);
static void
midori_history_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec);
static void
midori_history_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec);
static void
midori_history_class_init (MidoriHistoryClass* class)
{
GObjectClass* gobject_class;
GParamFlags flags;
gobject_class = G_OBJECT_CLASS (class);
gobject_class->finalize = midori_history_finalize;
gobject_class->set_property = midori_history_set_property;
gobject_class->get_property = midori_history_get_property;
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
g_object_class_install_property (gobject_class,
PROP_APP,
g_param_spec_object (
"app",
"App",
"The app",
MIDORI_TYPE_APP,
flags));
}
static const gchar*
midori_history_get_label (MidoriViewable* viewable)
{
return _("History");
}
static const gchar*
midori_history_get_stock_id (MidoriViewable* viewable)
{
return STOCK_HISTORY;
}
static gchar*
midori_history_format_date (KatzeItem *item)
{
gint age;
gint64 day;
gchar token[50];
gchar* sdate;
time_t current_time;
current_time = time (NULL);
day = katze_item_get_added (item);
age = sokoke_days_between ((time_t*)&day, &current_time);
/* A negative age is a date in the future, the clock is probably off */
if (age < -1)
;
else if (age > 7 || age < 0)
{
strftime (token, sizeof (token), "%x", localtime ((time_t*)&day));
sdate = token;
}
else if (age > 6)
sdate = _("A week ago");
else if (age > 1)
sdate = g_strdup_printf (ngettext ("%d day ago",
"%d days ago", (gint)age), (gint)age);
else if (age == 0)
sdate = _("Today");
else
sdate = _("Yesterday");
return sdate;
}
static void
midori_history_clear_db (MidoriHistory* history)
{
gchar* sqlcmd;
sqlite3* db;
char* errmsg = NULL;
db = g_object_get_data (G_OBJECT (history->array), "db");
sqlcmd = sqlite3_mprintf ("DELETE FROM history");
if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
{
g_printerr (_("Failed to remove history item: %s\n"), errmsg);
sqlite3_free (errmsg);
}
sqlite3_free (sqlcmd);
}
static void
midori_history_remove_item_from_db (MidoriHistory* history,
KatzeItem* item)
{
gchar* sqlcmd;
sqlite3* db;
char* errmsg = NULL;
db = g_object_get_data (G_OBJECT (history->array), "db");
if (KATZE_ITEM_IS_BOOKMARK (item))
sqlcmd = sqlite3_mprintf (
"DELETE FROM history WHERE uri = '%q' AND"
" title = '%q' AND date = %llu",
katze_item_get_uri (item),
katze_item_get_name (item),
katze_item_get_added (item));
else
sqlcmd = sqlite3_mprintf ("DELETE FROM history WHERE day = %d",
katze_item_get_meta_integer (item, "day"));
if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
{
g_printerr (_("Failed to remove history item: %s\n"), errmsg);
sqlite3_free (errmsg);
}
sqlite3_free (sqlcmd);
}
/**
* midori_history_read_from_db:
* @history: a #MidoriHistory
* @req_day: the timestamp of one day, or 0
* @filter: a filter string to search for
*
* Populates the model according to parameters:
* 1. If @req_day is 0, all dates are added as folders.
* 2. If @req_day is given, all pages for that day are added.
* 3. If @filter is given, all pages matching the filter are added.
**/
static KatzeArray*
midori_history_read_from_db (MidoriHistory* history,
int req_day,
const gchar* filter)
{
sqlite3* db;
sqlite3_stmt* statement;
gint result;
const gchar* sqlcmd;
db = g_object_get_data (G_OBJECT (history->array), "db");
if (filter && *filter)
{
gchar* filterstr;
sqlcmd = "SELECT * FROM ("
" SELECT uri, title, day FROM history"
" WHERE uri LIKE ?1 OR title LIKE ?1 GROUP BY uri "
"UNION ALL "
" SELECT replace (uri, '%s', keywords) AS uri, "
" keywords AS title, day FROM search "
" WHERE uri LIKE ?1 OR keywords LIKE ?1 GROUP BY uri "
") ORDER BY day ASC";
result = sqlite3_prepare_v2 (db, sqlcmd, -1, &statement, NULL);
filterstr = g_strdup_printf ("%%%s%%", filter);
sqlite3_bind_text (statement, 1, filterstr, -1, g_free);
req_day = -1;
}
else if (req_day == 0)
{
sqlcmd = "SELECT day, date FROM history GROUP BY day ORDER BY day ASC";
result = sqlite3_prepare_v2 (db, sqlcmd, -1, &statement, NULL);
}
else
{
sqlcmd = "SELECT uri, title, date, day "
"FROM history WHERE day = ? "
"GROUP BY uri ORDER BY date ASC";
result = sqlite3_prepare_v2 (db, sqlcmd, -1, &statement, NULL);
sqlite3_bind_int64 (statement, 1, req_day);
}
if (result != SQLITE_OK)
return NULL;
return katze_array_from_statement (statement);
}
static void
midori_history_read_from_db_to_model (MidoriHistory* history,
GtkTreeStore* model,
GtkTreeIter* parent,
int req_day,
const gchar* filter)
{
KatzeArray* array;
gint last;
KatzeItem* item;
GtkTreeIter child;
array = midori_history_read_from_db (history, req_day, filter);
katze_bookmark_populate_tree_view (array, model, parent);
/* Remove invisible dummy row */
last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent);
if (!last)
return;
gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model), &child, parent, last - 1);
gtk_tree_model_get (GTK_TREE_MODEL (model), &child, 0, &item, -1);
if (KATZE_ITEM_IS_SEPARATOR (item))
gtk_tree_store_remove (model, &child);
else
g_object_unref (item);
}
static void
midori_history_delete_clicked_cb (GtkWidget* toolitem,
MidoriHistory* history)
{
GtkTreeModel* model;
GtkTreeIter iter;
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (history->treeview),
&model, &iter))
{
KatzeItem* item;
gtk_tree_model_get (model, &iter, 0, &item, -1);
midori_history_remove_item_from_db (history, item);
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
g_object_unref (item);
}
}
static void
midori_history_clear_clicked_cb (GtkWidget* toolitem,
MidoriHistory* history)
{
MidoriBrowser* browser;
GtkWidget* dialog;
gint result;
browser = midori_browser_get_for_widget (GTK_WIDGET (history));
dialog = gtk_message_dialog_new (GTK_WINDOW (browser),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
_("Are you sure you want to remove all history items?"));
result = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
if (result != GTK_RESPONSE_YES)
return;
midori_history_clear_db (history);
}
static void
midori_history_bookmark_add_cb (GtkWidget* menuitem,
MidoriHistory* history)
{
GtkTreeModel* model;
GtkTreeIter iter;
KatzeItem* item;
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (history));
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (history->treeview),
&model, &iter))
gtk_tree_model_get (model, &iter, 0, &item, -1);
if (KATZE_IS_ITEM (item) && katze_item_get_uri (item))
midori_browser_edit_bookmark_dialog_new (browser, item, TRUE, FALSE);
else
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, FALSE);
g_object_unref (item);
}
static GtkWidget*
midori_history_get_toolbar (MidoriViewable* viewable)
{
MidoriHistory* history = MIDORI_HISTORY (viewable);
if (!history->toolbar)
{
GtkWidget* toolbar;
GtkToolItem* toolitem;
toolbar = gtk_toolbar_new ();
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
history->toolbar = toolbar;
toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK_ADD);
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
_("Bookmark the selected history item"));
gtk_tool_item_set_is_important (toolitem, TRUE);
g_signal_connect (toolitem, "clicked",
G_CALLBACK (midori_history_bookmark_add_cb), history);
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
gtk_widget_show (GTK_WIDGET (toolitem));
history->bookmark = GTK_WIDGET (toolitem);
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE);
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
_("Delete the selected history item"));
g_signal_connect (toolitem, "clicked",
G_CALLBACK (midori_history_delete_clicked_cb), history);
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
gtk_widget_show (GTK_WIDGET (toolitem));
history->delete = GTK_WIDGET (toolitem);
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLEAR);
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
_("Clear the entire history"));
g_signal_connect (toolitem, "clicked",
G_CALLBACK (midori_history_clear_clicked_cb), history);
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
gtk_widget_show (GTK_WIDGET (toolitem));
history->clear = GTK_WIDGET (toolitem);
g_signal_connect (history->bookmark, "destroy",
G_CALLBACK (gtk_widget_destroyed), &history->bookmark);
g_signal_connect (history->delete, "destroy",
G_CALLBACK (gtk_widget_destroyed), &history->delete);
g_signal_connect (history->clear, "destroy",
G_CALLBACK (gtk_widget_destroyed), &history->clear);
}
return history->toolbar;
}
static void
midori_history_viewable_iface_init (MidoriViewableIface* iface)
{
iface->get_stock_id = midori_history_get_stock_id;
iface->get_label = midori_history_get_label;
iface->get_toolbar = midori_history_get_toolbar;
}
static void
midori_history_set_app (MidoriHistory* history,
MidoriApp* app)
{
GtkTreeModel* model;
if (history->array)
{
g_object_unref (history->array);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
gtk_tree_store_clear (GTK_TREE_STORE (model));
}
katze_assign (history->app, app);
if (!app)
return;
g_object_ref (app);
history->array = katze_object_get_object (app, "history");
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
if (history->array)
midori_history_read_from_db_to_model (history, GTK_TREE_STORE (model), NULL, 0, NULL);
}
static void
midori_history_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
MidoriHistory* history = MIDORI_HISTORY (object);
switch (prop_id)
{
case PROP_APP:
midori_history_set_app (history, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
midori_history_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec)
{
MidoriHistory* history = MIDORI_HISTORY (object);
switch (prop_id)
{
case PROP_APP:
g_value_set_object (value, history->app);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
midori_history_treeview_render_icon_cb (GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* model,
GtkTreeIter* iter,
GtkWidget* treeview)
{
KatzeItem* item;
GdkPixbuf* pixbuf;
gtk_tree_model_get (model, iter, 0, &item, -1);
if (!item)
pixbuf = NULL;
else if (katze_item_get_uri (item))
pixbuf = katze_load_cached_icon (katze_item_get_uri (item), treeview);
else
pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY,
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_history_treeview_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 (KATZE_ITEM_IS_BOOKMARK (item))
g_object_set (renderer, "markup", NULL,
"text", katze_item_get_name (item), NULL);
else if (KATZE_ITEM_IS_FOLDER (item))
g_object_set (renderer, "markup", NULL,
"text", midori_history_format_date (item), NULL);
else
g_object_set (renderer, "markup", _("<i>Separator</i>"), NULL);
if (item)
g_object_unref (item);
}
static void
midori_history_row_activated_cb (GtkTreeView* treeview,
GtkTreePath* path,
GtkTreeViewColumn* column,
MidoriHistory* history)
{
GtkTreeModel* model;
GtkTreeIter iter;
KatzeItem* item;
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_ITEM_IS_BOOKMARK (item))
{
MidoriBrowser* browser;
const gchar* uri;
uri = katze_item_get_uri (item);
browser = midori_browser_get_for_widget (GTK_WIDGET (history));
midori_browser_set_current_uri (browser, uri);
g_object_unref (item);
return;
}
if (gtk_tree_view_row_expanded (treeview, path))
gtk_tree_view_collapse_row (treeview, path);
else
gtk_tree_view_expand_row (treeview, path, FALSE);
g_object_unref (item);
}
}
static void
midori_history_popup_item (GtkWidget* menu,
const gchar* stock_id,
const gchar* label,
KatzeItem* item,
gpointer callback,
MidoriHistory* history)
{
const gchar* uri;
GtkWidget* menuitem;
uri = katze_item_get_uri (item);
menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
if (label)
gtk_label_set_text_with_mnemonic (GTK_LABEL (gtk_bin_get_child (
GTK_BIN (menuitem))), label);
if (!strcmp (stock_id, GTK_STOCK_EDIT))
gtk_widget_set_sensitive (menuitem, uri != NULL);
else if (katze_item_get_uri (item) && strcmp (stock_id, GTK_STOCK_DELETE))
gtk_widget_set_sensitive (menuitem, uri != NULL);
g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item);
g_signal_connect (menuitem, "activate", G_CALLBACK (callback), history);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
}
static void
midori_history_open_activate_cb (GtkWidget* menuitem,
MidoriHistory* history)
{
KatzeItem* item;
const gchar* uri;
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
uri = katze_item_get_uri (item);
if (uri && *uri)
{
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (history));
midori_browser_set_current_uri (browser, uri);
}
}
static void
midori_history_open_in_tab_activate_cb (GtkWidget* menuitem,
MidoriHistory* history)
{
KatzeItem* item;
const gchar* uri;
guint n;
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
if (KATZE_ITEM_IS_FOLDER (item))
{
sqlite3* db;
gchar* sqlcmd;
KatzeItem* child;
KatzeArray* array;
guint i = 0;
db = g_object_get_data (G_OBJECT (history->array), "db");
sqlcmd = g_strdup_printf ("SELECT uri, title, date, day "
"FROM history WHERE day = %d "
"GROUP BY uri ORDER BY date ASC",
(int)katze_item_get_added (item));
array = katze_array_from_sqlite (db, sqlcmd);
g_free (sqlcmd);
while ((child = katze_array_get_nth_item (KATZE_ARRAY (array), i++)))
{
if ((uri = katze_item_get_uri (child)) && *uri)
{
MidoriBrowser* browser;
browser = midori_browser_get_for_widget (GTK_WIDGET (history));
n = midori_browser_add_item (browser, child);
midori_browser_set_current_page_smartly (browser, n);
}
}
}
else
{
if ((uri = katze_item_get_uri (item)) && *uri)
{
MidoriBrowser* browser;
browser = midori_browser_get_for_widget (GTK_WIDGET (history));
n = midori_browser_add_item (browser, item);
midori_browser_set_current_page_smartly (browser, n);
}
}
}
static void
midori_history_open_in_window_activate_cb (GtkWidget* menuitem,
MidoriHistory* history)
{
KatzeItem* item;
const gchar* uri;
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
uri = katze_item_get_uri (item);
if (uri && *uri)
{
MidoriBrowser* new_browser = midori_app_create_browser (history->app);
midori_app_add_browser (history->app, new_browser);
gtk_widget_show (GTK_WIDGET (new_browser));
midori_browser_add_uri (new_browser, uri);
}
}
static void
midori_history_popup (GtkWidget* widget,
GdkEventButton* event,
KatzeItem* item,
MidoriHistory* history)
{
GtkWidget* menu;
GtkWidget* menuitem;
menu = gtk_menu_new ();
if (!katze_item_get_uri (item))
midori_history_popup_item (menu,
STOCK_TAB_NEW, _("Open all in _Tabs"),
item, midori_history_open_in_tab_activate_cb, history);
else
{
midori_history_popup_item (menu, GTK_STOCK_OPEN, NULL,
item, midori_history_open_activate_cb, history);
midori_history_popup_item (menu, STOCK_TAB_NEW, _("Open in New _Tab"),
item, midori_history_open_in_tab_activate_cb, history);
midori_history_popup_item (menu, STOCK_WINDOW_NEW, _("Open in New _Window"),
item, midori_history_open_in_window_activate_cb, history);
midori_history_popup_item (menu, STOCK_BOOKMARK_ADD, NULL,
item, midori_history_bookmark_add_cb, history);
}
menuitem = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
midori_history_popup_item (menu, GTK_STOCK_DELETE, NULL,
item, midori_history_delete_clicked_cb, history);
katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR);
}
static gboolean
midori_history_button_release_event_cb (GtkWidget* widget,
GdkEventButton* event,
MidoriHistory* history)
{
GtkTreeModel* model;
GtkTreeIter iter;
if (event->button != 2 && event->button != 3)
return FALSE;
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
{
KatzeItem* item;
gtk_tree_model_get (model, &iter, 0, &item, -1);
if (!item)
return FALSE;
if (event->button == 2)
{
const gchar* uri = katze_item_get_uri (item);
if (uri && *uri)
{
MidoriBrowser* browser;
gint n;
browser = midori_browser_get_for_widget (widget);
n = midori_browser_add_uri (browser, uri);
midori_browser_set_current_page (browser, n);
}
}
else
midori_history_popup (widget, event, item, history);
g_object_unref (item);
return TRUE;
}
return FALSE;
}
static gboolean
midori_history_key_release_event_cb (GtkWidget* widget,
GdkEventKey* event,
MidoriHistory* history)
{
GtkTreeModel* model;
GtkTreeIter iter;
if (event->keyval != GDK_Delete)
return FALSE;
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
{
KatzeItem* item;
gtk_tree_model_get (model, &iter, 0, &item, -1);
midori_history_remove_item_from_db (history, item);
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
g_object_unref (item);
}
return FALSE;
}
static void
midori_history_popup_menu_cb (GtkWidget* widget,
MidoriHistory* history)
{
GtkTreeModel* model;
GtkTreeIter iter;
KatzeItem* item;
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
{
gtk_tree_model_get (model, &iter, 0, &item, -1);
midori_history_popup (widget, NULL, item, history);
g_object_unref (item);
}
}
static void
midori_history_row_expanded_cb (GtkTreeView* treeview,
GtkTreeIter* iter,
GtkTreePath* path,
MidoriHistory* history)
{
GtkTreeModel* model;
KatzeItem* item;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
gtk_tree_model_get (model, iter, 0, &item, -1);
midori_history_read_from_db_to_model (history, GTK_TREE_STORE (model),
iter, katze_item_get_meta_integer (item, "day"), NULL);
g_object_unref (item);
}
static void
midori_history_row_collapsed_cb (GtkTreeView *treeview,
GtkTreeIter *parent,
GtkTreePath *path,
gpointer user_data)
{
GtkTreeModel* model;
GtkTreeStore* treestore;
GtkTreeIter child;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
treestore = GTK_TREE_STORE (model);
while (gtk_tree_model_iter_nth_child (model, &child, parent, 0))
gtk_tree_store_remove (treestore, &child);
/* That's an invisible dummy, so we always have an expander */
gtk_tree_store_insert_with_values (treestore, &child, parent,
0, 0, NULL, -1);
}
static gboolean
midori_history_filter_timeout_cb (gpointer data)
{
MidoriHistory* history = data;
GtkTreeModel* model;
GtkTreeStore* treestore;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
treestore = GTK_TREE_STORE (model);
gtk_tree_store_clear (treestore);
midori_history_read_from_db_to_model (history, treestore, NULL, 0, history->filter);
return FALSE;
}
static void
midori_history_filter_entry_changed_cb (GtkEntry* entry,
MidoriHistory* history)
{
if (history->filter_timeout)
g_source_remove (history->filter_timeout);
history->filter_timeout = g_timeout_add (COMPLETION_DELAY,
midori_history_filter_timeout_cb, history);
katze_assign (history->filter, g_strdup (gtk_entry_get_text (entry)));
}
static void
midori_history_filter_entry_clear_cb (GtkEntry* entry,
gint icon_pos,
gint button,
MidoriHistory* history)
{
if (icon_pos == GTK_ICON_ENTRY_SECONDARY)
gtk_entry_set_text (entry, "");
}
static void
midori_history_init (MidoriHistory* history)
{
GtkWidget* entry;
GtkWidget* box;
GtkTreeStore* model;
GtkWidget* treeview;
GtkTreeViewColumn* column;
GtkCellRenderer* renderer_pixbuf;
GtkCellRenderer* renderer_text;
/* Create the filter entry */
entry = gtk_icon_entry_new ();
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY,
GTK_STOCK_FIND);
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY,
GTK_STOCK_CLEAR);
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY,
TRUE);
g_signal_connect (entry, "icon-release",
G_CALLBACK (midori_history_filter_entry_clear_cb), history);
g_signal_connect (entry, "changed",
G_CALLBACK (midori_history_filter_entry_changed_cb), history);
box = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 3);
gtk_widget_show_all (box);
gtk_box_pack_start (GTK_BOX (history), box, FALSE, FALSE, 5);
/* Create the treeview */
model = gtk_tree_store_new (1, KATZE_TYPE_ITEM);
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
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_history_treeview_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_history_treeview_render_text_cb,
treeview, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
g_object_unref (model);
g_object_connect (treeview,
"signal::row-activated",
midori_history_row_activated_cb, history,
"signal::button-release-event",
midori_history_button_release_event_cb, history,
"signal::key-release-event",
midori_history_key_release_event_cb, history,
"signal::row-expanded",
midori_history_row_expanded_cb, history,
"signal::row-collapsed",
midori_history_row_collapsed_cb, history,
"signal::popup-menu",
midori_history_popup_menu_cb, history,
NULL);
gtk_widget_show (treeview);
gtk_box_pack_start (GTK_BOX (history), treeview, TRUE, TRUE, 0);
history->treeview = treeview;
/* FIXME: We need to connect a signal here, to add new pages into history */
history->filter = NULL;
}
static void
midori_history_finalize (GObject* object)
{
MidoriHistory* history = MIDORI_HISTORY (object);
if (history->app)
g_object_unref (history->app);
/* FIXME: We don't unref items (last argument is FALSE) because
our reference counting is incorrect. */
g_object_unref (history->array);
katze_assign (history->filter, NULL);
}
/**
* midori_history_new:
*
* Creates a new empty history.
*
* Return value: a new #MidoriHistory
*
* Since: 0.1.3
**/
GtkWidget*
midori_history_new (void)
{
MidoriHistory* history = g_object_new (MIDORI_TYPE_HISTORY, NULL);
return GTK_WIDGET (history);
}