~midori/midori/trunk

« back to all changes in this revision

Viewing changes to midori/midori-bookmarks-db.c

  • Committer: André Auzi
  • Date: 2013-08-05 19:52:52 UTC
  • mto: This revision was merged to the branch mainline in revision 6406.
  • Revision ID: aauzi@free.fr-20130805195252-89hqx89j37gl7v61
Derive MidoriBookmarksDb from KatzeArray in order to implement update-item signal
Implements, partially, signal redirection to parent KatzeArray after database operations.
On update-item signal, both bookmarkbar and bookmarks panel update themself.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
    #include <unistd.h>
26
26
#endif
27
27
 
28
 
static gint64
29
 
midori_bookmarks_insert_item_db (sqlite3*   db,
30
 
                                 KatzeItem* item,
31
 
                                 gint64     parentid);
32
 
 
33
 
static gboolean
34
 
midori_bookmarks_update_item_db (sqlite3*   db,
35
 
                                 KatzeItem* item);
36
 
 
37
 
gint64
38
 
midori_bookmarks_insert_item_db (sqlite3*   db,
39
 
                                 KatzeItem* item,
40
 
                                 gint64     parentid)
 
28
/**
 
29
 * SECTION:midory-bookmarks-db
 
30
 * @short_description: A #KatzeArray connected to a database
 
31
 * @see_also: #KatzeArray
 
32
 *
 
33
 * #MidoriBookmarksDb is a #KatzeArray specialized for database
 
34
 * interraction.
 
35
 */
 
36
 
 
37
struct _MidoriBookmarksDb
 
38
{
 
39
    KatzeArray  parent_instance;
 
40
 
 
41
    sqlite3*    db;
 
42
};
 
43
 
 
44
struct _MidoriBookmarksDbClass
 
45
{
 
46
    KatzeArrayClass parent_class;
 
47
 
 
48
    /* Signals */
 
49
    void
 
50
    (*update_item)            (MidoriBookmarksDb* bookmarks,
 
51
                               gpointer    item);
 
52
};
 
53
 
 
54
G_DEFINE_TYPE (MidoriBookmarksDb, midori_bookmarks_db, KATZE_TYPE_ARRAY);
 
55
 
 
56
enum {
 
57
    UPDATE_ITEM,
 
58
 
 
59
    LAST_SIGNAL
 
60
};
 
61
 
 
62
static guint signals[LAST_SIGNAL];
 
63
 
 
64
static void
 
65
_midori_bookmarks_db_add_item (KatzeArray* array,
 
66
                               gpointer    item);
 
67
 
 
68
static void
 
69
_midori_bookmarks_db_update_item (MidoriBookmarksDb* bookmarks,
 
70
                                  gpointer    item);
 
71
 
 
72
static void
 
73
_midori_bookmarks_db_remove_item (KatzeArray* array,
 
74
                                  gpointer   item);
 
75
 
 
76
static void
 
77
_midori_bookmarks_db_move_item (KatzeArray* array,
 
78
                                gpointer    item,
 
79
                                gint        position);
 
80
 
 
81
static void
 
82
_midori_bookmarks_db_clear (KatzeArray* array);
 
83
 
 
84
static void
 
85
midori_bookmarks_db_finalize (GObject* object);
 
86
 
 
87
static gint64
 
88
midori_bookmarks_db_insert_item_db (sqlite3*   db,
 
89
                                    KatzeItem* item,
 
90
                                    gint64     parentid);
 
91
 
 
92
static gboolean
 
93
midori_bookmarks_db_update_item_db (sqlite3*   db,
 
94
                                    KatzeItem* item);
 
95
 
 
96
static gboolean
 
97
midori_bookmarks_db_remove_item_db (sqlite3*   db,
 
98
                                    KatzeItem* item);
 
99
 
 
100
static void
 
101
midori_bookmarks_db_class_init (MidoriBookmarksDbClass* class)
 
102
{
 
103
    GObjectClass* gobject_class;
 
104
    KatzeArrayClass* katze_array_class;
 
105
 
 
106
    gobject_class = G_OBJECT_CLASS (class);
 
107
    gobject_class->finalize = midori_bookmarks_db_finalize;
 
108
 
 
109
    signals[UPDATE_ITEM] = g_signal_new (
 
110
        "update-item",
 
111
        G_TYPE_FROM_CLASS (class),
 
112
        (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
 
113
        G_STRUCT_OFFSET (MidoriBookmarksDbClass, update_item),
 
114
        0,
 
115
        NULL,
 
116
        g_cclosure_marshal_VOID__POINTER,
 
117
        G_TYPE_NONE, 1,
 
118
        G_TYPE_POINTER);
 
119
 
 
120
    katze_array_class = KATZE_ARRAY_CLASS (class);
 
121
 
 
122
    katze_array_class->add_item = _midori_bookmarks_db_add_item;
 
123
    katze_array_class->remove_item = _midori_bookmarks_db_remove_item;
 
124
    katze_array_class->move_item = _midori_bookmarks_db_move_item;
 
125
    katze_array_class->clear = _midori_bookmarks_db_clear;
 
126
 
 
127
    class->update_item = _midori_bookmarks_db_update_item;
 
128
}
 
129
 
 
130
static void
 
131
midori_bookmarks_db_init (MidoriBookmarksDb* bookmarks)
 
132
{
 
133
    bookmarks->db = NULL;
 
134
 
 
135
    katze_item_set_meta_integer (KATZE_ITEM (bookmarks), "id", 0);
 
136
    katze_item_set_name (KATZE_ITEM (bookmarks), _("Bookmarks"));
 
137
    /* g_object_ref (bookmarks); */
 
138
}
 
139
 
 
140
static void
 
141
midori_bookmarks_db_finalize (GObject* object)
 
142
{
 
143
    MidoriBookmarksDb* bookmarks = MIDORI_BOOKMARKS_DB (object);
 
144
 
 
145
    if (bookmarks->db)
 
146
    {
 
147
        sqlite3_close (bookmarks->db);
 
148
    }
 
149
 
 
150
    G_OBJECT_CLASS (midori_bookmarks_db_parent_class)->finalize (object);
 
151
}
 
152
 
 
153
/**
 
154
 * midori_bookmarks_db_get_item_parent:
 
155
 * @bookmarks: the main bookmarks array
 
156
 * @item: a #KatzeItem
 
157
 *
 
158
 * Internal function that find the parent of the @item thanks to its %parentid
 
159
 **/
 
160
static KatzeArray*
 
161
midori_bookmarks_db_get_item_parent (MidoriBookmarksDb* bookmarks,
 
162
                                     gpointer    item)
 
163
{
 
164
    KatzeArray* parent;
 
165
    gint64 parentid;
 
166
 
 
167
    parentid = katze_item_get_meta_integer (KATZE_ITEM (item), "parentid");
 
168
 
 
169
    if (parentid == 0)
 
170
    {
 
171
        parent = KATZE_ARRAY (bookmarks);
 
172
    }
 
173
    else
 
174
    {
 
175
        parent = NULL;
 
176
    }
 
177
 
 
178
    return parent;
 
179
}
 
180
 
 
181
/**
 
182
 * _midori_bookmarks_db_add_item:
 
183
 * @array: the main bookmarks array
 
184
 * @item: a #KatzeItem
 
185
 *
 
186
 * Internal function that overloads the #KatzeArray %katze_array_add_item().
 
187
 * It relays the add item to the appropriate #KatzeArray.
 
188
 **/
 
189
static void
 
190
_midori_bookmarks_db_add_item (KatzeArray* array,
 
191
                               gpointer    item)
 
192
{
 
193
    MidoriBookmarksDb *bookmarks;
 
194
    KatzeArray* parent;
 
195
    KatzeArray* db_parent;
 
196
 
 
197
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (array));
 
198
    g_return_if_fail (KATZE_IS_ITEM (item));
 
199
 
 
200
    bookmarks = MIDORI_BOOKMARKS_DB (array);
 
201
 
 
202
    parent = katze_item_get_parent (KATZE_ITEM (item));
 
203
 
 
204
    db_parent = midori_bookmarks_db_get_item_parent (bookmarks, item);
 
205
 
 
206
    g_return_if_fail (db_parent);
 
207
 
 
208
    if (parent == db_parent)
 
209
    {
 
210
        if (IS_MIDORI_BOOKMARKS_DB (parent))
 
211
            KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->update (parent);
 
212
        else
 
213
            katze_array_update (parent);
 
214
        return;
 
215
    }
 
216
 
 
217
    if (IS_MIDORI_BOOKMARKS_DB (parent))
 
218
        KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->add_item (parent, item);
 
219
    else
 
220
        katze_array_add_item (parent, item);
 
221
}
 
