[Xfce4-commits] <midori:master> Bookmarks: Database structure improved

Christian Dywan noreply at xfce.org
Wed Jun 20 01:20:01 CEST 2012


Updating branch refs/heads/master
         to f840f0508cc9d7bf5f2cb4dd2205dc5234d7e138 (commit)
       from bc3792651604bb8380f6c04cd5b586c6fe252f66 (commit)

commit f840f0508cc9d7bf5f2cb4dd2205dc5234d7e138
Author: Oliver Hanraths <helloolli at gmx.net>
Date:   Sat Jun 16 01:06:58 2012 +0200

    Bookmarks: Database structure improved
    
    The new format uses bookmarks_v2.db.
    
    We require sqlite 3.6.19 now due to foreign keys.
    
    Fixes: https://bugs.launchpad.net/midori/+bug/836707

 midori/main.c             |   15 +--
 midori/midori-array.c     |   24 +++--
 midori/midori-bookmarks.c |  275 ++++++++++++++++++++++++++++++++++++++++-----
 midori/midori-bookmarks.h |    1 -
 midori/midori-browser.c   |  128 +++++++++++++++-------
 panels/midori-bookmarks.c |  212 ++++++++++++++++++++++++++---------
 panels/midori-bookmarks.h |   18 ++-
 wscript                   |    2 +-
 8 files changed, 524 insertions(+), 151 deletions(-)

