Implement navigation history backed by sqlite
The implementation relies on KatzeArray for the most part and only does the storage with sqlite behind the scenes. The change includes a working History panel. Changes to the database are committed in realtime.
This commit is contained in:
parent
a13f8b64b3
commit
d445745787
10 changed files with 982 additions and 20 deletions
|
@ -83,6 +83,12 @@ AC_SUBST(LIBXML_CFLAGS)
|
|||
AC_SUBST(LIBXML_LIBS)
|
||||
AC_DEFINE_UNQUOTED(HAVE_LIBXML,$have_libxml, [Whether LibXML is available])
|
||||
|
||||
# Check for sqlite 3
|
||||
PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.0], have_sqlite3=1, have_sqlite3=0)
|
||||
AC_SUBST([SQLITE3_CFLAGS])
|
||||
AC_SUBST([SQLITE3_LIBS])
|
||||
AC_DEFINE_UNQUOTED(HAVE_SQLITE3,$have_sqlite3, [Whether sqlite3 is available])
|
||||
|
||||
# i18n
|
||||
GETTEXT_PACKAGE=midori
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
|
|
|
@ -34,7 +34,9 @@ enum
|
|||
PROP_TEXT,
|
||||
PROP_URI,
|
||||
PROP_ICON,
|
||||
PROP_TOKEN
|
||||
PROP_TOKEN,
|
||||
PROP_ADDED,
|
||||
PROP_VISITS
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -109,6 +111,27 @@ katze_item_class_init (KatzeItemClass* class)
|
|||
_("The token of the item"),
|
||||
NULL,
|
||||
flags));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ADDED,
|
||||
g_param_spec_string (
|
||||
"added",
|
||||
_("Added"),
|
||||
_("When the item was added"),
|
||||
NULL,
|
||||
flags));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_VISITS,
|
||||
g_param_spec_int (
|
||||
"visits",
|
||||
_("Visits"),
|
||||
_("The number of visits of the item"),
|
||||
G_MININT,
|
||||
G_MAXINT,
|
||||
0,
|
||||
flags));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -129,6 +152,7 @@ katze_item_finalize (GObject* object)
|
|||
g_free (item->uri);
|
||||
g_free (item->icon);
|
||||
g_free (item->token);
|
||||
g_free (item->added);
|
||||
|
||||
G_OBJECT_CLASS (katze_item_parent_class)->finalize (object);
|
||||
}
|
||||
|
@ -158,6 +182,12 @@ katze_item_set_property (GObject* object,
|
|||
case PROP_TOKEN:
|
||||
item->token = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_ADDED:
|
||||
item->added = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_VISITS:
|
||||
item->visits = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -189,6 +219,12 @@ katze_item_get_property (GObject* object,
|
|||
case PROP_TOKEN:
|
||||
g_value_set_string (value, item->token);
|
||||
break;
|
||||
case PROP_ADDED:
|
||||
g_value_set_string (value, item->added);
|
||||
break;
|
||||
case PROP_VISITS:
|
||||
g_value_set_int (value, item->visits);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -375,6 +411,72 @@ katze_item_set_token (KatzeItem* item,
|
|||
g_object_notify (G_OBJECT (item), "token");
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_get_added:
|
||||
* @item: a #KatzeItem
|
||||
*
|
||||
* Determines when @item was added.
|
||||
*
|
||||
* Return value: a timestamp
|
||||
**/
|
||||
const gchar*
|
||||
katze_item_get_added (KatzeItem* item)
|
||||
{
|
||||
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||
|
||||
return item->added;
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_set_added:
|
||||
* @item: a #KatzeItem
|
||||
* @added: a timestamp
|
||||
*
|
||||
* Sets when @item was added.
|
||||
**/
|
||||
void
|
||||
katze_item_set_added (KatzeItem* item,
|
||||
const gchar* added)
|
||||
{
|
||||
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||
|
||||
katze_assign (item->added, g_strdup (added));
|
||||
g_object_notify (G_OBJECT (item), "added");
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_get_visits:
|
||||
* @item: a #KatzeItem
|
||||
*
|
||||
* Retrieves the number of visits of @item.
|
||||
*
|
||||
* Return value: the number of visits
|
||||
**/
|
||||
gint
|
||||
katze_item_get_visits (KatzeItem* item)
|
||||
{
|
||||
g_return_val_if_fail (KATZE_IS_ITEM (item), -1);
|
||||
|
||||
return item->visits;
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_set_visits:
|
||||
* @item: a #KatzeItem
|
||||
* @visits: an integer
|
||||
*
|
||||
* Sets the number of visits of @item.
|
||||
**/
|
||||
void
|
||||
katze_item_set_visits (KatzeItem* item,
|
||||
gint visits)
|
||||
{
|
||||
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||
|
||||
item->visits = visits;
|
||||
g_object_notify (G_OBJECT (item), "visits");
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_item_get_parent:
|
||||
* @item: a #KatzeItem
|
||||
|
@ -412,3 +514,4 @@ katze_item_set_parent (KatzeItem* item,
|
|||
katze_object_assign (item->parent, parent);
|
||||
/* g_object_notify (G_OBJECT (item), "parent"); */
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ struct _KatzeItem
|
|||
gchar* uri;
|
||||
gchar* icon;
|
||||
gchar* token;
|
||||
gchar* added;
|
||||
gint visits;
|
||||
|
||||
KatzeItem* parent;
|
||||
};
|
||||
|
@ -91,6 +93,20 @@ void
|
|||
katze_item_set_token (KatzeItem* item,
|
||||
const gchar* token);
|
||||
|
||||
const gchar*
|
||||
katze_item_get_added (KatzeItem* item);
|
||||
|
||||
void
|
||||
katze_item_set_added (KatzeItem* item,
|
||||
const gchar* added);
|
||||
|
||||
gint
|
||||
katze_item_get_visits (KatzeItem* item);
|
||||
|
||||
void
|
||||
katze_item_set_visits (KatzeItem* item,
|
||||
gint visits);
|
||||
|
||||
gpointer
|
||||
katze_item_get_parent (KatzeItem* item);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ G_DEFINE_TYPE (KatzeList, katze_list, KATZE_TYPE_ITEM)
|
|||
enum {
|
||||
ADD_ITEM,
|
||||
REMOVE_ITEM,
|
||||
CLEAR,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
@ -52,6 +53,23 @@ _katze_list_remove_item (KatzeList* list,
|
|||
list->items = g_list_remove (list->items, item);
|
||||
}
|
||||
|
||||
static void
|
||||
_katze_list_clear (KatzeList* list)
|
||||
{
|
||||
guint n;
|
||||
guint i;
|
||||
GObject* item;
|
||||
|
||||
n = g_list_length (list->items);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if ((item = g_list_nth_data (list->items, i)))
|
||||
katze_list_remove_item (list, item);
|
||||
}
|
||||
g_list_free (list->items);
|
||||
list->items = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
katze_list_class_init (KatzeListClass* class)
|
||||
{
|
||||
|
@ -79,11 +97,23 @@ katze_list_class_init (KatzeListClass* class)
|
|||
G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
signals[CLEAR] = g_signal_new (
|
||||
"clear",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||
G_STRUCT_OFFSET (KatzeListClass, clear),
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (class);
|
||||
gobject_class->finalize = katze_list_finalize;
|
||||
|
||||
class->add_item = _katze_list_add_item;
|
||||
class->remove_item = _katze_list_remove_item;
|
||||
class->clear = _katze_list_clear;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -227,18 +257,7 @@ katze_list_get_length (KatzeList* list)
|
|||
void
|
||||
katze_list_clear (KatzeList* list)
|
||||
{
|
||||
guint n;
|
||||
guint i;
|
||||
GObject* item;
|
||||
|
||||
g_return_if_fail (KATZE_IS_LIST (list));
|
||||
|
||||
n = g_list_length (list->items);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if ((item = g_list_nth_data (list->items, i)))
|
||||
katze_list_remove_item (list, item);
|
||||
}
|
||||
g_list_free (list->items);
|
||||
list->items = NULL;
|
||||
g_signal_emit (list, signals[CLEAR], 0);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,9 @@ struct _KatzeListClass
|
|||
void
|
||||
(*remove_item) (KatzeList* list,
|
||||
gpointer item);
|
||||
void
|
||||
(*clear) (KatzeList* list);
|
||||
|
||||
};
|
||||
|
||||
GType
|
||||
|
|
309
midori/main.c
309
midori/main.c
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -27,11 +28,21 @@
|
|||
#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)
|
||||
{
|
||||
|
@ -564,6 +575,283 @@ katze_array_from_file (KatzeArray* array,
|
|||
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)
|
||||
|
@ -756,6 +1044,7 @@ main (int argc,
|
|||
gchar* homepage;
|
||||
KatzeArray* search_engines;
|
||||
KatzeArray* bookmarks;
|
||||
KatzeArray* history;
|
||||
KatzeArray* _session;
|
||||
KatzeArray* trash;
|
||||
MidoriBrowser* browser;
|
||||
|
@ -764,6 +1053,7 @@ main (int argc,
|
|||
gchar* uri;
|
||||
KatzeItem* item;
|
||||
gchar* uri_ready;
|
||||
sqlite3* db;
|
||||
|
||||
#if ENABLE_NLS
|
||||
bindtextdomain (GETTEXT_PACKAGE, MIDORI_LOCALEDIR);
|
||||
|
@ -910,6 +1200,16 @@ main (int argc,
|
|||
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)
|
||||
|
@ -943,6 +1243,7 @@ main (int argc,
|
|||
g_object_unref (bookmarks);
|
||||
g_object_unref (_session);
|
||||
g_object_unref (trash);
|
||||
g_object_unref (history);
|
||||
g_string_free (error_messages, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
@ -987,11 +1288,16 @@ main (int argc,
|
|||
|
||||
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,
|
||||
|
@ -999,6 +1305,7 @@ main (int argc,
|
|||
"bookmarks", bookmarks,
|
||||
"trash", trash,
|
||||
"search-engines", search_engines,
|
||||
"history", history,
|
||||
NULL);
|
||||
midori_app_add_browser (app, browser);
|
||||
gtk_widget_show (GTK_WIDGET (browser));
|
||||
|
@ -1059,6 +1366,8 @@ main (int argc,
|
|||
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))
|
||||
|
|
|
@ -35,6 +35,7 @@ struct _MidoriApp
|
|||
KatzeArray* bookmarks;
|
||||
KatzeArray* trash;
|
||||
KatzeArray* search_engines;
|
||||
KatzeArray* history;
|
||||
|
||||
gpointer instance;
|
||||
};
|
||||
|
@ -52,6 +53,7 @@ enum
|
|||
PROP_TRASH,
|
||||
PROP_SEARCH_ENGINES,
|
||||
PROP_BROWSER,
|
||||
PROP_HISTORY,
|
||||
PROP_BROWSER_COUNT
|
||||
};
|
||||
|
||||
|
@ -172,6 +174,17 @@ midori_app_class_init (MidoriAppClass* class)
|
|||
_("The current number of browsers"),
|
||||
0, G_MAXUINT, 0,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_HISTORY,
|
||||
g_param_spec_object (
|
||||
"history",
|
||||
_("History"),
|
||||
_("The list of history items"),
|
||||
KATZE_TYPE_ARRAY,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
|
||||
}
|
||||
|
||||
static GObject*
|
||||
|
@ -212,6 +225,7 @@ midori_browser_message_received_cb (UniqueApp* instance,
|
|||
"bookmarks", app->bookmarks,
|
||||
"trash", app->trash,
|
||||
"search-engines", app->search_engines,
|
||||
"history", app->history,
|
||||
NULL);
|
||||
/* FIXME: Should open the homepage according to settings */
|
||||
midori_browser_add_uri (browser, "about:blank");
|
||||
|
@ -267,6 +281,7 @@ midori_app_init (MidoriApp* app)
|
|||
app->bookmarks = NULL;
|
||||
app->trash = NULL;
|
||||
app->search_engines = NULL;
|
||||
app->history = NULL;
|
||||
|
||||
#if HAVE_UNIQUE
|
||||
display_name = g_strdup (gdk_display_get_name (gdk_display_get_default ()));
|
||||
|
@ -301,6 +316,8 @@ midori_app_finalize (GObject* object)
|
|||
g_object_unref (app->trash);
|
||||
if (app->search_engines)
|
||||
g_object_unref (app->search_engines);
|
||||
if (app->history)
|
||||
g_object_unref (app->history);
|
||||
|
||||
if (app->instance)
|
||||
g_object_unref (app->instance);
|
||||
|
@ -338,6 +355,10 @@ midori_app_set_property (GObject* object,
|
|||
g_object_ref (app->search_engines);
|
||||
/* FIXME: Propagate search engines to all browsers */
|
||||
break;
|
||||
case PROP_HISTORY:
|
||||
katze_object_assign (app->history, g_value_get_object (value));
|
||||
/* FIXME: Propagate history to all browsers */
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -366,6 +387,9 @@ midori_app_get_property (GObject* object,
|
|||
case PROP_SEARCH_ENGINES:
|
||||
g_value_set_object (value, app->search_engines);
|
||||
break;
|
||||
case PROP_HISTORY:
|
||||
g_value_set_object (value, app->history);
|
||||
break;
|
||||
case PROP_BROWSER:
|
||||
g_value_set_object (value, app->browser);
|
||||
break;
|
||||
|
@ -398,6 +422,7 @@ midori_browser_new_window_cb (MidoriBrowser* browser,
|
|||
"bookmarks", app->bookmarks,
|
||||
"trash", app->trash,
|
||||
"search-engines", app->search_engines,
|
||||
"history", app->history,
|
||||
NULL);
|
||||
midori_browser_add_uri (new_browser, uri);
|
||||
gtk_widget_show (GTK_WIDGET (new_browser));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -47,6 +48,7 @@ struct _MidoriBrowser
|
|||
GtkWidget* menu_tools;
|
||||
GtkWidget* menu_window;
|
||||
GtkWidget* popup_bookmark;
|
||||
GtkWidget* popup_history;
|
||||
GtkWidget* throbber;
|
||||
GtkWidget* navigationbar;
|
||||
GtkWidget* button_tab_new;
|
||||
|
@ -58,6 +60,7 @@ struct _MidoriBrowser
|
|||
|
||||
GtkWidget* panel;
|
||||
GtkWidget* panel_bookmarks;
|
||||
GtkWidget* panel_history;
|
||||
GtkWidget* panel_console;
|
||||
GtkWidget* panel_pageholder;
|
||||
GtkWidget* notebook;
|
||||
|
@ -77,6 +80,7 @@ struct _MidoriBrowser
|
|||
KatzeArray* proxy_array;
|
||||
KatzeArray* trash;
|
||||
KatzeArray* search_engines;
|
||||
KatzeArray* history;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW)
|
||||
|
@ -94,7 +98,8 @@ enum
|
|||
PROP_SETTINGS,
|
||||
PROP_BOOKMARKS,
|
||||
PROP_TRASH,
|
||||
PROP_SEARCH_ENGINES
|
||||
PROP_SEARCH_ENGINES,
|
||||
PROP_HISTORY
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -130,7 +135,9 @@ midori_browser_get_property (GObject* object,
|
|||
GValue* value,
|
||||
GParamSpec* pspec);
|
||||
|
||||
|
||||
static void
|
||||
midori_browser_new_history_item (MidoriBrowser* browser,
|
||||
KatzeItem* item);
|
||||
|
||||
static GtkAction*
|
||||
_action_by_name (MidoriBrowser* browser,
|
||||
|
@ -435,12 +442,24 @@ midori_view_notify_title_cb (GtkWidget* view,
|
|||
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))
|
||||
{
|
||||
|
@ -1094,6 +1113,23 @@ midori_browser_class_init (MidoriBrowserClass* class)
|
|||
_("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
|
||||
|
@ -1941,6 +1977,98 @@ midori_panel_bookmarks_popup_menu_cb (GtkWidget* widget,
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -2131,6 +2259,70 @@ _action_bookmark_add_activate (GtkAction* action,
|
|||
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)
|
||||
|
@ -2419,6 +2611,120 @@ _action_bookmark_edit_activate (GtkAction* action,
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -2601,7 +2907,18 @@ static const GtkActionEntry entries[] = {
|
|||
{ "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",
|
||||
|
@ -2822,6 +3139,16 @@ static const gchar* ui_markup =
|
|||
"<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
|
||||
|
@ -2862,6 +3189,7 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
browser->bookmarks = NULL;
|
||||
browser->trash = NULL;
|
||||
browser->search_engines = NULL;
|
||||
browser->history = NULL;
|
||||
|
||||
/* Setup the window metrics */
|
||||
g_signal_connect (browser, "realize",
|
||||
|
@ -2987,6 +3315,9 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
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 ();
|
||||
|
@ -3126,10 +3457,39 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
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 */
|
||||
|
@ -3298,6 +3658,8 @@ midori_browser_finalize (GObject* object)
|
|||
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);
|
||||
}
|
||||
|
@ -3513,6 +3875,115 @@ midori_browser_load_bookmarks (MidoriBrowser* browser)
|
|||
_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,
|
||||
|
@ -3578,6 +4049,12 @@ midori_browser_set_property (GObject* object,
|
|||
_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;
|
||||
|
@ -3624,6 +4101,9 @@ midori_browser_get_property (GObject* object,
|
|||
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;
|
||||
|
|
|
@ -5,5 +5,5 @@ obj = bld.create_obj ('cc', 'program')
|
|||
obj.target = 'midori'
|
||||
obj.includes = '.. ../katze'
|
||||
obj.find_sources_in_dirs ('.')
|
||||
obj.uselib = 'UNIQUE GIO GTK GTKSOURCEVIEW WEBKIT LIBXML'
|
||||
obj.uselib = 'UNIQUE GIO GTK GTKSOURCEVIEW SQLITE WEBKIT LIBXML'
|
||||
obj.uselib_local = 'katze'
|
||||
|
|
1
wscript
1
wscript
|
@ -110,6 +110,7 @@ def configure (conf):
|
|||
|
||||
conf.check_pkg ('gtk+-2.0', destvar='GTK', vnum='2.6.0', mandatory=True)
|
||||
conf.check_pkg ('gtksourceview-2.0', destvar='GTKSOURCEVIEW', vnum='2.0', mandatory=False)
|
||||
conf.check_pkg ('sqlite3', destvar='SQLITE', vnum='3.0', mandatory=False)
|
||||
conf.check_pkg ('webkit-1.0', destvar='WEBKIT', vnum='0.1', mandatory=True)
|
||||
conf.check_pkg ('libxml-2.0', destvar='LIBXML', vnum='2.6', mandatory=True)
|
||||
|
||||
|
|
Loading…
Reference in a new issue