~midori/midori/trunk

« back to all changes in this revision

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

  • Committer: Tarmac
  • Author(s): André Auzi
  • Date: 2013-09-18 16:20:51 UTC
  • mfrom: (6319.3.4 fix-1179200-5)
  • Revision ID: tarmac-20130918162051-n73z21hwk1dju69u
Introduces KatzeArray::update-item to handle metadata changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
    #include <unistd.h>
26
26
#endif
27
27
 
28
 
static gboolean
29
 
midori_bookmarks_update_item_db (sqlite3*   db,
30
 
                                 KatzeItem* item);
31
 
 
32
 
gint64
33
 
midori_bookmarks_insert_item_db (sqlite3*   db,
34
 
                                 KatzeItem* item,
35
 
                                 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)
36
346
{
37
347
    gchar* sqlcmd;
38
348
    char* errmsg = NULL;
70
380
        new_parentid = g_strdup_printf ("NULL");
71
381
 
72
382
    sqlcmd = sqlite3_mprintf (
73
 
            "INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) "
74
 
            "VALUES (%q, %q, '%q', '%q', '%q', %d, %d)",
75
 
            id,
76
 
            new_parentid,
77
 
            katze_item_get_name (item),
78
 
            katze_str_non_null (uri),
79
 
            katze_str_non_null (desc),
80
 
            katze_item_get_meta_boolean (item, "toolbar"),
81
 
            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"));
82
392
 
83
393
    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) == SQLITE_OK)
84
394
    {
89
399
 
90
400
            sqlite3_free (sqlcmd);
91
401
            sqlcmd = sqlite3_mprintf (
92
 
                    "SELECT seq FROM sqlite_sequence WHERE name = 'bookmarks'");
 
402
                "SELECT seq FROM sqlite_sequence WHERE name = 'bookmarks'");
93
403
 
94
404
            seq_array = katze_array_from_sqlite (db, sqlcmd);
95
405
            if (katze_array_get_nth_item (seq_array, 0))
115
425
    return seq;
116
426
}
117
427
 
118
 
gboolean
119
 
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,
120
439
                                 KatzeItem* item)
121
440
{
122
441
    gchar* sqlcmd;
126
445
    gchar* id;
127
446
 
128
447
    id = g_strdup_printf ("%" G_GINT64_FORMAT,
129
 
            katze_item_get_meta_integer (item, "id"));
 
448
                          katze_item_get_meta_integer (item, "id"));
130
449
 
131
450
    if (katze_item_get_meta_integer (item, "parentid") > 0)
132
451
        parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
135
454
        parentid = g_strdup_printf ("NULL");
136
455
 
137
456
    sqlcmd = sqlite3_mprintf (
138
 
            "UPDATE bookmarks SET "
139
 
            "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d "
140
 
            "WHERE id = %q ;",
141
 
            parentid,
142
 
            katze_item_get_name (item),
143
 
            katze_str_non_null (katze_item_get_uri (item)),
144
 
            katze_str_non_null (katze_item_get_meta_string (item, "desc")),
145
 
            katze_item_get_meta_boolean (item, "toolbar"),
146
 
            katze_item_get_meta_boolean (item, "app"),
147
 
            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);
148
467
 
149
468
    updated = TRUE;
150
469
    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
162
481
}
163
482
 
164
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
/**
165
541
 * midori_bookmarks_db_update_item:
166
542
 * @bookmarks: the main bookmark array
167
543
 * @item: #KatzeItem the item to update
168
544
 *
169
545
 * Updates the @item in the bookmark data base.
170
546
 *
171
 
 * Since: 0.5.5
172
 
 **/
173
 
void
174
 
midori_array_update_item (KatzeArray* bookmarks,
175
 
                          KatzeItem* item)
176
 
{
177
 
    g_return_if_fail (KATZE_IS_ARRAY (bookmarks));
178
 
    g_return_if_fail (KATZE_IS_ITEM (item));
179
 
    g_return_if_fail (katze_item_get_meta_string (item, "id"));
180
 
    g_return_if_fail (0 != katze_item_get_meta_integer (item, "id"));
181
 
 
182
 
    sqlite3* db = g_object_get_data (G_OBJECT (bookmarks), "db");
183
 
 
184
 
    g_return_if_fail (db);
185
 
 
186
 
    midori_bookmarks_update_item_db (db, item);
187
 
}
188
 
 
189
 