diff --git a/midori/main.c b/midori/main.c
index 53dfa03..b53ad98 100644
--- a/midori/main.c
+++ b/midori/main.c
@@ -434,7 +434,6 @@ midori_history_clear_cb (KatzeArray* array,
 static gboolean
 midori_history_initialize (KatzeArray*  array,
                            const gchar* filename,
-                           const gchar* bookmarks_filename,
                            char**       errmsg)
 {
     sqlite3* db;
@@ -442,6 +441,9 @@ midori_history_initialize (KatzeArray*  array,
     sqlite3_stmt* stmt;
     gint result;
     gchar* sql;
+    gchar* bookmarks_filename;
+
+    g_return_val_if_fail (errmsg != NULL, FALSE);
 
     if (sqlite3_open (filename, &db) != SQLITE_OK)
     {
@@ -493,7 +495,9 @@ midori_history_initialize (KatzeArray*  array,
                       "COMMIT;",
                       NULL, NULL, errmsg);
 
+    bookmarks_filename = build_config_filename ("bookmarks_v2.db");
     sql = g_strdup_printf ("ATTACH DATABASE '%s' AS bookmarks", bookmarks_filename);
+    g_free (bookmarks_filename);
     sqlite3_exec (db, sql, NULL, NULL, errmsg);
     g_free (sql);
     g_object_set_data (G_OBJECT (array), "db", db);
@@ -1900,9 +1904,7 @@ main (int    argc,
     gchar** extensions;
     MidoriWebSettings* settings;
     gchar* config_file;
-    gchar* bookmarks_file;
     GKeyFile* speeddial;
-    gboolean bookmarks_exist;
     MidoriStartup load_on_startup;
     KatzeArray* search_engines;
     KatzeArray* bookmarks;
@@ -2347,10 +2349,8 @@ main (int    argc,
     midori_startup_timer ("Search read: \t%f");
 
     bookmarks = katze_array_new (KATZE_TYPE_ARRAY);
-    bookmarks_file = g_build_filename (config, "bookmarks.db", NULL);
-    bookmarks_exist = g_access (bookmarks_file, F_OK) == 0;
     errmsg = NULL;
-    if ((db = midori_bookmarks_initialize (bookmarks, bookmarks_file, &errmsg)) == NULL)
+    if ((db = midori_bookmarks_initialize (bookmarks, &errmsg)) == NULL)
     {
         g_string_append_printf (error_messages,
             _("Bookmarks couldn't be loaded: %s\n"), errmsg);
@@ -2396,13 +2396,12 @@ main (int    argc,
     katze_assign (config_file, g_build_filename (config, "history.db", NULL));
 
     errmsg = NULL;
-    if (!midori_history_initialize (history, config_file, bookmarks_file, &errmsg))
+    if (!midori_history_initialize (history, config_file, &errmsg))
     {
         g_string_append_printf (error_messages,
             _("The history couldn't be loaded: %s\n"), errmsg);
         errmsg = NULL;
     }
-    g_free (bookmarks_file);
     midori_startup_timer ("History read: \t%f");
 
     error = NULL;
diff --git a/midori/midori-array.c b/midori/midori-array.c
index 7ba6c62..aa10715 100644
--- a/midori/midori-array.c
+++ b/midori/midori-array.c
@@ -982,24 +982,26 @@ katze_item_set_value_from_column (sqlite3_stmt* stmt,
         item->added = date;
     }
     else if (g_str_equal (name, "day") || g_str_equal (name, "app")
-          || g_str_equal (name, "toolbar"))
+          || g_str_equal (name, "toolbar") || g_str_equal (name, "id")
+          || g_str_equal (name, "parentid") || g_str_equal (name, "seq")
+          || g_str_equal (name, "pos_panel") || g_str_equal (name, "pos_bar"))
     {
         gint value;
         value = sqlite3_column_int64 (stmt, column);
         katze_item_set_meta_integer (item, name, value);
     }
-    else if (g_str_equal (name, "folder"))
-    {
-        const unsigned char* folder;
-        folder = sqlite3_column_text (stmt, column);
-        katze_item_set_meta_string (item, name, (gchar*)folder);
-    }
     else if (g_str_equal (name, "desc"))
     {
         const unsigned char* text;
         text = sqlite3_column_text (stmt, column);
         item->text =  g_strdup ((gchar*)text);
     }
+    else if (g_str_equal (name, "sql"))
+    {
+        const unsigned char* sql;
+        sql = sqlite3_column_text (stmt, column);
+        katze_item_set_meta_string (item, name, (gchar*)sql);
+    }
     else
         g_warn_if_reached ();
 }
@@ -1102,7 +1104,7 @@ midori_array_query_recursive (KatzeArray*  bookmarks,
         return NULL;
 
     sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s "
-                              "ORDER BY title DESC", fields, condition);
+                              "ORDER BY (uri='') ASC, title DESC", fields, condition);
     if (strstr (condition, "%q"))
     {
         sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");
@@ -1120,10 +1122,14 @@ midori_array_query_recursive (KatzeArray*  bookmarks,
     {
         if (KATZE_ITEM_IS_FOLDER (item))
         {
+            gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
+                katze_item_get_meta_integer (item, "id"));
             KatzeArray* subarray = midori_array_query_recursive (bookmarks,
-                fields, "folder='%q'", item->name, TRUE);
+                fields, "parentid=%q", parentid, TRUE);
             katze_item_set_name (KATZE_ITEM (subarray), item->name);
             katze_array_add_item (array, subarray);
+
+            g_free (parentid);
         }
     }
     g_list_free (list);
diff --git a/midori/midori-bookmarks.c b/midori/midori-bookmarks.c
index 59865fb..db9c5c7 100644
--- a/midori/midori-bookmarks.c
+++ b/midori/midori-bookmarks.c
@@ -13,7 +13,9 @@
 #include "midori-bookmarks.h"
 #include "panels/midori-bookmarks.h"
 #include "midori-array.h"
+#include "sokoke.h"
 
+#include <glib/gstdio.h>
 #include <glib/gi18n.h>
 
 #ifdef G_ENABLE_DEBUG
@@ -29,7 +31,7 @@ midori_bookmarks_add_item_cb (KatzeArray* array,
                               sqlite3*    db)
 {
     midori_bookmarks_insert_item_db (db, item,
-        katze_item_get_meta_string (item, "folder"));
+        katze_item_get_meta_integer (item, "parentid"));
 }
 
 void
@@ -40,19 +42,10 @@ midori_bookmarks_remove_item_cb (KatzeArray* array,
     gchar* sqlcmd;
     char* errmsg = NULL;
 
-    if (KATZE_ITEM_IS_BOOKMARK (item))
-        sqlcmd = sqlite3_mprintf (
-            "DELETE FROM bookmarks WHERE uri = '%q' "
-            " AND folder = '%q'",
-            katze_item_get_uri (item),
-            katze_str_non_null (katze_item_get_meta_string (item, "folder")));
 
-    else
-       sqlcmd = sqlite3_mprintf (
-            "DELETE FROM bookmarks WHERE title = '%q'"
-            " AND folder = '%q'",
-            katze_item_get_name (item),
-            katze_str_non_null (katze_item_get_meta_string (item, "folder")));
+    sqlcmd = sqlite3_mprintf (
+            "DELETE FROM bookmarks WHERE id = %" G_GINT64_FORMAT ";",
+            katze_item_get_meta_integer (item, "id"));
 
     if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
     {
@@ -63,20 +56,102 @@ midori_bookmarks_remove_item_cb (KatzeArray* array,
     sqlite3_free (sqlcmd);
 }
 
+#define _APPEND_TO_SQL_ERRORMSG(custom_errmsg) \
+    do { \
+        if (sql_errmsg) \
+        { \
+            g_string_append_printf (errmsg_str, "%s : %s\n", custom_errmsg, sql_errmsg); \
+            sqlite3_free (sql_errmsg); \
+        } \
+        else \
+            g_string_append (errmsg_str, custom_errmsg); \
+    } while (0)
+
+gboolean
+midori_bookmarks_import_from_old_db (sqlite3*     db,
+                                     const gchar* oldfile,
+                                     gchar**      errmsg)
+{
+    gint sql_errcode;
+    gboolean failure = FALSE;
+    gchar* sql_errmsg = NULL;
+    GString* errmsg_str = g_string_new (NULL);
+    gchar* attach_stmt = sqlite3_mprintf ("ATTACH DATABASE %Q AS old_db;", oldfile);
+    const gchar* convert_stmts =
+        "BEGIN TRANSACTION;"
+        "INSERT INTO main.bookmarks (parentid, title, uri, desc, app, toolbar) "
+        "SELECT NULL AS parentid, title, uri, desc, app, toolbar "
+        "FROM old_db.bookmarks;"
+        "UPDATE main.bookmarks SET parentid = ("
+        "SELECT id FROM main.bookmarks AS b1 WHERE b1.title = ("
+        "SELECT folder FROM old_db.bookmarks WHERE title = main.bookmarks.title));"
+        "COMMIT;";
+    const gchar* detach_stmt = "DETACH DATABASE old_db;";
+
+    *errmsg = NULL;
+    sql_errcode = sqlite3_exec (db, attach_stmt, NULL, NULL, &sql_errmsg);
+    sqlite3_free (attach_stmt);
+
+    if (sql_errcode != SQLITE_OK)
+    {
+        _APPEND_TO_SQL_ERRORMSG (_("failed to ATTACH old db"));
+        goto convert_failed;
+    }
+
+    if (sqlite3_exec (db, convert_stmts, NULL, NULL, &sql_errmsg) != SQLITE_OK)
+    {
+        failure = TRUE;
+        _APPEND_TO_SQL_ERRORMSG (_("failed to import from old db"));
+
+        /* try to get back to previous state */
+        if (sqlite3_exec (db, "ROLLBACK TRANSACTION;", NULL, NULL, &sql_errmsg) != SQLITE_OK)
+            _APPEND_TO_SQL_ERRORMSG (_("failed to rollback the transaction"));
+    }
+
+    if (sqlite3_exec (db, detach_stmt, NULL, NULL, &sql_errmsg) != SQLITE_OK)
+        _APPEND_TO_SQL_ERRORMSG (_("failed to DETACH "));
+
+    if (failure)
+    {
+    convert_failed:
+        *errmsg = g_string_free (errmsg_str, FALSE);
+        g_print ("ERRORR: %s\n", errmsg_str->str);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+#undef _APPEND_TO_SQL_ERRORMSG
+
 sqlite3*
 midori_bookmarks_initialize (KatzeArray*  array,
-                             const gchar* filename,
                              char**       errmsg)
 {
     sqlite3* db;
+    gchar* oldfile;
+    gchar* newfile;
+    gboolean newfile_did_exist, oldfile_exists;
+    const gchar* create_stmt;
+    gchar* sql_errmsg = NULL;
+    gchar* import_errmsg = NULL;
 
-    if (sqlite3_open (filename, &db) != SQLITE_OK)
+    g_return_val_if_fail (errmsg != NULL, NULL);
+
+    oldfile = g_build_filename (sokoke_set_config_dir (NULL), "bookmarks.db", NULL);
+    oldfile_exists = g_access (oldfile, F_OK) == 0;
+    newfile = g_build_filename (sokoke_set_config_dir (NULL), "bookmarks_v2.db", NULL);
+    newfile_did_exist = g_access (newfile, F_OK) == 0;
+
+    /* sqlite3_open will create the file if it did not exists already */
+    if (sqlite3_open (newfile, &db) != SQLITE_OK)
     {
-        if (errmsg)
-            *errmsg = g_strdup_printf (_("Failed to open database: %s\n"),
-                                       sqlite3_errmsg (db));
-        sqlite3_close (db);
-        return NULL;
+        if (db)
+            *errmsg = g_strdup_printf (_("failed to open database: %s\n"),
+                    sqlite3_errmsg (db));
+        else
+            *errmsg = g_strdup (_("failed to open database\n"));
+
+        goto init_failed;
     }
 
 #ifdef G_ENABLE_DEBUG
@@ -84,17 +159,155 @@ midori_bookmarks_initialize (KatzeArray*  array,
         sqlite3_trace (db, midori_bookmarks_dbtracer, NULL);
 #endif
 
-    if (sqlite3_exec (db,
-                      "CREATE TABLE IF NOT EXISTS "
-                      "bookmarks (uri text, title text, folder text, "
-                      "desc text, app integer, toolbar integer);",
-                      NULL, NULL, errmsg) != SQLITE_OK)
+    create_stmt =     /* Table structure */
+        "CREATE TABLE IF NOT EXISTS bookmarks "
+        "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
+        "parentid INTEGER DEFAULT NULL, "
+        "title TEXT, uri TEXT, desc TEXT, app INTEGER, toolbar INTEGER, "
+        "pos_panel INTEGER, pos_bar INTEGER, "
+        "created DATE DEFAULT CURRENT_TIMESTAMP, "
+        "last_visit DATE, visit_count INTEGER DEFAULT 0, "
+        "nick TEXT, "
+        "FOREIGN KEY(parentid) REFERENCES bookmarks(id) "
+        "ON DELETE CASCADE); PRAGMA foreign_keys = ON;"
+
+        /* trigger: insert panel position */
+        "CREATE TRIGGER IF NOT EXISTS bookmarkInsertPosPanel "
+        "AFTER INSERT ON bookmarks FOR EACH ROW "
+        "BEGIN UPDATE bookmarks SET pos_panel = ("
+        "SELECT ifnull(MAX(pos_panel),0)+1 FROM bookmarks WHERE "
+        "(NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
+        "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
+        "WHERE id = NEW.id; END;"
+
+        /* trigger: insert Bookmarkbar position */
+        "CREATE TRIGGER IF NOT EXISTS bookmarkInsertPosBar "
+        "AFTER INSERT ON bookmarks FOR EACH ROW WHEN NEW.toolbar=1 "
+        "BEGIN UPDATE bookmarks SET pos_bar = ("
+        "SELECT ifnull(MAX(pos_bar),0)+1 FROM bookmarks WHERE "
+        "((NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
+        "OR (NEW.parentid IS NULL AND parentid IS NULL)) AND toolbar=1) "
+        "WHERE id = NEW.id; END;"
+
+        /* trigger: update panel position */
+        "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosPanel "
+        "BEFORE UPDATE OF parentid ON bookmarks FOR EACH ROW "
+        "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
+        "AND NEW.parentid IS NOT OLD.parentid) OR "
+        "((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
+        "AND NEW.parentid!=OLD.parentid) "
+        "BEGIN UPDATE bookmarks SET pos_panel = pos_panel-1 "
+        "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
+        "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_panel > OLD.pos_panel; "
+        "UPDATE bookmarks SET pos_panel = ("
+        "SELECT ifnull(MAX(pos_panel),0)+1 FROM bookmarks "
+        "WHERE (NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
+        "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
+        "WHERE id = OLD.id; END;"
+
+        /* trigger: update Bookmarkbar position */
+        "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosBar0 "
+        "AFTER UPDATE OF parentid, toolbar ON bookmarks FOR EACH ROW "
+        "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
+        "AND NEW.parentid IS NOT OLD.parentid) "
+        "OR ((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
+        "AND NEW.parentid!=OLD.parentid) OR (OLD.toolbar=1 AND NEW.toolbar=0) "
+        "BEGIN UPDATE bookmarks SET pos_bar = NULL WHERE id = NEW.id; "
+        "UPDATE bookmarks SET pos_bar = pos_bar-1 "
+        "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
+        "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_bar > OLD.pos_bar; END;"
+
+        /* trigger: update Bookmarkbar position */
+        "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosBar1 "
+        "BEFORE UPDATE OF parentid, toolbar ON bookmarks FOR EACH ROW "
+        "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
+        "AND NEW.parentid IS NOT OLD.parentid) OR "
+        "((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
+        "AND NEW.parentid!=OLD.parentid) OR (OLD.toolbar=0 AND NEW.toolbar=1) "
+        "BEGIN UPDATE bookmarks SET pos_bar = ("
+        "SELECT ifnull(MAX(pos_bar),0)+1 FROM bookmarks WHERE "
+        "(NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
+        "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
+        "WHERE id = OLD.id; END;"
+
+        /* trigger: delete panel position */
+        "CREATE TRIGGER IF NOT EXISTS bookmarkDeletePosPanel "
+        "AFTER DELETE ON bookmarks FOR EACH ROW "
+        "BEGIN UPDATE bookmarks SET pos_panel = pos_panel-1 "
+        "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
+        "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_panel > OLD.pos_panel; END;"
+
+        /* trigger: delete Bookmarkbar position */
+        "CREATE TRIGGER IF NOT EXISTS bookmarkDeletePosBar "
+        "AFTER DELETE ON bookmarks FOR EACH ROW WHEN OLD.toolbar=1 "
+        "BEGIN UPDATE bookmarks SET pos_bar = pos_bar-1 "
+        "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
+        "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_bar > OLD.pos_bar; END;";
+
+
+    if (newfile_did_exist)
+    {
+        /* we are done */
+        goto init_success;
+    }
+    else
+    {
+        /* initial creation */
+        if (sqlite3_exec (db, create_stmt, NULL, NULL, &sql_errmsg) != SQLITE_OK)
+        {
+
+            if (errmsg)
+            {
+                if (sql_errmsg)
+                {
+                    *errmsg = g_strdup_printf (_("could not create bookmarks table: %s\n"), sql_errmsg);
+                    sqlite3_free (sql_errmsg);
+                }
+                else
+                    *errmsg = g_strdup (_("could not create bookmarks table"));
+            }
+
+            /* we can as well remove the new file */
+            g_unlink (newfile);
+            goto init_failed;
+        }
+
+    }
+
+    if (oldfile_exists)
+        /* import from old db */
+        if (!midori_bookmarks_import_from_old_db (db, oldfile, &import_errmsg))
+        {
+            if (errmsg)
+            {
+                if (import_errmsg)
+                {
+                    *errmsg = g_strdup_printf (_("could not import from old database: %s\n"), import_errmsg);
+                    g_free (import_errmsg);
+                }
+                else
+                    *errmsg = g_strdup_printf (_("could not import from old database"));
+            }
+        }
+
+    init_success:
+        g_free (newfile);
+        g_free (oldfile);
+        g_signal_connect (array, "add-item",
+                          G_CALLBACK (midori_bookmarks_add_item_cb), db);
+        g_signal_connect (array, "remove-item",
+                          G_CALLBACK (midori_bookmarks_remove_item_cb), db);
+
+        return db;
+
+    init_failed:
+        g_free (newfile);
+        g_free (oldfile);
+
+        if (db)
+            sqlite3_close (db);
+
         return NULL;
-    g_signal_connect (array, "add-item",
-                      G_CALLBACK (midori_bookmarks_add_item_cb), db);
-    g_signal_connect (array, "remove-item",
-                      G_CALLBACK (midori_bookmarks_remove_item_cb), db);
-    return db;
 }
 
 void
@@ -112,5 +325,5 @@ midori_bookmarks_import (const gchar* filename,
         g_error_free (error);
         return;
     }
-    midori_bookmarks_import_array_db (db, bookmarks, "");
+    midori_bookmarks_import_array_db (db, bookmarks, 0);
 }
diff --git a/midori/midori-bookmarks.h b/midori/midori-bookmarks.h
index a5f38ce..e4a3f8d 100644
--- a/midori/midori-bookmarks.h
+++ b/midori/midori-bookmarks.h
@@ -25,7 +25,6 @@ midori_bookmarks_remove_item_cb (KatzeArray* array,
 
 sqlite3*
 midori_bookmarks_initialize (KatzeArray*  array,
-                             const gchar* filename,
                              char**       errmsg);
 
 void
diff --git a/midori/midori-browser.c b/midori/midori-browser.c
index dba7b75..da3a04d 100644
--- a/midori/midori-browser.c
+++ b/midori/midori-browser.c
@@ -173,7 +173,11 @@ midori_browser_get_property (GObject*    object,
 void
 midori_bookmarks_import_array_db (sqlite3*    db,
                                   KatzeArray* array,
-                                  gchar*      folder);
+                                  gint64      parentid);
+
+gboolean
+midori_bookmarks_update_item_db (sqlite3*   db,
+                                 KatzeItem* item);
 
 void
 midori_browser_open_bookmark (MidoriBrowser* browser,
@@ -659,9 +663,10 @@ midori_view_notify_statusbar_text_cb (GtkWidget*     view,
 }
 
 static GtkWidget*
-midori_bookmark_folder_button_new (KatzeArray*  array,
-                                   gboolean     new_bookmark,
-                                   const gchar* selected)
+midori_bookmark_folder_button_new (KatzeArray* array,
+                                   gboolean    new_bookmark,
+                                   gint64      selected,
+                                   gint64      parentid)
 {
     GtkListStore* model;
     GtkWidget* combo;
@@ -670,16 +675,16 @@ midori_bookmark_folder_button_new (KatzeArray*  array,
     sqlite3* db;
     sqlite3_stmt* statement;
     gint result;
-    const gchar* sqlcmd = "SELECT title from bookmarks where uri=''";
+    const gchar* sqlcmd = "SELECT title, id FROM bookmarks WHERE uri='' ORDER BY title ASC";
 
-    model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+    model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT64);
     combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model));
     renderer = gtk_cell_renderer_text_new ();
     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
     gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "text", 0);
     gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "ellipsize", 1);
     gtk_list_store_insert_with_values (model, NULL, G_MAXINT,
-        0, _("Toplevel folder"), 1, PANGO_ELLIPSIZE_END, -1);
+        0, _("Toplevel folder"), 1, PANGO_ELLIPSIZE_END, 2, (gint64)0, -1);
     gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
 
     db = g_object_get_data (G_OBJECT (array), "db");
@@ -689,34 +694,45 @@ midori_bookmark_folder_button_new (KatzeArray*  array,
     while ((result = sqlite3_step (statement)) == SQLITE_ROW)
     {
         const unsigned char* name = sqlite3_column_text (statement, 0);
-        gtk_list_store_insert_with_values (model, NULL, G_MAXINT,
-            0, name, 1, PANGO_ELLIPSIZE_END, -1);
-        if (!new_bookmark && !g_strcmp0 (selected, (gchar*)name))
-            gtk_combo_box_set_active (GTK_COMBO_BOX (combo), n);
-        n++;
+        gint64 id = sqlite3_column_int64 (statement, 1);
+
+        /* do not show the folder itself */
+        if (id != selected)
+        {
+            gtk_list_store_insert_with_values (model, NULL, G_MAXINT,
+                0, name, 1, PANGO_ELLIPSIZE_END, 2, id, -1);
+
+            if (!new_bookmark && id == parentid)
+                gtk_combo_box_set_active (GTK_COMBO_BOX (combo), n);
+            n++;
+        }
     }
     if (n < 2)
         gtk_widget_set_sensitive (combo, FALSE);
     return combo;
 }
 
-static gchar*
+static gint64
 midori_bookmark_folder_button_get_active (GtkWidget* combo)
 {
-    gchar* selected = NULL;
+    gint64 id;
     GtkTreeIter iter;
 
-    g_return_val_if_fail (GTK_IS_COMBO_BOX (combo), NULL);
+    g_return_val_if_fail (GTK_IS_COMBO_BOX (combo), 0);
 
     if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter))
     {
+        gchar* selected = NULL;
         GtkTreeModel* model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
-        gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &selected, -1);
+        gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &selected, 2, &id, -1);
+
         if (g_str_equal (selected, _("Toplevel folder")))
-            katze_assign (selected, g_strdup (""));
+            id = 0;
+
+        g_free (selected);
     }
 
-    return selected;
+    return id;
 }
 
 static void
@@ -861,7 +877,8 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
     gtk_size_group_add_widget (sizegroup, label);
     gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
     combo_folder = midori_bookmark_folder_button_new (browser->bookmarks,
-        new_bookmark, katze_item_get_meta_string (bookmark, "folder"));
+        new_bookmark, katze_item_get_meta_integer (bookmark, "id"),
+        katze_item_get_meta_integer (bookmark, "parentid"));
     gtk_box_pack_start (GTK_BOX (hbox), combo_folder, TRUE, TRUE, 0);
     gtk_container_add (GTK_CONTAINER (content_area), hbox);
     gtk_widget_show_all (hbox);
@@ -912,10 +929,7 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
     gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
     {
-        gchar* selected;
-
-        if (!new_bookmark)
-            katze_array_remove_item (browser->bookmarks, bookmark);
+        gint64 selected;
 
         katze_item_set_name (bookmark,
             gtk_entry_get_text (GTK_ENTRY (entry_title)));
@@ -930,13 +944,16 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
         }
 
         selected = midori_bookmark_folder_button_get_active (combo_folder);
-        katze_item_set_meta_string (bookmark, "folder", selected);
-        katze_array_add_item (browser->bookmarks, bookmark);
+        katze_item_set_meta_integer (bookmark, "parentid", selected);
+
+        if (new_bookmark)
+            katze_array_add_item (browser->bookmarks, bookmark);
+        else
+            midori_bookmarks_update_item_db (db, bookmark);
 
         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_toolbar)))
             if (!gtk_widget_get_visible (browser->bookmarkbar))
                 _action_set_active (browser, "Bookmarkbar", TRUE);