222
 
 
223
/**
 
224
 * _midori_bookmarks_db_update_item:
 
225
 * @array: the main bookmarks array
 
226
 * @item: a #KatzeItem
 
227
 *
 
228
 * Internal function that implements the %midori_bookmarks_db_update_item() post-processing.
 
229
 * It relays an update to the appropriate #KatzeArray.
 
230
 **/
 
231
static void
 
232
_midori_bookmarks_db_update_item (MidoriBookmarksDb* bookmarks,
 
233
                                              gpointer    item)
 
234
{
 
235
    KatzeArray* parent;
 
236
 
 
237
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks));
 
238
    g_return_if_fail (KATZE_IS_ITEM (item));
 
239
 
 
240
    parent = katze_item_get_parent (KATZE_ITEM (item));
 
241
 
 
242
    g_return_if_fail (parent);
 
243
 
 
244
    katze_array_update (parent);
 
245
}
 
246
 
 
247
/**
 
248
 * _midori_bookmarks_db_remove_item:
 
249
 * @array: the main bookmarks array
 
250
 * @item: a #KatzeItem
 
251
 *
 
252
 * Internal function that overloads the #KatzeArray %katze_array_remove_item().
 
253
 * It relays the remove item to the appropriate #KatzeArray.
 
254
 **/
 
255
static void
 
256
_midori_bookmarks_db_remove_item (KatzeArray* array,
 
257
                                  gpointer   item)
 
258
{
 
259
    KatzeArray* parent;
 
260
 
 
261
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (array));
 
262
    g_return_if_fail (KATZE_IS_ITEM (item));
 
263
 
 
264
    parent = katze_item_get_parent (KATZE_ITEM (item));
 
265
 
 
266
    g_return_if_fail (parent);
 
267
 
 
268
    if (IS_MIDORI_BOOKMARKS_DB (parent))
 
269
        KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->remove_item (parent, item);
 
270
    else
 
271
        katze_array_remove_item (parent, item);
 
272
}
 
273
 
 
274
/**
 
275
 * _midori_bookmarks_db_move_item:
 
276
 * @array: the main bookmarks array
 
277
 * @item: a #KatzeItem
 
278
 * @position: the new @item position
 
279
 *
 
280
 * Internal function that overloads the #KatzeArray %katze_array_move_item().
 
281
 * It relays the move @item to the appropriate #KatzeArray.
 
282
 **/
 
283
static void
 
284
_midori_bookmarks_db_move_item (KatzeArray* array,
 
285
                                gpointer    item,
 
286
                                gint        position)
 
287
{
 
288
    MidoriBookmarksDb *bookmarks;
 
289
    KatzeArray* parent;
 
290
 
 
291
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (array));
 
292
    g_return_if_fail (KATZE_IS_ITEM (item));
 
293
 
 
294
    parent = katze_item_get_parent (KATZE_ITEM (item));
 
295
 
 
296
    g_return_if_fail (parent);
 
297
 
 
298
    KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->move_item (parent, item, position);
 
299
}
 
300
 
 
301
/**
 
302
 * _midori_bookmarks_db_clear:
 
303
 * @array: the main bookmarks array
 
304
 *
 
305
 * Internal function that overloads the #KatzeArray %katze_array_clear().
 
306
 * It deletes the whole bookmarks data.
 
307
 **/
 
308
static void
 
309
_midori_bookmarks_db_clear (KatzeArray* array)
 
310
{
 
311
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (array));
 
312
 
 
313
    g_critical ("_midori_bookmarks_db_clear: not implemented\n");
 
314
}
 
315
 
 
316
/**
 
317
 * midori_bookmarks_db_signal_update_item:
 
318
 * @array: a #KatzeArray
 
319
 * @item: an item
 
320
 *
 
321
 * Notify an update of the item of the array.
 
322
 *
 
323
 **/
 
324
static void
 
325
midori_bookmarks_db_signal_update_item (MidoriBookmarksDb* array,
 
326
                                        gpointer    item)
 
327
{
 
328
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (array));
 
329
 
 
330
    g_signal_emit (array, signals[UPDATE_ITEM], 0, item);
 
331
}
 
332
 
 
333
/**
 
334
 * midori_bookmarks_db_insert_item_db:
 
335
 * @db: the #sqlite3
 
336
 * @item: #KatzeItem the item to insert
 
337
 *
 
338
 * Internal function that does the actual SQL INSERT of the @item in @db.
 
339
 *
 
340
 * Since: 0.5.2
 
341
 **/
 
342
static gint64
 
343
midori_bookmarks_db_insert_item_db (sqlite3*   db,
 
344
                                    KatzeItem* item,
 
345
                                    gint64     parentid)
41
346
{
42
347
    gchar* sqlcmd;
43
348
    char* errmsg = NULL;
75
380
        new_parentid = g_strdup_printf ("NULL");
76
381
 
77
382
    sqlcmd = sqlite3_mprintf (
78
 
            "INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) "
79
 
            "VALUES (%q, %q, '%q', '%q', '%q', %d, %d)",
80
 
            id,
81
 
            new_parentid,
82
 
            katze_item_get_name (item),
83
 
            katze_str_non_null (uri),
84
 
            katze_str_non_null (desc),
85
 
            katze_item_get_meta_boolean (item, "toolbar"),
86
 
            katze_item_get_meta_boolean (item, "app"));
 
383
        "INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) "
 
384
        "VALUES (%q, %q, '%q', '%q', '%q', %d, %d)",
 
385
        id,
 
386
        new_parentid,
 
387
        katze_item_get_name (item),
 
388
        katze_str_non_null (uri),
 
389
        katze_str_non_null (desc),
 
390
        katze_item_get_meta_boolean (item, "toolbar"),
 
391
        katze_item_get_meta_boolean (item, "app"));
87
392
 
88
393
    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) == SQLITE_OK)
89
394
    {
94
399
 
95
400
            sqlite3_free (sqlcmd);
96
401
            sqlcmd = sqlite3_mprintf (
97
 
                    "SELECT seq FROM sqlite_sequence WHERE name = 'bookmarks'");
 
402
                "SELECT seq FROM sqlite_sequence WHERE name = 'bookmarks'");