void
190
 
midori_bookmarks_dbtracer (void*       dummy,
191
 
                           const char* query)
192
 
{
193
 
    g_printerr ("%s\n", query);
194
 
}
195
 
 
196
 
static void
197
 
midori_bookmarks_add_item_cb (KatzeArray* array,
198
 
                              KatzeItem*  item,
199
 
                              sqlite3*    db)
200
 
{
201
 
    midori_bookmarks_insert_item_db (db, item,
202
 
        katze_item_get_meta_integer (item, "parentid"));
203
 
}
204
 
 
205
 
static void
206
 
midori_bookmarks_remove_item_cb (KatzeArray* array,
207
 
                                 KatzeItem*  item,
208
 
                                 sqlite3*    db)
209
 
{
210
 
    gchar* sqlcmd;
211
 
    char* errmsg = NULL;
212
 
    gchar* id;
213
 
 
214
 
    id = g_strdup_printf ("%" G_GINT64_FORMAT,
215
 
            katze_item_get_meta_integer (item, "id"));
216
 
 
217
 
    sqlcmd = sqlite3_mprintf ("DELETE FROM bookmarks WHERE id = %q", id);
218
 
 
219
 
    if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
220
 
    {
221
 
        g_printerr (_("Failed to remove bookmark item: %s\n"), errmsg);
222
 
        sqlite3_free (errmsg);
223
 
    }
224
 
 
225
 
    sqlite3_free (sqlcmd);
226
 
    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);
227
582
}
228
583
 
229
584
#define _APPEND_TO_SQL_ERRORMSG(custom_errmsg) \
237
592
            g_string_append (errmsg_str, custom_errmsg); \
238
593
    } while (0)
239
594
 
240
 
gboolean
241
 
midori_bookmarks_import_from_old_db (sqlite3*     db,
 
595
static gboolean
 
596
midori_bookmarks_db_import_from_old_db (sqlite3*     db,
242
597
                                     const gchar* oldfile,
243
598
                                     gchar**      errmsg)
244
599
{
293
648
}
294
649
#undef _APPEND_TO_SQL_ERRORMSG
295
650
 
296
 
KatzeArray*
297
 
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)
298
669
{
299
670
    sqlite3* db;
300
671
    gchar* oldfile;
304
675
    gchar* sql_errmsg = NULL;
305
676
    gchar* import_errmsg = NULL;
306
677
    KatzeArray* array;
 
678
    MidoriBookmarksDb* bookmarks;
307
679
 
308
680
    g_return_val_if_fail (errmsg != NULL, NULL);
309
681
 
321
693
    }
322
694
 
323
695
    if (midori_debug ("bookmarks"))
324
 
        sqlite3_trace (db, midori_bookmarks_dbtracer, NULL);
 
696
        sqlite3_trace (db, midori_bookmarks_db_dbtracer, NULL);
325
697
 
326
698
    create_stmt =     /* Table structure */
327
699
        "CREATE TABLE IF NOT EXISTS bookmarks "
442
814
 
443
815
    if (oldfile_exists)
444
816
        /* import from old db */
445
 
        if (!midori_bookmarks_import_from_old_db (db, oldfile, &import_errmsg))
 
817
        if (!midori_bookmarks_db_import_from_old_db (db, oldfile, &import_errmsg))
446
818
        {
447
819
            *errmsg = g_strdup_printf (_("Couldn't import from old database: %s\n"),
448
820
                import_errmsg ? import_errmsg : "(err = NULL)");
452
824
    init_success:
453
825
        g_free (newfile);
454
826
        g_free (oldfile);
455
 
        array = katze_array_new (KATZE_TYPE_ARRAY);
456
 
        g_signal_connect (array, "add-item",
457
 
                          G_CALLBACK (midori_bookmarks_add_item_cb), db);
458
 
        g_signal_connect (array, "remove-item",
459
 
                          G_CALLBACK (midori_bookmarks_remove_item_cb), db);
460
 
        g_object_set_data (G_OBJECT (array), "db", db);
461
 
        return array;
 
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;
462
832
 
463
833
    init_failed:
464
834
        g_free (newfile);
470
840
        return NULL;
471
841
}
472
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
 **/