-        g_free (selected);
         return_status = TRUE;
     }
     if (gtk_widget_get_visible (browser->bookmarkbar))
@@ -3041,14 +3058,35 @@ _action_bookmarks_populate_folder (GtkAction*     action,
                                    KatzeArray*    folder,
                                    MidoriBrowser* browser)
 {
-    const gchar* folder_name;
+    gint64 id;
     KatzeArray* bookmarks;
     GtkWidget* menuitem;
 
-    folder_name = katze_item_get_name (KATZE_ITEM (folder));
-    if (!(bookmarks = midori_array_query (browser->bookmarks,
-          "uri, title, app, folder", "folder = '%q'", folder_name)))
-        return FALSE;
+    id = katze_item_get_meta_integer (KATZE_ITEM (folder), "id");
+
+    if (id == -1)
+    {
+        if (!(bookmarks = midori_array_query (browser->bookmarks,
+          "id, title, parentid, uri, app, pos_panel, pos_bar", "parentid is NULL", NULL)))
+        {
+            g_warning ("midori_array_query returned NULL)");
+            return FALSE;
+        }
+    }
+    else
+    {
+        gchar *parentid = g_strdup_printf ("%" G_GINT64_FORMAT, id);
+
+        if (!(bookmarks = midori_array_query (browser->bookmarks,
+              "id, title, parentid, uri, app, pos_panel, pos_bar", "parentid = %q", parentid)))
+        {
+            g_warning ("midori_array_query returned NULL (id='%s')", parentid);
+            g_free (parentid);
+            return FALSE;
+        }
+
+        g_free (parentid);
+    }
 
     /* Clear items from dummy array here */
     gtk_container_foreach (GTK_CONTAINER (menu),
@@ -4365,7 +4403,7 @@ _action_bookmarks_import_activate (GtkAction*     action,
     gtk_size_group_add_widget (sizegroup, label);
     gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
     combobox_folder = midori_bookmark_folder_button_new (browser->bookmarks,
-                                                         FALSE, NULL);
+                                                         FALSE, 0, 0);
     gtk_box_pack_start (GTK_BOX (hbox), combobox_folder, TRUE, TRUE, 0);
     gtk_container_add (GTK_CONTAINER (content_area), hbox);
     gtk_widget_show_all (hbox);
@@ -4375,7 +4413,7 @@ _action_bookmarks_import_activate (GtkAction*     action,
     {
         GtkTreeIter iter;
         gchar* path = NULL;
-        gchar* selected = NULL;
+        gint64 selected;
         GError* error;
         sqlite3* db = g_object_get_data (G_OBJECT (browser->bookmarks), "db");
 
@@ -4408,7 +4446,6 @@ _action_bookmarks_import_activate (GtkAction*     action,
         midori_bookmarks_import_array_db (db, bookmarks, selected);
         katze_array_update (browser->bookmarks);
         g_object_unref (bookmarks);
-        g_free (selected);
         g_free (path);
     }
     else
@@ -4465,7 +4502,7 @@ wrong_format:
 
     error = NULL;
     bookmarks = midori_array_query_recursive (browser->bookmarks,
-        "*", "folder='%q'", "", TRUE);
+        "*", "parentid IS NULL", NULL, TRUE);
     if (!midori_array_to_file (bookmarks, path, format, &error))
     {
         sokoke_message_dialog (GTK_MESSAGE_ERROR,
@@ -7044,9 +7081,10 @@ midori_bookmarkbar_populate (MidoriBrowser* browser)
                         gtk_separator_tool_item_new (), -1);
 
     array = midori_array_query (browser->bookmarks,
-        "uri, title, desc, app, folder, toolbar", "toolbar = 1", NULL);
+        "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL);
     if (!array)
     {
+        g_warning ("midori_array_query returned NULL");
         _action_set_sensitive (browser, "BookmarkAdd", FALSE);
         _action_set_sensitive (browser, "BookmarkFolderAdd", FALSE);
         return;
@@ -7058,10 +7096,22 @@ midori_bookmarkbar_populate (MidoriBrowser* browser)
             midori_bookmarkbar_insert_item (browser->bookmarkbar, item);
         else
         {
+            gint64 id = katze_item_get_meta_integer (item, "id");
+            gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT, id);
             KatzeArray* subfolder = midori_array_query (browser->bookmarks,
-                "uri, title, desc, app", "folder = '%q' AND uri != ''", katze_item_get_name (item));
-            katze_item_set_name (KATZE_ITEM (subfolder), katze_item_get_name (item));
-            midori_bookmarkbar_insert_item (browser->bookmarkbar, KATZE_ITEM (subfolder));
+                "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q AND uri != ''",
+                parentid);
+
+            if (subfolder)
+            {
+                katze_item_set_name (KATZE_ITEM (subfolder), katze_item_get_name (item));
+                katze_item_set_meta_integer (KATZE_ITEM (subfolder), "id", id);
+                midori_bookmarkbar_insert_item (browser->bookmarkbar, KATZE_ITEM (subfolder));
+            }
+            else
+                g_warning ("midori_array_query returned NULL (id='%s')", parentid);
+
+            g_free (parentid);
         }
     }
     _action_set_sensitive (browser, "BookmarkAdd", TRUE);
diff --git a/panels/midori-bookmarks.c b/panels/midori-bookmarks.c
index 390ebae..2f9ef4c 100644
--- a/panels/midori-bookmarks.c
+++ b/panels/midori-bookmarks.c
@@ -120,66 +120,87 @@ midori_bookmarks_get_stock_id (MidoriViewable* viewable)
     return STOCK_BOOKMARKS;
 }
 
+/* TODO: Function never used */
 void
-midori_bookmarks_export_array_db (sqlite3*     db,
-                                  KatzeArray*  array,
-                                  const gchar* folder)
+midori_bookmarks_export_array_db (sqlite3*    db,
+                                  KatzeArray* array,
+                                  gint64      parentid)
 {
     KatzeArray* root_array;
     KatzeArray* subarray;
     KatzeItem* item;
     GList* list;
+    gchar* parent_id;
 
-    if (!(root_array = midori_array_query (array, "*", "folder='%q'", folder)))
+    parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);
+    if (!(root_array = midori_array_query (array, "*", "parentid = %q", parent_id)))
+    {
+        g_free (parent_id);
         return;
+    }
     KATZE_ARRAY_FOREACH_ITEM_L (item, root_array, list)
     {
         if (KATZE_ITEM_IS_FOLDER (item))
         {
             subarray = katze_array_new (KATZE_TYPE_ARRAY);
             katze_item_set_name (KATZE_ITEM (subarray), katze_item_get_name (item));
-            midori_bookmarks_export_array_db (db, subarray, katze_item_get_name (item));
+            midori_bookmarks_export_array_db (db, subarray,
+                    katze_item_get_meta_integer (item, "parentid"));
             katze_array_add_item (array, subarray);
         }
         else
             katze_array_add_item (array, item);
     }
+
+    g_free (parent_id);
     g_list_free (list);
 }
 
 void