98
403
 
99
404
            seq_array = katze_array_from_sqlite (db, sqlcmd);
100
405
            if (katze_array_get_nth_item (seq_array, 0))
120
425
    return seq;
121
426
}
122
427
 
123
 
gboolean
124
 
midori_bookmarks_update_item_db (sqlite3*   db,
 
428
/**
 
429
 * midori_bookmarks_db_update_item_db:
 
430
 * @db: the #sqlite3
 
431
 * @item: #KatzeItem the item to update
 
432
 *
 
433
 * Internal function that does the actual SQL UPDATE of the @item in @db.
 
434
 *
 
435
 * Since: 0.5.2
 
436
 **/
 
437
static gboolean
 
438
midori_bookmarks_db_update_item_db (sqlite3*   db,
125
439
                                 KatzeItem* item)
126
440
{
127
441
    gchar* sqlcmd;
131
445
    gchar* id;
132
446
 
133
447
    id = g_strdup_printf ("%" G_GINT64_FORMAT,
134
 
            katze_item_get_meta_integer (item, "id"));
 
448
                          katze_item_get_meta_integer (item, "id"));
135
449
 
136
450
    if (katze_item_get_meta_integer (item, "parentid") > 0)
137
451
        parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
140
454
        parentid = g_strdup_printf ("NULL");
141
455
 
142
456
    sqlcmd = sqlite3_mprintf (
143
 
            "UPDATE bookmarks SET "
144
 
            "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d "
145
 
            "WHERE id = %q ;",
146
 
            parentid,
147
 
            katze_item_get_name (item),
148
 
            katze_str_non_null (katze_item_get_uri (item)),
149
 
            katze_str_non_null (katze_item_get_meta_string (item, "desc")),
150
 
            katze_item_get_meta_boolean (item, "toolbar"),
151
 
            katze_item_get_meta_boolean (item, "app"),
152
 
            id);
 
457
        "UPDATE bookmarks SET "
 
458
        "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d "
 
459
        "WHERE id = %q ;",
 
460
        parentid,
 
461
        katze_item_get_name (item),
 
462
        katze_str_non_null (katze_item_get_uri (item)),
 
463
        katze_str_non_null (katze_item_get_meta_string (item, "desc")),
 
464
        katze_item_get_meta_boolean (item, "toolbar"),
 
465
        katze_item_get_meta_boolean (item, "app"),
 
466
        id);
153
467
 
154
468
    updated = TRUE;
155
469
    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
167
481
}
168
482
 
169
483
/**
 
484
 * midori_bookmarks_db_remove_item_db:
 
485
 * @db: the #sqlite3
 
486
 * @item: #KatzeItem the item to delete
 
487
 *
 
488
 * Internal function that does the actual SQL DELETE of the @item in @db.
 
489
 *
 
490
 * Since: 0.5.2
 
491
 **/
 
492
static gboolean
 
493
midori_bookmarks_db_remove_item_db (sqlite3*    db,
 
494
                                    KatzeItem*  item)
 
495
{
 
496
    char* errmsg = NULL;
 
497
    gchar* sqlcmd;
 
498
    gboolean removed = TRUE;
 
499
    gchar* id;
 
500
 
 
501
    id = g_strdup_printf ("%" G_GINT64_FORMAT,
 
502
                          katze_item_get_meta_integer (item, "id"));
 
503
 
 
504
    sqlcmd = sqlite3_mprintf ("DELETE FROM bookmarks WHERE id = %q", id);
 
505
 
 
506
    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
 
507
    {
 
508
        g_printerr (_("Failed to remove bookmark item: %s\n"), errmsg);
 
509
        sqlite3_free (errmsg);
 
510
        removed = FALSE;
 
511
    }
 
512
 
 
513
    sqlite3_free (sqlcmd);
 
514
    g_free (id);
 
515
    return removed;
 
516
}
 
517
 
 
518
/**
 
519
 * midori_bookmarks_db_add_item:
 
520
 * @bookmarks: the main bookmark array
 
521
 * @item: #KatzeItem the item to update
 
522
 *
 
523
 * Adds the @item in the bookmark data base.
 
524
 *
 
525
 * Since: 0.5.2
 
526
 **/
 
527
void
 
528
midori_bookmarks_db_add_item (MidoriBookmarksDb* bookmarks, KatzeItem* item)
 
529
{
 
530
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks));
 
531
    g_return_if_fail (KATZE_IS_ITEM (item));
 
532
    g_return_if_fail (NULL == katze_item_get_meta_string (item, "id"));
 
533
 
 
534
    midori_bookmarks_db_insert_item_db (bookmarks->db, item,
 
535
                                        katze_item_get_meta_integer (item, "parentid"));
 
536
 
 
537
    katze_array_add_item (KATZE_ARRAY (bookmarks), item);
 
538
}
 
539
 
 
540
/**
170
541
 * midori_bookmarks_db_update_item:
171
542
 * @bookmarks: the main bookmark array
172
543
 * @item: #KatzeItem the item to update
173
544
 *
174
545
 * Updates the @item in the bookmark data base.
175
546
 *
176
 
 * Since: 0.5.5
177
 
 **/
178
 
void
179
 
midori_array_update_item (KatzeArray* bookmarks,
180
 
                          KatzeItem* item)
181
 
{
182
 
    g_return_if_fail (KATZE_IS_ARRAY (bookmarks));
183
 
    g_return_if_fail (KATZE_IS_ITEM (item));
184
 
    g_return_if_fail (katze_item_get_meta_string (item, "id"));
185
 
    g_return_if_fail (0 != katze_item_get_meta_integer (item, "id"));
186
 
 
187
 
    sqlite3* db = g_object_get_data (G_OBJECT (bookmarks), "db");
188
 
 
189
 
    g_return_if_fail (db);
190
 
 
191
 
    midori_bookmarks_update_item_db (db, item);
192
 
}
193
 
 
194
 
void
195
 
midori_bookmarks_dbtracer (void*       dummy,
196
 
                           const char* query)
197
 
{
198
 
    g_printerr ("%s\n", query);
199
 
}
200
 
 
201
 
static void
202
 
midori_bookmarks_add_item_cb (KatzeArray* array,
203
 
                              KatzeItem*  item,
204
 
                              sqlite3*    db)
205
 
{
206
 
    midori_bookmarks_insert_item_db (db, item,
207
 
        katze_item_get_meta_integer (item, "parentid"));
208
 
}
209
 
 
210
 
static void
211
 
midori_bookmarks_remove_item_cb (KatzeArray* array,
212
 
                                 KatzeItem*  item,
213
 
                                 sqlite3*    db)
214
 
{
215
 
    gchar* sqlcmd;
216
 
    char* errmsg = NULL;
217
 
    gchar* id;
218
 
 
219
 
    id = g_strdup_printf ("%" G_GINT64_FORMAT,
220
 
            katze_item_get_meta_integer (item, "id"));
221
 
 
222
 
    sqlcmd = sqlite3_mprintf ("DELETE FROM bookmarks WHERE id = %q", id);
223
 
 
224
 
    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
225
 
    {
226
 
        g_printerr (_("Failed to remove bookmark item: %s\n"), errmsg);
227
 
        sqlite3_free (errmsg);
228
 
    }
229
 
 
230
 
    sqlite3_free (sqlcmd);
231
 
    g_free (id);
 
547
 * Since: 0.5.2
 
548
 **/
 
549
void
 
550
midori_bookmarks_db_update_item (MidoriBookmarksDb* bookmarks, KatzeItem* item)
 
551
{
 
552
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks));
 