473
851
void
474
 
midori_bookmarks_on_quit (KatzeArray* array)
 
852
midori_bookmarks_db_on_quit (MidoriBookmarksDb* bookmarks)
475
853
{
476
 
    g_return_if_fail (KATZE_IS_ARRAY (array));
 
854
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks));
477
855
 
478
 
    sqlite3* db = g_object_get_data (G_OBJECT (array), "db");
479
 
    g_return_if_fail (db != NULL);
480
 
    sqlite3_close (db);
 
856
    g_object_unref (bookmarks);
481
857
}
482
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
 **/
483
870
void
484
 
midori_bookmarks_import_array (KatzeArray* bookmarks,
 
871
midori_bookmarks_db_import_array (MidoriBookmarksDb* bookmarks,
485
872
                               KatzeArray* array,
486
873
                               gint64      parentid)
487
874
{
488
875
    GList* list;
489
876
    KatzeItem* item;
490
877
 
491
 
    if (!bookmarks)
492
 
        return;
 
878
    g_return_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks));
 
879
    g_return_if_fail (KATZE_IS_ARRAY (array));
493
880
 
494
881
    KATZE_ARRAY_FOREACH_ITEM_L (item, array, list)
495
882
    {
496
883
        katze_item_set_meta_integer (item, "parentid", parentid);
497
 
        katze_array_add_item (bookmarks, item);
 
884
        midori_bookmarks_db_add_item (bookmarks, item);
498
885
        if (KATZE_IS_ARRAY (item))
499
 
          midori_bookmarks_import_array (bookmarks, KATZE_ARRAY (item),
500
 
                                         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"));
501
888
    }
502
889
    g_list_free (list);
503
890
}
504
891
 
505
892
/**
506
 
 * 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:
507
977
 * @array: the main bookmark array
508
978
 * @fields: comma separated list of fields
509
979
 * @condition: condition, like "folder = '%q'"
514
984
 *
515
985
 * Return value: a #KatzeArray on success, %NULL otherwise
516
986
 *
517
 
 * Since: 0.4.4
 
987
 * Since: 0.5.2
518
988
 **/
519
989
KatzeArray*
520
 
midori_array_query_recursive (KatzeArray*  bookmarks,
521
 
                              const gchar* fields,
522
 
                              const gchar* condition,
523
 
                              const gchar* value,
524
 
                              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)
525
995
{
526
 
    sqlite3* db;
527
996
    gchar* sqlcmd;
528
997
    char* sqlcmd_value;
529
998
    KatzeArray* array;
530
999
    KatzeItem* item;
531
1000
    GList* list;
532
1001
 
533
 
    g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), NULL);
 
1002
    g_return_val_if_fail (IS_MIDORI_BOOKMARKS_DB (bookmarks), NULL);
534
1003
    g_return_val_if_fail (fields, NULL);
535
1004
    g_return_val_if_fail (condition, NULL);
536
 
    db = g_object_get_data (G_OBJECT (bookmarks), "db");
537
 
    g_return_val_if_fail (db != NULL, NULL);
538
1005
 
539
1006
    sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s "
540
1007
                              "ORDER BY (uri='') ASC, title DESC", fields, condition);
541
1008
    if (strstr (condition, "%q"))
542
1009
    {
543
1010
        sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");
544
 
        array = katze_array_from_sqlite (db, sqlcmd_value);
 
1011
        array = midori_bookmarks_db_array_from_sqlite (bookmarks, sqlcmd_value);
545
1012
        sqlite3_free (sqlcmd_value);
546
1013
    }
547
1014
    else
548
 
        array = katze_array_from_sqlite (db, sqlcmd);
 
1015
        array = midori_bookmarks_db_array_from_sqlite (bookmarks, sqlcmd);