-midori_bookmarks_import_array_db (sqlite3*     db,
-                                  KatzeArray*  array,
-                                  const gchar* folder)
+midori_bookmarks_import_array_db (sqlite3*    db,
+                                  KatzeArray* array,
+                                  gint64      parentid)
 {
     GList* list;
     KatzeItem* item;
+    gint64 id;
 
     if (!db)
         return;
 
     KATZE_ARRAY_FOREACH_ITEM_L (item, array, list)
     {
+        id = midori_bookmarks_insert_item_db (db, item, parentid);
         if (KATZE_IS_ARRAY (item))
-            midori_bookmarks_import_array_db (db, KATZE_ARRAY (item), folder);
-        midori_bookmarks_insert_item_db (db, item, folder);
+            midori_bookmarks_import_array_db (db, KATZE_ARRAY (item), id);
     }
     g_list_free (list);
 }
 
 static KatzeArray*
 midori_bookmarks_read_from_db (MidoriBookmarks* bookmarks,
-                               const gchar*     folder,
+                               gint64           parentid,
                                const gchar*     keyword)
 {
     KatzeArray* array;
 
     if (keyword && *keyword)
         array = midori_array_query (bookmarks->array,
-           "uri, title, desc, app, toolbar, folder", "title LIKE '%%%q%%'", keyword);
+           "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword);
     else
-        array = midori_array_query (bookmarks->array,
-           "uri, title, desc, app, toolbar, folder", "folder = '%q'", folder);
+    {
+        if (parentid > 0)
+        {
+            gchar* parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);
+            array = midori_array_query (bookmarks->array,
+               "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id);
+
+            g_free (parent_id);
+        }
+        else
+            array = midori_array_query (bookmarks->array,
+               "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL);
+    }
     return array ? array : katze_array_new (KATZE_TYPE_ITEM);
 }
 
@@ -187,7 +208,7 @@ static void
 midori_bookmarks_read_from_db_to_model (MidoriBookmarks* bookmarks,
                                         GtkTreeStore*    model,
                                         GtkTreeIter*     parent,
-                                        const gchar*     folder,
+                                        gint64           parentid,
                                         const gchar*     keyword)
 {
     KatzeArray* array;
@@ -195,7 +216,7 @@ midori_bookmarks_read_from_db_to_model (MidoriBookmarks* bookmarks,
     KatzeItem* item;
     GtkTreeIter child;
 
-    array = midori_bookmarks_read_from_db (bookmarks, folder, keyword);
+    array = midori_bookmarks_read_from_db (bookmarks, parentid, keyword);
     katze_bookmark_populate_tree_view (array, model, parent);
     /* Remove invisible dummy row */
     last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent);
@@ -209,23 +230,30 @@ midori_bookmarks_read_from_db_to_model (MidoriBookmarks* bookmarks,
         g_object_unref (item);
 }
 
-void
-midori_bookmarks_insert_item_db (sqlite3*     db,
-                                 KatzeItem*   item,
-                                const gchar* folder)
+gint64
+midori_bookmarks_insert_item_db (sqlite3*   db,
+                                 KatzeItem* item,
+                                 gint64     parentid)
 {
     gchar* sqlcmd;
     char* errmsg = NULL;
     KatzeItem* old_parent;
-    const gchar* parent;
+    gchar* new_parentid;
+    gchar* id = NULL;
     const gchar* uri = NULL;
     const gchar* desc = NULL;
+    gint64 seq = 0;
 
     /* Bookmarks must have a name, import may produce invalid items */
-    g_return_if_fail (katze_item_get_name (item));
+    g_return_val_if_fail (katze_item_get_name (item), seq);
 
     if (!db)
-        return;
+        return seq;
+
+    if (katze_item_get_meta_integer (item, "id") > 0)
+        id = g_strdup_printf ("%" G_GINT64_FORMAT, katze_item_get_meta_integer(item, "id"));
+    else
+        id = g_strdup_printf ("NULL");
 
     if (KATZE_ITEM_IS_BOOKMARK (item))
         uri = katze_item_get_uri (item);
@@ -235,30 +263,57 @@ midori_bookmarks_insert_item_db (sqlite3*     db,
 
     /* Use folder, otherwise fallback to parent folder */
     old_parent = katze_item_get_parent (item);
-    if (folder && *folder)
-        parent = folder;
-    else if (old_parent && katze_item_get_name (old_parent))
-        parent = katze_item_get_name (old_parent);
+    if (parentid > 0)
+        new_parentid = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);
+    else if (old_parent && katze_item_get_meta_integer (old_parent, "id") > 0)
+        new_parentid = g_strdup_printf ("%" G_GINT64_FORMAT, katze_item_get_meta_integer (old_parent, "id"));
     else
-        parent = "";
+        new_parentid = g_strdup_printf ("NULL");
 
     sqlcmd = sqlite3_mprintf (
-            "INSERT into bookmarks (uri, title, desc, folder, toolbar, app) values"
-            " ('%q', '%q', '%q', '%q', %d, %d)",
-            uri ? uri : "",
+            "INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) "
+            "VALUES (%q, %q, '%q', '%q', '%q', %d, %d)",
+            id,
+            new_parentid,
             katze_item_get_name (item),
-            desc ? desc : "",
-            parent,
+            katze_str_non_null (uri),
+            katze_str_non_null (desc),
             katze_item_get_meta_boolean (item, "toolbar"),
             katze_item_get_meta_boolean (item, "app"));
 
-    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
+    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) == SQLITE_OK)
+    {
+        /* Get insert id */
+        if (g_str_equal (id, "NULL"))
+        {
+            KatzeArray* seq_array;
+
+            sqlite3_free (sqlcmd);
+            sqlcmd = sqlite3_mprintf (
+                    "SELECT seq FROM sqlite_sequence WHERE name = 'bookmarks'");
+
+            seq_array = katze_array_from_sqlite (db, sqlcmd);
+            if (katze_array_get_nth_item (seq_array, 0))
+            {
+                KatzeItem* seq_item = katze_array_get_nth_item (seq_array, 0);
+
+                seq = katze_item_get_meta_integer (seq_item, "seq");
+                katze_item_set_meta_integer (item, "id", seq);
+            }
+            g_object_unref (seq_array);
+        }
+    }
+    else
     {
         g_printerr (_("Failed to add bookmark item: %s\n"), errmsg);
         sqlite3_free (errmsg);
     }
 
     sqlite3_free (sqlcmd);
+    g_free (new_parentid);
+    g_free (id);
+
+    return seq;
 }
 
 static void