553
    g_return_if_fail (KATZE_IS_ITEM (item));
 
554
    g_return_if_fail (katze_item_get_meta_string (item, "id"));
 
555
    g_return_if_fail (0 != katze_item_get_meta_integer (item, "id"));
 
556
 
 
557
    midori_bookmarks_db_update_item_db (bookmarks->db, item);
 
558
 
 
559
    midori_bookmarks_db_signal_update_item (bookmarks, item);
 
560
}
 
561
 
 
562
/**
 
563
 * midori_bookmarks_db_remove_item:
 
564
 * @bookmarks: the main bookmark array
 
565
 * @item: #KatzeItem the item to remove
 
566
 *
 
567
 * Removes the @item from the bookmark data base.
 
568
 *
 
569
 * Since: 0.5.2
 
570
 **/
 
571
void
 
572
midori_bookmarks_db_remove_item (MidoriBookmarksDb* bookmarks, KatzeItem* item)
 
573
{
 
574
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks));
 
575
    g_return_if_fail (KATZE_IS_ITEM (item));
 
576
    g_return_if_fail (katze_item_get_meta_string (item, "id"));
 
577
    g_return_if_fail (0 != katze_item_get_meta_integer (item, "id"));
 
578
 
 
579
    midori_bookmarks_db_remove_item_db (bookmarks->db, item);
 
580
 
 
581
    katze_array_remove_item (KATZE_ARRAY (bookmarks), item);
232
582
}
233
583
 
234
584
#define _APPEND_TO_SQL_ERRORMSG(custom_errmsg) \
242
592
            g_string_append (errmsg_str, custom_errmsg); \
243
593
    } while (0)
244
594
 
245
 
gboolean
246
 