549
1016
    g_free (sqlcmd);
550
1017
 
551
1018
    if (!recursive)
556
1023
        if (KATZE_ITEM_IS_FOLDER (item))
557
1024
        {
558
1025
            gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
559
 
                                               katze_item_get_meta_integer (item, "id"));
560
 
            KatzeArray* subarray = midori_array_query_recursive (bookmarks,
561
 
                                                                 fields, "parentid=%q", parentid, TRUE);
 
1026
                                               katze_item_get_meta_integer (item, "id"));
 
1027
            KatzeArray* subarray = midori_bookmarks_db_query_recursive (bookmarks,
 
1028
                                                                        fields, "parentid=%q", parentid, TRUE);
562
1029
            KatzeItem* subitem;
563
1030
            GList* sublist;
564
1031
 
576
1043
}
577
1044
 
578
1045
static gint64
579
 
count_from_sqlite (sqlite3*     db,
580
 
                   const gchar* sqlcmd)
 
1046
midori_bookmarks_db_count_from_sqlite (sqlite3*     db,
 
1047
                                       const gchar* sqlcmd)
581
1048
{
582
1049
    gint64 count = -1;
583
1050
    sqlite3_stmt* stmt;
584
1051
    gint result;
585
 
    
 
1052
 
586
1053
    result = sqlite3_prepare_v2 (db, sqlcmd, -1, &stmt, NULL);
587
1054
    if (result != SQLITE_OK)
588
1055
        return -1;
589
1056
 
590
1057
    g_assert (sqlite3_column_count (stmt) == 1);
591
 
    
 
1058
 
592
1059
    if ((result = sqlite3_step (stmt)) == SQLITE_ROW)
593
 
        count = sqlite3_column_int64(stmt, 0);
 
1060
        count = sqlite3_column_int64(stmt, 0);
594
1061
 
595
1062
    sqlite3_clear_bindings (stmt);
596
1063
    sqlite3_reset (stmt);
599
1066
}
600
1067
 
601
1068
static gint64
602
 
midori_array_count_recursive_by_id (KatzeArray*  bookmarks,
603
 
                                    const gchar* condition,
604
 
                                    const gchar* value,
605
 
                                    gint64       id,
606
 
                                    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)
607
1074
{
608
1075
    gint64 count = -1;
609
 
    sqlite3* db;
610
1076
    gchar* sqlcmd;
611
1077
    char* sqlcmd_value;
612
1078
    sqlite3_stmt* stmt;
615
1081
    GList* iter_ids;
616
1082
 
617
1083
    g_return_val_if_fail (condition, -1);
618
 
    g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), -1);
619
 
    db = g_object_get_data (G_OBJECT (bookmarks), "db");
620
 
    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);
621
1086
 
622
1087
    g_assert(!strstr("parentid", condition));
623
1088
 
624
1089
    if (id > 0)
625
 
        sqlcmd = g_strdup_printf ("SELECT COUNT(*) FROM bookmarks "
626
 
                                  "WHERE parentid = %" G_GINT64_FORMAT " AND %s",
627
 
                                  id,
628
 
                                  condition);
 
1090
        sqlcmd = g_strdup_printf ("SELECT COUNT(*) FROM bookmarks "
 
1091
                                  "WHERE parentid = %" G_GINT64_FORMAT " AND %s",
 
1092
                                  id,
 
1093
                                  condition);
629
1094
    else
630
 
        sqlcmd = g_strdup_printf ("SELECT COUNT(*) FROM bookmarks "
631
 
                                  "WHERE parentid IS NULL AND %s ",
632
 
                                  condition);
 
1095
        sqlcmd = g_strdup_printf ("SELECT COUNT(*) FROM bookmarks "
 
1096
                                  "WHERE parentid IS NULL AND %s ",
 
1097
                                  condition);
633
1098
 
634
1099
    if (strstr (condition, "%q"))
635
1100
    {
636
1101
        sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");
637
 
        count = count_from_sqlite (db, sqlcmd_value);
 
1102
        count = midori_bookmarks_db_count_from_sqlite (bookmarks->db, sqlcmd_value);
638
1103
        sqlite3_free (sqlcmd_value);
639
1104
    }