@@ -268,15 +323,9 @@ midori_bookmarks_add_item_cb (KatzeArray*      array,
 {
     GtkTreeModel* model;
     model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
-    if (!g_strcmp0 (katze_item_get_meta_string (item, "folder"), ""))
-        gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
-                                           NULL, NULL, G_MAXINT, 0, item, -1);
-    else
-    {
-        gtk_tree_store_clear (GTK_TREE_STORE (model));
-        midori_bookmarks_read_from_db_to_model (bookmarks,
-            GTK_TREE_STORE (model), NULL, NULL, bookmarks->filter);
-    }
+    gtk_tree_store_clear (GTK_TREE_STORE (model));
+    midori_bookmarks_read_from_db_to_model (bookmarks,
+        GTK_TREE_STORE (model), NULL, 0, bookmarks->filter);
 }
 
 static void
@@ -287,7 +336,7 @@ midori_bookmarks_remove_item_cb (KatzeArray*      array,
     GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
     gtk_tree_store_clear (GTK_TREE_STORE (model));
     midori_bookmarks_read_from_db_to_model (bookmarks,
-        GTK_TREE_STORE (model), NULL, NULL, bookmarks->filter);
+        GTK_TREE_STORE (model), NULL, 0, bookmarks->filter);
 }
 
 static void