midori_bookmarks_import_from_old_db (sqlite3*     db,
 
595
static gboolean
 
596
midori_bookmarks_db_import_from_old_db (sqlite3*     db,
247
597
                                     const gchar* oldfile,
248
598
                                     gchar**      errmsg)
249
599
{
253
603
    GString* errmsg_str = g_string_new (NULL);
254
604
    gchar* attach_stmt = sqlite3_mprintf ("ATTACH DATABASE %Q AS old_db;", oldfile);
255
605
    const gchar* convert_stmts =
256
 
        "BEGIN TRANSACTION;"
257
 
        "INSERT INTO main.bookmarks (parentid, title, uri, desc, app, toolbar) "
258
 
        "SELECT NULL AS parentid, title, uri, desc, app, toolbar "
259
 
        "FROM old_db.bookmarks;"
260
 
        "UPDATE main.bookmarks SET parentid = ("
261
 
        "SELECT id FROM main.bookmarks AS b1 WHERE b1.title = ("
262
 
        "SELECT folder FROM old_db.bookmarks WHERE title = main.bookmarks.title));"
263
 
        "COMMIT;";
 
606
     "BEGIN TRANSACTION;"
 
607
     "INSERT INTO main.bookmarks (parentid, title, uri, desc, app, toolbar) "
 
608
     "SELECT NULL AS parentid, title, uri, desc, app, toolbar "
 
609
     "FROM old_db.bookmarks;"
 
610
     "UPDATE main.bookmarks SET parentid = ("
 
611
     "SELECT id FROM main.bookmarks AS b1 WHERE b1.title = ("
 
612
     "SELECT folder FROM old_db.bookmarks WHERE title = main.bookmarks.title));"
 
613
     "COMMIT;";
264
614
    const gchar* detach_stmt = "DETACH DATABASE old_db;";
265
615
 
266
616
    *errmsg = NULL;
288
638
 
289
639
    if (failure)
290
640
    {
291
 
    convert_failed:
 
641
      convert_failed:
292
642
        *errmsg = g_string_free (errmsg_str, FALSE);
293
643
        g_print ("ERRORR: %s\n", errmsg_str->str);
294
644
        return FALSE;
298
648
}
299
649
#undef _APPEND_TO_SQL_ERRORMSG
300
650
 
301
 
KatzeArray*
302
 
midori_bookmarks_new (char** errmsg)
 
651
static void
 
652
midori_bookmarks_db_dbtracer (void*       dummy,
 
653
                              const char* query)
 
654
{
 
655
    g_printerr ("%s\n", query);
 
656
}
 
657
 
 
658
/**
 
659
 * midori_bookmarks_db_new:
 
660
 *
 
661
 * Initializes the bookmark data base.
 
662
 *
 
663
 * Returns: the main bookmarks array
 
664
 *
 
665
 * Since: 0.5.2
 
666
 **/
 
667
MidoriBookmarksDb*
 
668
midori_bookmarks_db_new (char** errmsg)
303
669
{
304
670
    sqlite3* db;
305
671
    gchar* oldfile;
309
675
    gchar* sql_errmsg = NULL;
310
676
    gchar* import_errmsg = NULL;
311
677
    KatzeArray* array;
 
678
    MidoriBookmarksDb* bookmarks;
312
679
 
313
680
    g_return_val_if_fail (errmsg != NULL, NULL);
314
681
 
321
688
    if (sqlite3_open (newfile, &db) != SQLITE_OK)
322
689
    {
323
690
        *errmsg = g_strdup_printf (_("Failed to open database: %s\n"),
324
 
            db ? sqlite3_errmsg (db) : "(db = NULL)");
 
691
                                   db ? sqlite3_errmsg (db) : "(db = NULL)");
325
692
        goto init_failed;
326
693
    }
327
694
 
328
695
    if (midori_debug ("bookmarks"))
329
 
        sqlite3_trace (db, midori_bookmarks_dbtracer, NULL);
 
696
        sqlite3_trace (db, midori_bookmarks_db_dbtracer, NULL);
330
697
 
331
698
    create_stmt =     /* Table structure */
332
 
        "CREATE TABLE IF NOT EXISTS bookmarks "
333
 
        "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
334
 
        "parentid INTEGER DEFAULT NULL, "
335
 
        "title TEXT, uri TEXT, desc TEXT, app INTEGER, toolbar INTEGER, "
336
 
        "pos_panel INTEGER, pos_bar INTEGER, "
337
 
        "created DATE DEFAULT CURRENT_TIMESTAMP, "
338
 
        "last_visit DATE, visit_count INTEGER DEFAULT 0, "
339
 
        "nick TEXT, "
340
 
        "FOREIGN KEY(parentid) REFERENCES bookmarks(id) "
341
 
        "ON DELETE CASCADE); PRAGMA foreign_keys = ON;"
342
 
 
343
 
        /* trigger: insert panel position */
344
 
        "CREATE TRIGGER IF NOT EXISTS bookmarkInsertPosPanel "
345
 
        "AFTER INSERT ON bookmarks FOR EACH ROW "
346
 
        "BEGIN UPDATE bookmarks SET pos_panel = ("
347
 
        "SELECT ifnull(MAX(pos_panel),0)+1 FROM bookmarks WHERE "
348
 
        "(NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
349
 
        "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
350
 
        "WHERE id = NEW.id; END;"
351
 
 
352
 
        /* trigger: insert Bookmarkbar position */
353
 
        "CREATE TRIGGER IF NOT EXISTS bookmarkInsertPosBar "
354
 
        "AFTER INSERT ON bookmarks FOR EACH ROW WHEN NEW.toolbar=1 "
355
 
        "BEGIN UPDATE bookmarks SET pos_bar = ("
356
 
        "SELECT ifnull(MAX(pos_bar),0)+1 FROM bookmarks WHERE "
357
 
        "((NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
358
 
        "OR (NEW.parentid IS NULL AND parentid IS NULL)) AND toolbar=1) "
359
 
        "WHERE id = NEW.id; END;"
360
 
 
361
 
        /* trigger: update panel position */
362
 
        "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosPanel "
363
 
        "BEFORE UPDATE OF parentid ON bookmarks FOR EACH ROW "
364
 
        "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
365
 
        "AND NEW.parentid IS NOT OLD.parentid) OR "
366
 
        "((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
367
 
        "AND NEW.parentid!=OLD.parentid) "
368
 
        "BEGIN UPDATE bookmarks SET pos_panel = pos_panel-1 "
369
 
        "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
370
 
        "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_panel > OLD.pos_panel; "
371
 
        "UPDATE bookmarks SET pos_panel = ("
372
 
        "SELECT ifnull(MAX(pos_panel),0)+1 FROM bookmarks "
373
 
        "WHERE (NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
374
 
        "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
375
 
        "WHERE id = OLD.id; END;"
376
 
 
377
 
        /* trigger: update Bookmarkbar position */
378
 
        "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosBar0 "
379
 
        "AFTER UPDATE OF parentid, toolbar ON bookmarks FOR EACH ROW "
380
 
        "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
381
 
        "AND NEW.parentid IS NOT OLD.parentid) "
382
 
        "OR ((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
383
 
        "AND NEW.parentid!=OLD.parentid) OR (OLD.toolbar=1 AND NEW.toolbar=0) "
384
 
        "BEGIN UPDATE bookmarks SET pos_bar = NULL WHERE id = NEW.id; "
385
 
        "UPDATE bookmarks SET pos_bar = pos_bar-1 "
386
 
        "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
387
 
        "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_bar > OLD.pos_bar; END;"
388
 
 
389
 
        /* trigger: update Bookmarkbar position */
390
 
        "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosBar1 "
391
 
        "BEFORE UPDATE OF parentid, toolbar ON bookmarks FOR EACH ROW "
392
 
        "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
393
 
        "AND NEW.parentid IS NOT OLD.parentid) OR "
394
 
        "((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
395
 
        "AND NEW.parentid!=OLD.parentid) OR (OLD.toolbar=0 AND NEW.toolbar=1) "
396
 
        "BEGIN UPDATE bookmarks SET pos_bar = ("
397
 
        "SELECT ifnull(MAX(pos_bar),0)+1 FROM bookmarks WHERE "
398
 
        "(NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
399
 
        "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
400
 
        "WHERE id = OLD.id; END;"
401
 
 
402
 
        /* trigger: delete panel position */
403
 
        "CREATE TRIGGER IF NOT EXISTS bookmarkDeletePosPanel "
404
 
        "AFTER DELETE ON bookmarks FOR EACH ROW "
405
 
        "BEGIN UPDATE bookmarks SET pos_panel = pos_panel-1 "
406
 
        "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
407
 
        "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_panel > OLD.pos_panel; END;"
408
 
 
409
 
        /* trigger: delete Bookmarkbar position */
410
 
        "CREATE TRIGGER IF NOT EXISTS bookmarkDeletePosBar "
411
 
        "AFTER DELETE ON bookmarks FOR EACH ROW WHEN OLD.toolbar=1 "
412
 
        "BEGIN UPDATE bookmarks SET pos_bar = pos_bar-1 "
413
 
        "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
414
 
        "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_bar > OLD.pos_bar; END;";
 
699
     "CREATE TABLE IF NOT EXISTS bookmarks "
 
700
     "(id INTEGER PRIMARY KEY AUTOINCREMENT, "
 
701
     "parentid INTEGER DEFAULT NULL, "
 
702
     "title TEXT, uri TEXT, desc TEXT, app INTEGER, toolbar INTEGER, "
 
703
     "pos_panel INTEGER, pos_bar INTEGER, "
 
704
     "created DATE DEFAULT CURRENT_TIMESTAMP, "
 
705
     "last_visit DATE, visit_count INTEGER DEFAULT 0, "
 
706
     "nick TEXT, "
 
707
     "FOREIGN KEY(parentid) REFERENCES bookmarks(id) "
 
708
     "ON DELETE CASCADE); PRAGMA foreign_keys = ON;"
 
709
 
 
710
     /* trigger: insert panel position */
 
711
     "CREATE TRIGGER IF NOT EXISTS bookmarkInsertPosPanel "
 
712
     "AFTER INSERT ON bookmarks FOR EACH ROW "
 
713
     "BEGIN UPDATE bookmarks SET pos_panel = ("
 
714
     "SELECT ifnull(MAX(pos_panel),0)+1 FROM bookmarks WHERE "
 
715
     "(NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
 
716
     "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
 
717
     "WHERE id = NEW.id; END;"
 
718
 
 
719
     /* trigger: insert Bookmarkbar position */
 
720
     "CREATE TRIGGER IF NOT EXISTS bookmarkInsertPosBar "
 
721
     "AFTER INSERT ON bookmarks FOR EACH ROW WHEN NEW.toolbar=1 "
 
722
     "BEGIN UPDATE bookmarks SET pos_bar = ("
 
723
     "SELECT ifnull(MAX(pos_bar),0)+1 FROM bookmarks WHERE "
 
724
     "((NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
 
725
     "OR (NEW.parentid IS NULL AND parentid IS NULL)) AND toolbar=1) "
 
726
     "WHERE id = NEW.id; END;"
 
727
 
 
728
     /* trigger: update panel position */
 
729
     "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosPanel "
 
730
     "BEFORE UPDATE OF parentid ON bookmarks FOR EACH ROW "
 
731
     "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
 
732
     "AND NEW.parentid IS NOT OLD.parentid) OR "
 
733
     "((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
 
734
     "AND NEW.parentid!=OLD.parentid) "
 
735
     "BEGIN UPDATE bookmarks SET pos_panel = pos_panel-1 "
 
736
     "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
 
737
     "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_panel > OLD.pos_panel; "
 
738
     "UPDATE bookmarks SET pos_panel = ("
 
739
     "SELECT ifnull(MAX(pos_panel),0)+1 FROM bookmarks "
 
740
     "WHERE (NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
 
741
     "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
 
742
     "WHERE id = OLD.id; END;"
 
743
 
 
744
     /* trigger: update Bookmarkbar position */
 
745
     "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosBar0 "
 
746
     "AFTER UPDATE OF parentid, toolbar ON bookmarks FOR EACH ROW "
 
747
     "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
 
748
     "AND NEW.parentid IS NOT OLD.parentid) "
 
749
     "OR ((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
 
750
     "AND NEW.parentid!=OLD.parentid) OR (OLD.toolbar=1 AND NEW.toolbar=0) "
 
751
     "BEGIN UPDATE bookmarks SET pos_bar = NULL WHERE id = NEW.id; "
 
752
     "UPDATE bookmarks SET pos_bar = pos_bar-1 "
 
753
     "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
 
754
     "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_bar > OLD.pos_bar; END;"
 
755
 
 
756
     /* trigger: update Bookmarkbar position */
 
757
     "CREATE TRIGGER IF NOT EXISTS bookmarkUpdatePosBar1 "
 
758
     "BEFORE UPDATE OF parentid, toolbar ON bookmarks FOR EACH ROW "
 
759
     "WHEN ((NEW.parentid IS NULL OR OLD.parentid IS NULL) "
 
760
     "AND NEW.parentid IS NOT OLD.parentid) OR "
 
761
     "((NEW.parentid IS NOT NULL AND OLD.parentid IS NOT NULL) "
 
762
     "AND NEW.parentid!=OLD.parentid) OR (OLD.toolbar=0 AND NEW.toolbar=1) "
 
763
     "BEGIN UPDATE bookmarks SET pos_bar = ("
 
764
     "SELECT ifnull(MAX(pos_bar),0)+1 FROM bookmarks WHERE "
 
765
     "(NEW.parentid IS NOT NULL AND parentid = NEW.parentid) "
 
766
     "OR (NEW.parentid IS NULL AND parentid IS NULL)) "
 
767
     "WHERE id = OLD.id; END;"
 
768
 
 
769
     /* trigger: delete panel position */
 
770
     "CREATE TRIGGER IF NOT EXISTS bookmarkDeletePosPanel "
 
771
     "AFTER DELETE ON bookmarks FOR EACH ROW "
 
772
     "BEGIN UPDATE bookmarks SET pos_panel = pos_panel-1 "
 
773
     "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
 
774
     "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_panel > OLD.pos_panel; END;"
 
775
 
 
776
     /* trigger: delete Bookmarkbar position */
 
777
     "CREATE TRIGGER IF NOT EXISTS bookmarkDeletePosBar "
 
778
     "AFTER DELETE ON bookmarks FOR EACH ROW WHEN OLD.toolbar=1 "
 
779
     "BEGIN UPDATE bookmarks SET pos_bar = pos_bar-1 "
 
780
     "WHERE ((OLD.parentid IS NOT NULL AND parentid = OLD.parentid) "
 
781
     "OR (OLD.parentid IS NULL AND parentid IS NULL)) AND pos_bar > OLD.pos_bar; END;";
415
782
 
416
783
 
417
784
    if (newfile_did_exist)
421
788
        if (sqlite3_exec (db, setup_stmt, NULL, NULL, &sql_errmsg) != SQLITE_OK)
422
789
        {
423
790
            *errmsg = g_strdup_printf (_("Couldn't setup bookmarks: %s\n"),
424
 
                sql_errmsg ? sql_errmsg : "(err = NULL)");
 
791
                                       sql_errmsg ? sql_errmsg : "(err = NULL)");
425
792
            sqlite3_free (sql_errmsg);
426
793
            goto init_failed;
427
794
        }
435
802
        if (sqlite3_exec (db, create_stmt, NULL, NULL, &sql_errmsg) != SQLITE_OK)
436
803
        {
437
804
            *errmsg = g_strdup_printf (_("Couldn't create bookmarks table: %s\n"),
438
 
                sql_errmsg ? sql_errmsg : "(err = NULL)");
 
805
                                       sql_errmsg ? sql_errmsg : "(err = NULL)");
439
806
            sqlite3_free (sql_errmsg);
440
807
 
441
808
            /* we can as well remove the new file */
447
814
 
448
815
    if (oldfile_exists)
449
816
        /* import from old db */
450
 
        if (!midori_bookmarks_import_from_old_db (db, oldfile, &import_errmsg))
 
817
        if (!midori_bookmarks_db_import_from_old_db (db, oldfile, &import_errmsg))
451
818
        {
452
819
            *errmsg = g_strdup_printf (_("Couldn't import from old database: %s\n"),
453
 
                import_errmsg ? import_errmsg : "(err = NULL)");
 
820
                                       import_errmsg ? import_errmsg : "(err = NULL)");
454
821
            g_free (import_errmsg);
455
822
        }