640
1105
    else
641
 
        count = count_from_sqlite (db, sqlcmd);
 
1106
        count = midori_bookmarks_db_count_from_sqlite (bookmarks->db, sqlcmd);
642
1107
 
643
1108
    g_free (sqlcmd);
644
1109
 
648
1113
    ids = NULL;
649
1114
 
650
1115
    if (id > 0)
651
 
        sqlcmd_value = sqlite3_mprintf (
652
 
            "SELECT id FROM bookmarks "
653
 
            "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);
654
1119
    else
655
 
        sqlcmd_value = sqlite3_mprintf (
656
 
            "SELECT id FROM bookmarks "
657
 
            "WHERE parentid IS NULL AND uri = ''");
 
1120
        sqlcmd_value = sqlite3_mprintf (
 
1121
            "SELECT id FROM bookmarks "
 
1122
            "WHERE parentid IS NULL AND uri = ''");
658
1123
 
659
 
    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)
660
1125
    {
661
 
        g_assert (sqlite3_column_count (stmt) == 1);
662
 
    
663
 
        if ((result = sqlite3_step (stmt)) == SQLITE_ROW)
664
 
        {
665
 
            gint64* pid = g_new (gint64, 1);
666
 
            
667
 
            *pid = sqlite3_column_int64(stmt, 0);
668
 
            ids = g_list_append (ids, pid);
669
 
        }
670
 
        
671
 
        sqlite3_clear_bindings (stmt);
672
 
        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);
673
1138
    }
674
1139
 
675
1140
    sqlite3_free (sqlcmd_value);
677
1142
    iter_ids = ids;
678
1143
    while (iter_ids)
679
1144
    {
680
 
        gint64 sub_count = midori_array_count_recursive_by_id (bookmarks,
681
 
                                                               condition,
682
 
                                                               value,
683
 
                                                               *(gint64*)(iter_ids->data),
684
 
                                                               recursive);
685
 
        
686
 
        if (sub_count < 0)
687
 
        {
688
 
            g_list_free_full (ids, g_free);
689
 
            return -1;
690
 
        }
691
 
        
692
 
        count += sub_count;
693
 
        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);
694
1159
    }
695
 
        
 
1160
 
696
1161
    g_list_free_full (ids, g_free);
697
1162
    return count;
698
1163
}
699
1164
 
700
1165
/**
701
 
 * midori_array_count_recursive:
702
 
 * @array: the main bookmark array
 
1166
 * midori_bookmarks_db_count_recursive:
 
1167
 * @bookmarks: the main bookmark array
703
1168
 * @condition: condition, like "folder = '%q'"
704
1169
 * @value: a value to be inserted if @condition contains %q
705
1170
 * @recursive: if %TRUE include children
709
1174
 * Since: 0.5.2
710
1175
 **/
711
1176
gint64
712
 
midori_array_count_recursive (KatzeArray*  bookmarks,
713
 
                              const gchar* condition,
714
 
                              const gchar* value,
715
 
                              KatzeItem*   folder,
716
 
                              gboolean     recursive)
 
1177
midori_bookmarks_db_count_recursive (MidoriBookmarksDb*  bookmarks,
 
1178
                                     const gchar*        condition,
 
1179
                                     const gchar*        value,
 
1180
                                     KatzeItem*          folder,
 
1181
                                     gboolean            recursive)
717
1182
{
718
1183
    gint64 id = -1;
719
1184
 
720
1185
    g_return_val_if_fail (!folder || KATZE_ITEM_IS_FOLDER (folder), -1);
721
 
    
 
1186
 
722
1187
    id = folder ? katze_item_get_meta_integer (folder, "id") : 0;
723
1188
 
724
 
    return midori_array_count_recursive_by_id (bookmarks, condition,
725
 
                                               value, id,
726
 
                                               recursive);
 
1189
    return midori_bookmarks_db_count_recursive_by_id (bookmarks, condition,
 
1190
                                                      value, id,
 
1191
                                                      recursive);
727
1192
}