@@ -297,7 +346,7 @@ midori_bookmarks_update_cb (KatzeArray*      array,
     GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
     gtk_tree_store_clear (GTK_TREE_STORE (model));
     midori_bookmarks_read_from_db_to_model (bookmarks,
-        GTK_TREE_STORE (model), NULL, NULL, bookmarks->filter);
+        GTK_TREE_STORE (model), NULL, 0, bookmarks->filter);
 }
 
 
@@ -310,7 +359,7 @@ midori_bookmarks_row_changed_cb (GtkTreeModel*    model,
     KatzeItem* item;
     GtkTreeIter parent;
     KatzeItem* new_parent = NULL;
-    const gchar* parent_name;
+    gint64 parentid;
 
     gtk_tree_model_get (model, iter, 0, &item, -1);
 
@@ -320,15 +369,15 @@ midori_bookmarks_row_changed_cb (GtkTreeModel*    model,
 
         /* Bookmarks must not be moved into non-folder items */
         if (!KATZE_ITEM_IS_FOLDER (new_parent))
-            parent_name = "";
+            parentid = 0;
         else
-            parent_name = katze_item_get_name (new_parent);
+            parentid = katze_item_get_meta_integer (new_parent, "id");
     }
     else
-        parent_name = "";
+        parentid = 0;
 
     katze_array_remove_item (bookmarks->array, item);
-    katze_item_set_meta_string (item, "folder", parent_name);
+    katze_item_set_meta_integer (item, "parentid", parentid);
     katze_array_add_item (bookmarks->array, item);
 
     g_object_unref (item);
@@ -359,14 +408,24 @@ midori_bookmarks_edit_clicked_cb (GtkWidget*       toolitem,
     {
         KatzeItem* item;
         MidoriBrowser* browser;
+        gint64 parentid;
 
         gtk_tree_model_get (model, &iter, 0, &item, -1);
 
         g_assert (!KATZE_ITEM_IS_SEPARATOR (item));
 
         browser = midori_browser_get_for_widget (bookmarks->treeview);
+        parentid = katze_item_get_meta_integer (item, "parentid");
         midori_browser_edit_bookmark_dialog_new (
             browser, item, FALSE, KATZE_ITEM_IS_FOLDER (item), NULL);
+
+        if (katze_item_get_meta_integer (item, "parentid") != parentid)
+        {
+            gtk_tree_store_clear (GTK_TREE_STORE (model));
+            midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model),
+                    NULL, 0, NULL);
+        }
+
         g_object_unref (item);
     }
 }