456
823
 
457
 
    init_success:
458
 
        g_free (newfile);
459
 
        g_free (oldfile);
460
 
        array = katze_array_new (KATZE_TYPE_ARRAY);
461
 
        g_signal_connect (array, "add-item",
462
 
                          G_CALLBACK (midori_bookmarks_add_item_cb), db);
463
 
        g_signal_connect (array, "remove-item",
464
 
                          G_CALLBACK (midori_bookmarks_remove_item_cb), db);
465
 
        g_object_set_data (G_OBJECT (array), "db", db);
466
 
        return array;
467
 
 
468
 
    init_failed:
469
 
        g_free (newfile);
470
 
        g_free (oldfile);
471
 
 
472
 
        if (db)
473
 
            sqlite3_close (db);
474
 
 
475
 
        return NULL;
 
824
  init_success:
 
825
    g_free (newfile);
 
826
    g_free (oldfile);
 
827
    bookmarks = MIDORI_BOOKMARKS_DB (g_object_new (TYPE_MIDORI_BOOKMARKS_DB, NULL));
 
828
    bookmarks->db = db;
 
829
 
 
830
    g_object_set_data (G_OBJECT (bookmarks), "db", db);
 
831
    return bookmarks;
 
832
 
 
833
  init_failed:
 
834
    g_free (newfile);
 
835
    g_free (oldfile);
 
836
 
 
837
    if (db)
 
838
        sqlite3_close (db);
 
839
 
 
840
    return NULL;
476
841
}
477
842
 
 
843
/**
 
844
 * midori_bookmarks_db_on_quit:
 
845
 * @bookmarks: the main bookmark array
 
846
 *
 
847
 * Delete the main bookmark array.
 
848
 *
 
849
 * Since: 0.5.2
 
850
 **/
478
851
void
479
 
midori_bookmarks_on_quit (KatzeArray* array)
 
852
midori_bookmarks_db_on_quit (MidoriBookmarksDb* bookmarks)
480
853
{
481
 
    g_return_if_fail (KATZE_IS_ARRAY (array));
 
854
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks));
482
855
 
483
 
    sqlite3* db = g_object_get_data (G_OBJECT (array), "db");
484
 
    g_return_if_fail (db != NULL);
485
 
    sqlite3_close (db);
 
856
    g_object_unref (bookmarks);
486
857
}
487
858
 
 
859
/**
 
860
 * midori_bookmarks_db_import_array:
 
861
 * @array: the main bookmark array
 
862
 * @array: #KatzeArray containing the items to import
 
863
 * @parentid: the id of folder
 
864
 *
 
865
 * Imports the items of @array as childs of the folder
 
866
 * identfied by @parentid.
 
867
 *
 
868
 * Since: 0.5.2
 
869
 **/
488
870
void
489
 
midori_bookmarks_import_array (KatzeArray* bookmarks,
 
871
midori_bookmarks_db_import_array (MidoriBookmarksDb* bookmarks,
490
872
                               KatzeArray* array,
491
873
                               gint64      parentid)
492
874
{
493
875
    GList* list;
494
876
    KatzeItem* item;
495
877
 
496
 
    if (!bookmarks)
497
 
        return;
 
878
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks));
 
879
    g_return_if_fail (KATZE_IS_ARRAY (array));
498
880
 
499
881
    KATZE_ARRAY_FOREACH_ITEM_L (item, array, list)
