]> spindle.queued.net Git - midori/commitdiff
Implement navigation history backed by sqlite
authorDale Whittaker <dayul@users.sf.net>
Tue, 7 Oct 2008 00:19:33 +0000 (02:19 +0200)
committerChristian Dywan <christian@twotoasts.de>
Tue, 7 Oct 2008 00:19:33 +0000 (02:19 +0200)
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.

configure.in
katze/katze-item.c
katze/katze-item.h
katze/katze-list.c
katze/katze-list.h
midori/main.c
midori/midori-app.c
midori/midori-browser.c
midori/wscript_build
wscript

index 777efd0818aaf4f1b0bcf7e382c32d50b501e4c2..fa102248102caee7074e467625649dea80b6f5b5 100644 (file)
@@ -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)
index f71d8d05ee980078cfc5ed9a15f53df0ef8f1353..46e0b8a028b20203151fb3c98a8a26dd755ac713 100644 (file)
@@ -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"); */
 }
+
index 7a921c975aaea520eae851e24af63cab61136bc5..8014b57aa860008fb0dfd15ad3e490c7ae109b0f 100644 (file)
@@ -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);
 
index 15bb0e1ea03137e52a0a40c0670a9700351be502..cb0fe80d97817a9406ae4dae7a751205a906b5b1 100644 (file)
@@ -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);
 }
index 0e2570dbe4daf5dea104cf932e5a6079c5e4fdb2..4d5d9d93cec5cc1e5f51a29e895da5d754d6bea2 100644 (file)
@@ -50,6 +50,9 @@ struct _KatzeListClass
     void
     (*remove_item)            (KatzeList* list,
                                gpointer   item);
+    void
+    (*clear)                  (KatzeList* list);
+
 };
 
 GType
index dfd6f602a08d86197df1ef7f1210e59ef8af14bb..bb6e4ed3d242d5a9d47905644458cbdd0e3c220e 100644 (file)
@@ -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
 #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))
index d5db66fb6dd416596c7f9db4a0c2edbfb8d378f4..4c77f0c8089a315c2b6783db4c3c895cda78093f 100644 (file)
@@ -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));
index 24426dbcff31c5cf0421a6a7eeafaedf8f712a08..0608ed577c1d33a91182d603f6042c8b6a8fd48d 100644 (file)
@@ -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;
index cc6435cf3eb9f615102bbdced6a0ca3ac8000e92..0dfb01a32af1bb0ad145690fd20798ae0d39cc09 100644 (file)
@@ -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'
diff --git a/wscript b/wscript
index 782d81745be050c2a48fb98e0fc2b6265702e3e5..76e1c4dae3d082e77314af610105dee0cfa4fabf 100644 (file)
--- a/wscript
+++ b/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)