@@ -382,6 +441,47 @@ midori_bookmarks_toolbar_update (MidoriBookmarks *bookmarks)
     gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->edit), selected);
 }
 
+gboolean
+midori_bookmarks_update_item_db (sqlite3*   db,
+                                 KatzeItem* item)
+{
+    gchar* sqlcmd;
+    char* errmsg = NULL;
+    gchar* parentid;
+    gboolean updated;
+
+    if (katze_item_get_meta_integer (item, "parentid") > 0)
+        parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
+                                    katze_item_get_meta_integer (item, "parentid"));
+    else
+        parentid = g_strdup_printf ("NULL");
+
+    sqlcmd = sqlite3_mprintf (
+            "UPDATE bookmarks SET "
+            "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d "
+            "WHERE id = %" G_GINT64_FORMAT ";",
+            parentid,
+            katze_item_get_name (item),
+            katze_str_non_null (katze_item_get_uri (item)),
+            katze_str_non_null (katze_item_get_meta_string (item, "desc")),
+            katze_item_get_meta_boolean (item, "toolbar"),
+            katze_item_get_meta_boolean (item, "app"),
+            katze_item_get_meta_integer (item, "id"));
+
+    updated = TRUE;
+    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
+    {
+        updated = FALSE;
+        g_printerr (_("Failed to update bookmark : %s\n"), errmsg);
+        sqlite3_free (errmsg);
+    }
+
+    sqlite3_free (sqlcmd);
+    g_free (parentid);
+
+    return updated;
+}
+
 static void
 midori_bookmarks_delete_clicked_cb (GtkWidget*       toolitem,
                                     MidoriBookmarks* bookmarks)