500
882
    {
501
883
        katze_item_set_meta_integer (item, "parentid", parentid);
502
 
        katze_array_add_item (bookmarks, item);
 
884
        midori_bookmarks_db_add_item (bookmarks, item);
503
885
        if (KATZE_IS_ARRAY (item))
504
 
          midori_bookmarks_import_array (bookmarks, KATZE_ARRAY (item),
505
 
                                         katze_item_get_meta_integer(item, "id"));
 
886
            midori_bookmarks_db_import_array (bookmarks, KATZE_ARRAY (item),
 
887
                                              katze_item_get_meta_integer(item, "id"));
506
888
    }
507
889
    g_list_free (list);
508
890
}
509
891
 
510
892
/**
511
 
 * midori_array_query_recursive:
 
893
 * midori_bookmarks_db_array_from_statement:
 
894
 * @stmt: the sqlite returned statement
 
895
 * @bookmarks: the database controller
 
896
 *
 
897
 * Internal function that populate a #KatzeArray by processing the @stmt
 
898
 * rows identifying:
 
899
 * a- if the item is already in memory
 
900
 *    in this case the item data is updated with retreived database content
 
901
 *    and the already existing item is populated in the returned #KatzeArray
 
902
 * b- if the data is a folder
 
903
 *    a new #KatzeArray item is populated in the returned  #KatzeArray and
 
904
 *    memorized for future use.
 
905
 * c- if the data is a bookmark
 
906
 *    a new #KatzeItem item is populated in the returned  #KatzeArray and
 
907
 *    memorized for furure use.
 
908
 *
 
909
 * Return value: the populated #KatzeArray
 
910
 **/
 
911
static KatzeArray*
 
912
midori_bookmarks_db_array_from_statement (sqlite3_stmt* stmt,
 
913
                                       MidoriBookmarksDb* bookmarks)
 
914
{
 
915
    KatzeArray *array;
 
916
    gint result;
 
917
    gint cols;
 
918
 
 
919
    array = katze_array_new (KATZE_TYPE_ITEM);
 
920
    cols = sqlite3_column_count (stmt);
 
921
 
 
922
    while ((result = sqlite3_step (stmt)) == SQLITE_ROW)
 
923
    {
 
924
        gint i;
 
925
        KatzeItem* item;
 
926
        KatzeItem* found;
 
927
 
 
928
        item = katze_item_new ();
 
929
        for (i = 0; i < cols; i++)
 
930
            katze_item_set_value_from_column (stmt, i, item);
 
931
 
 
932
        if (KATZE_ITEM_IS_FOLDER (item))
 
933
        {
 
934
            g_object_unref (item);
 
935
 
 
936
            item = KATZE_ITEM (katze_array_new (KATZE_TYPE_ITEM));
 
937
 
 
938
            for (i = 0; i < cols; i++)
 
939
                katze_item_set_value_from_column (stmt, i, item);
 
940
        }
 
941
 
 
942
        katze_array_add_item (array, item);
 
943
    }
 
944
 
 
945
    sqlite3_clear_bindings (stmt);
 
946
    sqlite3_reset (stmt);
 
947
    return array;
 
948
}
 
949
 
 
950
/**
 
951
 * midori_bookmarks_db_array_from_sqlite:
 
952
 * @array: the main bookmark array
 
953
 * @sqlcmd: the sqlcmd to execute
 
954
 *
 
955
 * Internal function that process the requested @sqlcmd.
 
956
 *
 
957
 * Return value: a #KatzeArray on success, %NULL otherwise
 
958
 **/
 
959
static KatzeArray*
 
960
midori_bookmarks_db_array_from_sqlite (MidoriBookmarksDb* bookmarks,
 
961
                                    const gchar* sqlcmd)
 
962
{
 
963
    sqlite3_stmt* stmt;
 
964
    gint result;
 
965
 
 
966
    g_return_val_if_fail (bookmarks->db != NULL, NULL);
 
967
 
 
968
    result = sqlite3_prepare_v2 (bookmarks->db, sqlcmd, -1, &stmt, NULL);
 
969
    if (result != SQLITE_OK)
 
970
        return NULL;
 
971
 
 
972
    return midori_bookmarks_db_array_from_statement (stmt, bookmarks);
 
973
}
 
974
 
 
975
/**
 
976
 * midori_bookmarks_db_query_recursive:
512
977
 * @array: the main bookmark array
513
978
 * @fields: comma separated list of fields
514
979
 * @condition: condition, like "folder = '%q'"
519
984
 *
520
985
 * Return value: a #KatzeArray on success, %NULL otherwise
521
986
 *
522
 
 * Since: 0.4.4
 
987
 * Since: 0.5.2
523
988
 **/
524
989
KatzeArray*
525
 
midori_array_query_recursive (KatzeArray*  bookmarks,
526
 
                              const gchar* fields,
527
 
                              const gchar* condition,
528
 
                              const gchar* value,
529
 
                              gboolean     recursive)
 
990
midori_bookmarks_db_query_recursive (MidoriBookmarksDb*  bookmarks,
 
991
                                  const gchar* fields,
 
992
                                  const gchar* condition,
 
993
                                  const gchar* value,
 
994
                                  gboolean     recursive)
530
995
{
531
 
    sqlite3* db;
532
996
    gchar* sqlcmd;
533
997
    char* sqlcmd_value;
534
998
    KatzeArray* array;
535
999
    KatzeItem* item;
536
1000
    GList* list;
537
1001
 
538
 
    g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), NULL);
 
1002
    g_return_val_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks), NULL);
539
1003
    g_return_val_if_fail (fields, NULL);
540
1004
    g_return_val_if_fail (condition, NULL);
541
 
    db = g_object_get_data (G_OBJECT (bookmarks), "db");
542
 
    g_return_val_if_fail (db != NULL, NULL);
543
1005
 
544
1006
    sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s "
545
1007
                              "ORDER BY (uri='') ASC, title DESC", fields, condition);
546
1008
    if (strstr (condition, "%q"))
547
1009
    {
548
1010
        sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");
549
 
        array = katze_array_from_sqlite (db, sqlcmd_value);
 
1011
        array = midori_bookmarks_db_array_from_sqlite (bookmarks, sqlcmd_value);
550
1012
        sqlite3_free (sqlcmd_value);
551
1013
    }
552
1014
    else
553
 
        array = katze_array_from_sqlite (db, sqlcmd);
 
1015
        array = midori_bookmarks_db_array_from_sqlite (bookmarks, sqlcmd);
554
1016
    g_free (sqlcmd);
555
1017
 
556
1018
    if (!recursive)
562
1024
        {
563
1025
            gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
564
1026
                                               katze_item_get_meta_integer (item, "id"));
565
 
            KatzeArray* subarray = midori_array_query_recursive (bookmarks,
566
 
                                                                 fields, "parentid=%q", parentid, TRUE);
 
1027
            KatzeArray* subarray = midori_bookmarks_db_query_recursive (bookmarks,
 
1028
                                                                        fields, "parentid=%q", parentid, TRUE);
567
1029
            KatzeItem* subitem;
568
1030
            GList* sublist;
569
1031
 
581
1043
}
582
1044
 
583
1045
static gint64
584
 
count_from_sqlite (sqlite3*     db,
585
 
                   const gchar* sqlcmd)
 
1046
midori_bookmarks_db_count_from_sqlite (sqlite3*     db,
 
1047
                                       const gchar* sqlcmd)