@@ -496,8 +596,8 @@ midori_bookmarks_set_app (MidoriBookmarks* bookmarks,
 
     g_object_ref (app);
     bookmarks->array = katze_object_get_object (app, "bookmarks");
-    midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), NULL, "", NULL);
-    g_signal_connect (bookmarks->array, "add-item",
+    midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), NULL, 0, NULL);
+    g_signal_connect_after (bookmarks->array, "add-item",
                       G_CALLBACK (midori_bookmarks_add_item_cb), bookmarks);
     g_signal_connect (bookmarks->array, "remove-item",
                       G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks);
@@ -687,7 +787,9 @@ midori_bookmarks_open_in_tab_activate_cb (GtkWidget*       menuitem,
         KatzeItem* child;
         KatzeArray* array;
 
-        array = midori_bookmarks_read_from_db (bookmarks, katze_item_get_name (item), NULL);
+        array = midori_bookmarks_read_from_db (bookmarks,
+                katze_item_get_meta_integer (item, "parentid"), NULL);
+
         g_return_if_fail (KATZE_IS_ARRAY (array));
         KATZE_ARRAY_FOREACH_ITEM (child, array)
         {
@@ -843,7 +945,7 @@ midori_bookmarks_row_expanded_cb (GtkTreeView*     treeview,
     model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
     gtk_tree_model_get (model, iter, 0, &item, -1);
     midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model),
-                                            iter, katze_item_get_name (item), NULL);
+                                            iter, katze_item_get_meta_integer (item, "id"), NULL);
     g_object_unref (item);
 }
 
@@ -885,7 +987,7 @@ midori_bookmarks_filter_timeout_cb (gpointer data)
 
     gtk_tree_store_clear (treestore);
     midori_bookmarks_read_from_db_to_model (bookmarks,
-        treestore, NULL, NULL, bookmarks->filter);
+        treestore, NULL, 0, bookmarks->filter);
 
     return FALSE;
 }
diff --git a/panels/midori-bookmarks.h b/panels/midori-bookmarks.h
index 1be0412..cf56dea 100644
--- a/panels/midori-bookmarks.h
+++ b/panels/midori-bookmarks.h
@@ -40,15 +40,19 @@ midori_bookmarks_get_type               (void);
 GtkWidget*
 midori_bookmarks_new                    (void);
 
-void
-midori_bookmarks_insert_item_db (sqlite3*     db,
-                                 KatzeItem*   item,
-                                 const gchar* folder);
+gint64
+midori_bookmarks_insert_item_db (sqlite3*   db,
+                                 KatzeItem* item,
+                                 gint64     parentid);
 
 void
-midori_bookmarks_import_array_db (sqlite3*       db,
-                                  KatzeArray*    array,
-                                  const gchar*   folder);
+midori_bookmarks_import_array_db (sqlite3*    db,
+                                  KatzeArray* array,
+                                  gint64      parentid);
+
+gboolean
+midori_bookmarks_update_item_db (sqlite3*   db,
+                                 KatzeItem* item);
 
 G_END_DECLS
 
diff --git a/wscript b/wscript
index a3513f5..dfe53ab 100644
--- a/wscript
+++ b/wscript
@@ -268,7 +268,7 @@ def configure (conf):
     if check_version (conf.env['LIBSOUP_VERSION'], 2, 37, 1):
         conf.define ('HAVE_LIBSOUP_2_37_1', 1)
     check_pkg ('libxml-2.0', '2.6')
-    check_pkg ('sqlite3', '3.0', True, var='SQLITE')
+    check_pkg ('sqlite3', '3.6.19', True, var='SQLITE')
 
     if option_enabled ('hildon'):
         if check_pkg ('hildon-1', mandatory=False, var='HILDON'):


More information about the Xfce4-commits mailing list