586
1048
{
587
1049
    gint64 count = -1;
588
1050
    sqlite3_stmt* stmt;
604
1066
}
605
1067
 
606
1068
static gint64
607
 
midori_array_count_recursive_by_id (KatzeArray*  bookmarks,
608
 
                                    const gchar* condition,
609
 
                                    const gchar* value,
610
 
                                    gint64       id,
611
 
                                    gboolean     recursive)
 
1069
midori_bookmarks_db_count_recursive_by_id (MidoriBookmarksDb*  bookmarks,
 
1070
                                                           const gchar*        condition,
 
1071
                                                           const gchar*        value,
 
1072
                                                           gint64              id,
 
1073
                                                           gboolean            recursive)
612
1074
{
613
1075
    gint64 count = -1;
614
 
    sqlite3* db;
615
1076
    gchar* sqlcmd;
616
1077
    char* sqlcmd_value;
617
1078
    sqlite3_stmt* stmt;
620
1081
    GList* iter_ids;
621
1082
 
622
1083
    g_return_val_if_fail (condition, -1);
623
 
    g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), -1);
624
 
    db = g_object_get_data (G_OBJECT (bookmarks), "db");
625
 
    g_return_val_if_fail (db != NULL, -1);
 
1084
    g_return_val_if_fail (MIDORI_BOOKMARKS_DB (bookmarks), -1);
 
1085
    g_return_val_if_fail (bookmarks->db != NULL, -1);
626
1086
 
627
1087
    g_assert(!strstr("parentid", condition));
628
1088
 
639
1099
    if (strstr (condition, "%q"))
640
1100
    {
641
1101
        sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");
642
 
        count = count_from_sqlite (db, sqlcmd_value);
 
1102
        count = midori_bookmarks_db_count_from_sqlite (bookmarks->db, sqlcmd_value);
643
1103
        sqlite3_free (sqlcmd_value);
644
1104
    }
645
1105
    else
646
 
        count = count_from_sqlite (db, sqlcmd);
 
1106
        count = midori_bookmarks_db_count_from_sqlite (bookmarks->db, sqlcmd);
647
1107
 
648
1108
    g_free (sqlcmd);
649
1109
 
653
1113
    ids = NULL;
654
1114
 
655
1115
    if (id > 0)
656
 
        sqlcmd_value = sqlite3_mprintf (
657
 
            "SELECT id FROM bookmarks "
658
 
            "WHERE parentid = %" G_GINT64_FORMAT " AND uri = ''", id);
 
1116
        sqlcmd_value = sqlite3_mprintf (
 
1117
            "SELECT id FROM bookmarks "
 
1118
            "WHERE parentid = %" G_GINT64_FORMAT " AND uri = ''", id);
659
1119
    else
660
 
        sqlcmd_value = sqlite3_mprintf (
661
 
            "SELECT id FROM bookmarks "
662
 
            "WHERE parentid IS NULL AND uri = ''");
 
1120
        sqlcmd_value = sqlite3_mprintf (
 
1121
            "SELECT id FROM bookmarks "
 
1122
            "WHERE parentid IS NULL AND uri = ''");
663
1123
 
664
 
    if (sqlite3_prepare_v2 (db, sqlcmd_value, -1, &stmt, NULL) == SQLITE_OK)
 
1124
    if (sqlite3_prepare_v2 (bookmarks->db, sqlcmd_value, -1, &stmt, NULL) == SQLITE_OK)
665
1125
    {
666
 
        g_assert (sqlite3_column_count (stmt) == 1);
667
 
    
668
 
        if ((result = sqlite3_step (stmt)) == SQLITE_ROW)
669
 
        {
670
 
            gint64* pid = g_new (gint64, 1);
671
 
            
672
 
            *pid = sqlite3_column_int64(stmt, 0);
673
 
            ids = g_list_append (ids, pid);
674
 
        }
675
 
        
676
 
        sqlite3_clear_bindings (stmt);
677
 
        sqlite3_reset (stmt);
 
1126
        g_assert (sqlite3_column_count (stmt) == 1);
 
1127
 
 
1128
        if ((result = sqlite3_step (stmt)) == SQLITE_ROW)
 
1129
        {
 
1130
            gint64* pid = g_new (gint64, 1);
 
1131
 
 
1132
            *pid = sqlite3_column_int64(stmt, 0);
 
1133
            ids = g_list_append (ids, pid);
 
1134
        }
 
1135
 
 
1136
        sqlite3_clear_bindings (stmt);
 
1137
        sqlite3_reset (stmt);
678
1138
    }
679
1139
 
680
1140
    sqlite3_free (sqlcmd_value);
682
1142
    iter_ids = ids;
683
1143
    while (iter_ids)
684
1144
    {
685
 
        gint64 sub_count = midori_array_count_recursive_by_id (bookmarks,
686
 
                                                               condition,
687
 
                                                               value,
688
 
                                                               *(gint64*)(iter_ids->data),
689
 
                                                               recursive);
690
 
        
691
 
        if (sub_count < 0)
692
 
        {
693
 
            g_list_free_full (ids, g_free);
694
 
            return -1;
695
 
        }
696
 
        
697
 
        count += sub_count;
698
 
        iter_ids = g_list_next (iter_ids);
 
1145
        gint64 sub_count = midori_bookmarks_db_count_recursive_by_id (bookmarks,
 
1146
                                                                      condition,
 
1147
                                                                      value,
 
1148
                                                                      *(gint64*)(iter_ids->data),
 
1149
                                                                      recursive);
 
1150
 
 
1151
        if (sub_count < 0)
 
1152
        {
 
1153
            g_list_free_full (ids, g_free);
 
1154
            return -1;
 
1155
        }
 
1156
 
 
1157
        count += sub_count;
 
1158
        iter_ids = g_list_next (iter_ids);
699
1159
    }
700
1160
        
701
1161
    g_list_free_full (ids, g_free);
703
1163
}
704
1164
 
705
1165
/**
706
 
 * midori_array_count_recursive:
707
 
 * @array: the main bookmark array
 
1166
 * midori_bookmarks_db_count_recursive:
 
1167
 * @bookmarks: the main bookmark array
708
1168
 * @condition: condition, like "folder = '%q'"
709
1169
 * @value: a value to be inserted if @condition contains %q
710
1170
 * @recursive: if %TRUE include children
714
1174
 * Since: 0.5.2
715
1175
 **/
716
1176
gint64
717
 
midori_array_count_recursive (KatzeArray*  bookmarks,
718
 
                              const gchar* condition,
719
 
                              const gchar* value,
720
 
                              KatzeItem*   folder,
721
 
                              gboolean     recursive)
 
1177
midori_bookmarks_db_count_recursive (MidoriBookmarksDb*  bookmarks,
 
1178
                                                 const gchar*        condition,
 
1179
                                     const gchar*        value,
 
1180
                                                 KatzeItem*          folder,
 
1181
                                     gboolean            recursive)
722
1182
{
723
1183
    gint64 id = -1;
724
1184
 
726
1186
    
727
1187
    id = folder ? katze_item_get_meta_integer (folder, "id") : 0;
728
1188
 
729
 
    return midori_array_count_recursive_by_id (bookmarks, condition,
730
 
                                               value, id,
731
 
                                               recursive);
 
1189
    return midori_bookmarks_db_count_recursive_by_id (bookmarks, condition,
 
1190
                                                      value, id,
 
1191
                                                      recursive);
732
1192
}