Status: | Work in progress | ||||||||
---|---|---|---|---|---|---|---|---|---|
Proposed branch: | lp:~aauzi/midori/fix-894143 | ||||||||
Merge into: | lp:midori | ||||||||
Diff against target: |
3396 lines (+2255/-309) 10 files modified
katze/katze-array.c (+53/-2) katze/katze-arrayaction.c (+10/-0) katze/katze-utils.c (+90/-3) katze/katze-utils.h (+5/-0) midori/midori-array.c (+7/-0) midori/midori-bookmarks-db.c (+107/-15) midori/midori-bookmarks-db.h (+11/-9) midori/midori-browser.c (+11/-19) panels/midori-bookmarks.c (+1960/-260) tests/bookmarks.c (+1/-1) |
||||||||
To merge this branch: | bzr merge lp:~aauzi/midori/fix-894143 | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Midori Devs | Pending | ||
Review via email: mp+165249@code.launchpad.net |
Commit message
Description of the change
(For review: fix-1179200 is a prerequisite to fix-894143)
To post a comment you must log in.
lp:~aauzi/midori/fix-894143
updated
- 6340. By André Auzi
-
merge lp:midori after merge of fix-1179200-8
Unmerged revisions
- 6340. By André Auzi
-
merge lp:midori after merge of fix-1179200-8
- 6339. By André Auzi
-
Fix race condition in timestamp comparison
- 6338. By André Auzi
-
merge lp:midori
- 6337. By André Auzi
-
Fix Test #9 regression error
- 6336. By André Auzi
- 6335. By André Auzi
-
merge fix-xbel-
import- regression - 6334. By André Auzi
-
merge lp:midori
- 6333. By André Auzi
-
manage sort order in bookmarks test
- 6332. By André Auzi
-
merge lp:midori after insert of fix-1179200-4
- 6331. By André Auzi
-
Derivation of GtkTreeStore for DND drop destination control.
Inserts are delayed to handle move operations where move is actually an insert at destination, followed by a delete at the source and finally a row change callback.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'katze/katze-array.c' |
2 | --- katze/katze-array.c 2013-11-04 20:57:37 +0000 |
3 | +++ katze/katze-array.c 2014-01-30 21:24:26 +0000 |
4 | @@ -33,6 +33,15 @@ |
5 | GList* items; |
6 | }; |
7 | |
8 | +enum |
9 | +{ |
10 | + PROP_0, |
11 | + |
12 | + PROP_TYPE, |
13 | + |
14 | + N_PROPERTIES |
15 | +}; |
16 | + |
17 | enum { |
18 | ADD_ITEM, |
19 | REMOVE_ITEM, |
20 | @@ -55,6 +64,17 @@ |
21 | { |
22 | g_object_set_data (G_OBJECT (array), "last-update", |
23 | GINT_TO_POINTER (time (NULL))); |
24 | +/* #define DEBUG_UPDATE */ |
25 | +#ifdef DEBUG_UPDATE |
26 | + if (KATZE_IS_ITEM (array)) |
27 | + { |
28 | + const gchar *name = katze_item_get_name (KATZE_ITEM (array)); |
29 | + if (name && *name) |
30 | + { |
31 | + g_print ("_katze_array_update: %s\n", name); |
32 | + } |
33 | + } |
34 | +#endif |
35 | } |
36 | |
37 | static void |
38 | @@ -105,6 +125,27 @@ |
39 | } |
40 | |
41 | static void |
42 | +_katze_array_set_property (GObject *object, |
43 | + guint property_id, |
44 | + const GValue *value, |
45 | + GParamSpec *pspec) |
46 | +{ |
47 | + KatzeArray *array = KATZE_ARRAY (object); |
48 | + |
49 | + switch (property_id) |
50 | + { |
51 | + case PROP_TYPE: |
52 | + array->priv->type = g_value_get_gtype (value); |
53 | + break; |
54 | + |
55 | + default: |
56 | + /* We don't have any other property... */ |
57 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
58 | + break; |
59 | + } |
60 | +} |
61 | + |
62 | +static void |
63 | katze_array_class_init (KatzeArrayClass* class) |
64 | { |
65 | GObjectClass* gobject_class; |
66 | @@ -187,6 +228,7 @@ |
67 | |
68 | gobject_class = G_OBJECT_CLASS (class); |
69 | gobject_class->finalize = katze_array_finalize; |
70 | + gobject_class->set_property = _katze_array_set_property; |
71 | |
72 | class->add_item = _katze_array_add_item; |
73 | class->remove_item = _katze_array_remove_item; |
74 | @@ -194,6 +236,16 @@ |
75 | class->clear = _katze_array_clear; |
76 | class->update = _katze_array_update; |
77 | |
78 | + |
79 | + g_object_class_install_property (gobject_class, |
80 | + PROP_TYPE, |
81 | + g_param_spec_gtype ( |
82 | + "type", |
83 | + "Type", |
84 | + "The array item type", |
85 | + G_TYPE_NONE, |
86 | + G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); |
87 | + |
88 | g_type_class_add_private (class, sizeof (KatzeArrayPrivate)); |
89 | } |
90 | |
91 | @@ -238,8 +290,7 @@ |
92 | |
93 | g_return_val_if_fail (g_type_is_a (type, G_TYPE_OBJECT), NULL); |
94 | |
95 | - array = g_object_new (KATZE_TYPE_ARRAY, NULL); |
96 | - array->priv->type = type; |
97 | + array = g_object_new (KATZE_TYPE_ARRAY, "type", type, NULL); |
98 | |
99 | return array; |
100 | } |
101 | |
102 | === modified file 'katze/katze-arrayaction.c' |
103 | --- katze/katze-arrayaction.c 2012-12-16 18:40:00 +0000 |
104 | +++ katze/katze-arrayaction.c 2014-01-30 21:24:26 +0000 |
105 | @@ -767,12 +767,14 @@ |
106 | KatzeArray* array) |
107 | { |
108 | GSList* proxies; |
109 | + KatzeArray *old_array = NULL; |
110 | |
111 | g_return_if_fail (KATZE_IS_ARRAY_ACTION (array_action)); |
112 | g_return_if_fail (!array || katze_array_is_a (array, KATZE_TYPE_ITEM)); |
113 | |
114 | /* FIXME: Disconnect old array */ |
115 | |
116 | + old_array = array_action->array; |
117 | if (array) |
118 | g_object_ref (array); |
119 | katze_object_assign (array_action->array, array); |
120 | @@ -793,7 +795,15 @@ |
121 | |
122 | do |
123 | { |
124 | + KatzeArray* item = g_object_get_data (G_OBJECT (proxies->data), "KatzeItem"); |
125 | + |
126 | + if (item && (item == old_array)) |
127 | + g_object_set_data (G_OBJECT (proxies->data), "KatzeItem", array); |
128 | + |
129 | gtk_widget_set_sensitive (proxies->data, array != NULL); |
130 | } |
131 | while ((proxies = g_slist_next (proxies))); |
132 | + |
133 | + if (array) |
134 | + katze_array_update (KATZE_ARRAY (array)); |
135 | } |
136 | |
137 | === modified file 'katze/katze-utils.c' |
138 | --- katze/katze-utils.c 2013-11-05 21:51:18 +0000 |
139 | +++ katze/katze-utils.c 2014-01-30 21:24:26 +0000 |
140 | @@ -1002,12 +1002,99 @@ |
141 | |
142 | g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE); |
143 | |
144 | - if ((selection = gtk_tree_view_get_selection (treeview))) |
145 | - if (gtk_tree_selection_get_selected (selection, model, iter)) |
146 | - return TRUE; |
147 | + selection = gtk_tree_view_get_selection(treeview); |
148 | + |
149 | + switch (gtk_tree_selection_get_mode (selection)) |
150 | + { |
151 | + default: |
152 | + break; |
153 | + |
154 | + case GTK_SELECTION_SINGLE: |
155 | + case GTK_SELECTION_BROWSE: |
156 | + if (gtk_tree_selection_get_selected (selection, model, iter)) |
157 | + return TRUE; |
158 | + break; |
159 | + |
160 | + case GTK_SELECTION_MULTIPLE: |
161 | + if (gtk_tree_selection_count_selected_rows (selection) == 1) |
162 | + { |
163 | + GtkTreeModel *stock_model; |
164 | + GList *list = gtk_tree_selection_get_selected_rows (selection, &stock_model); |
165 | + |
166 | + if (model) |
167 | + *model = stock_model; |
168 | + |
169 | + if (list) |
170 | + { |
171 | + GtkTreePath *path = (GtkTreePath *)g_list_nth_data (list, 0); |
172 | + |
173 | + if (path && (!iter || gtk_tree_model_get_iter (stock_model, iter, path))) |
174 | + { |
175 | + g_list_free_full(list, (GDestroyNotify) gtk_tree_path_free); |
176 | + return TRUE; |
177 | + } |
178 | + |
179 | + g_list_free_full(list, (GDestroyNotify) gtk_tree_path_free); |
180 | + } |
181 | + } |
182 | + } |
183 | + |
184 | return FALSE; |
185 | } |
186 | |
187 | +/** |
188 | + * katze_tree_view_get_selected_rows: |
189 | + * @treeview: a #GtkTreeView |
190 | + * @model: a pointer to store the #GtkTreeModel, or %NULL |
191 | + * @rows: a pointer to store the #GList of #GtkTreePath, or %NULL |
192 | + * |
193 | + * Determines whether there is a selection in @treeview |
194 | + * and sets the @rows to the current selection. |
195 | + * |
196 | + * If there is a selection and @model is not %NULL, it is |
197 | + * set to the model. If @model is %NULL, the @rows will be |
198 | + * set to %NULL. |
199 | + * |
200 | + * Either @model or @rows or both can be %NULL in which case |
201 | + * no value will be assigned in any case. |
202 | + * |
203 | + * When @rows is not %NULL it must be freed using: |
204 | + * g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); |
205 | + * |
206 | + * Return value: the count of selected rows |
207 | + * |
208 | + * Since: 0.4.7.aau.1 |
209 | + **/ |
210 | + |
211 | +gint |
212 | +katze_tree_view_get_selected_rows (GtkTreeView* treeview, |
213 | + GtkTreeModel** model, |
214 | + GList** rows) |
215 | +{ |
216 | + gint count; |
217 | + GtkTreeSelection* selection; |
218 | + |
219 | + if (model) |
220 | + *model = NULL; |
221 | + if (rows) |
222 | + *rows = NULL; |
223 | + |
224 | + g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), 0); |
225 | + |
226 | + selection = gtk_tree_view_get_selection(treeview); |
227 | + |
228 | + count = gtk_tree_selection_count_selected_rows (selection); |
229 | + if (count > 0) |
230 | + { |
231 | + if (model && rows) |
232 | + { |
233 | + *rows = gtk_tree_selection_get_selected_rows (selection, model); |
234 | + } |
235 | + } |
236 | + |
237 | + return count; |
238 | +} |
239 | + |
240 | void |
241 | katze_bookmark_populate_tree_view (KatzeArray* array, |
242 | GtkTreeStore* model, |
243 | |
244 | === modified file 'katze/katze-utils.h' |
245 | --- katze/katze-utils.h 2013-04-16 22:10:56 +0000 |
246 | +++ katze/katze-utils.h 2014-01-30 21:24:26 +0000 |
247 | @@ -88,6 +88,11 @@ |
248 | GtkTreeModel** model, |
249 | GtkTreeIter* iter); |
250 | |
251 | +gint |
252 | +katze_tree_view_get_selected_rows (GtkTreeView* treeview, |
253 | + GtkTreeModel** model, |
254 | + GList** rows); |
255 | + |
256 | void |
257 | katze_bookmark_populate_tree_view (KatzeArray* array, |
258 | GtkTreeStore* model, |
259 | |
260 | === modified file 'midori/midori-array.c' |
261 | --- midori/midori-array.c 2013-08-05 19:52:52 +0000 |
262 | +++ midori/midori-array.c 2014-01-30 21:24:26 +0000 |
263 | @@ -1031,9 +1031,16 @@ |
264 | || g_str_equal (name, "last_visit") || g_str_equal (name, "visit_count") |
265 | || g_str_equal (name, "pos_panel") || g_str_equal (name, "pos_bar")) |
266 | { |
267 | +#if 0 |
268 | gint value; |
269 | value = sqlite3_column_int64 (stmt, column); |
270 | katze_item_set_meta_integer (item, name, value); |
271 | +#else |
272 | + /* use text to properly handle NULL values */ |
273 | + const unsigned char* text; |
274 | + text = sqlite3_column_text (stmt, column); |
275 | + katze_item_set_meta_string (item, name, (gchar*)text); |
276 | +#endif |
277 | } |
278 | else if (g_str_equal (name, "desc")) |
279 | { |
280 | |
281 | === modified file 'midori/midori-bookmarks-db.c' |
282 | --- midori/midori-bookmarks-db.c 2014-01-24 23:04:05 +0000 |
283 | +++ midori/midori-bookmarks-db.c 2014-01-30 21:24:26 +0000 |
284 | @@ -181,14 +181,29 @@ |
285 | midori_bookmarks_db_get_item_parent (MidoriBookmarksDb* bookmarks, |
286 | gpointer item) |
287 | { |
288 | + gint64 parentid = katze_item_get_meta_integer (KATZE_ITEM (item), "parentid"); |
289 | + KatzeItem *search = katze_item_new (); |
290 | KatzeArray* parent; |
291 | - gint64 parentid; |
292 | - |
293 | - parentid = katze_item_get_meta_integer (KATZE_ITEM (item), "parentid"); |
294 | - |
295 | - if (parentid == 0) |
296 | - { |
297 | + |
298 | + if (!parentid) |
299 | + { |
300 | + parentid = katze_item_get_meta_integer (KATZE_ITEM (bookmarks), "id"); |
301 | + katze_item_set_meta_integer (KATZE_ITEM (item), "parentid", parentid); |
302 | + } |
303 | + |
304 | + katze_item_set_meta_integer(search, "id", parentid); |
305 | + |
306 | + parent = KATZE_ARRAY (g_hash_table_lookup (bookmarks->all_items, search)); |
307 | + |
308 | + g_object_unref (search); |
309 | + |
310 | + if (!parent) |
311 | + { |
312 | + g_warning ("item parent not found\n"); |
313 | + |
314 | parent = KATZE_ARRAY (bookmarks); |
315 | + katze_item_set_meta_integer (KATZE_ITEM (item), "parentid", |
316 | + katze_item_get_meta_integer (KATZE_ITEM (bookmarks), "id")); |
317 | } |
318 | else |
319 | { |
320 | @@ -267,7 +282,10 @@ |
321 | |
322 | g_return_if_fail (parent); |
323 | |
324 | - katze_array_update (parent); |
325 | + if (IS_MIDORI_BOOKMARKS_DB (parent)) |
326 | + KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->update (parent); |
327 | + else |
328 | + katze_array_update (parent); |
329 | } |
330 | |
331 | /** |
332 | @@ -479,7 +497,7 @@ |
333 | else if (old_parent && katze_item_get_meta_integer (old_parent, "id") > 0) |
334 | new_parentid = g_strdup_printf ("%" G_GINT64_FORMAT, katze_item_get_meta_integer (old_parent, "id")); |
335 | else |
336 | - new_parentid = g_strdup_printf ("NULL"); |
337 | + new_parentid = g_strdup ("NULL"); |
338 | |
339 | sqlcmd = sqlite3_mprintf ( |
340 | "INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) " |
341 | @@ -557,7 +575,8 @@ |
342 | |
343 | sqlcmd = sqlite3_mprintf ( |
344 | "UPDATE bookmarks SET " |
345 | - "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d " |
346 | + "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d, " |
347 | + "pos_bar=%d, pos_panel=%d " |
348 | "WHERE id = %q ;", |
349 | parentid, |
350 | katze_item_get_name (item), |
351 | @@ -565,6 +584,8 @@ |
352 | katze_str_non_null (katze_item_get_meta_string (item, "desc")), |
353 | katze_item_get_meta_boolean (item, "toolbar"), |
354 | katze_item_get_meta_boolean (item, "app"), |
355 | + (gint)katze_item_get_meta_integer (item, "pos_bar"), |
356 | + (gint)katze_item_get_meta_integer (item, "pos_panel"), |
357 | id); |
358 | |
359 | updated = TRUE; |
360 | @@ -579,6 +600,14 @@ |
361 | g_free (parentid); |
362 | g_free (id); |
363 | |
364 | +#ifdef DEBUG_DB_UPDATE |
365 | + g_print ("update:%s - parentid: %s, pos_bar:%d, pos_panel:%d\n", |
366 | + katze_item_get_name (item), |
367 | + parentid, |
368 | + (gint)katze_item_get_meta_integer (item, "pos_bar"), |
369 | + (gint)katze_item_get_meta_integer (item, "pos_panel")); |
370 | +#endif |
371 | + |
372 | return updated; |
373 | } |
374 | |
375 | @@ -710,10 +739,10 @@ |
376 | g_return_val_if_fail (errmsg != NULL, NULL); |
377 | |
378 | database = midori_bookmarks_database_new (&error); |
379 | - |
380 | + |
381 | if (error != NULL) |
382 | { |
383 | - *errmsg = g_strdup (error->message); |
384 | + *errmsg = g_strdup (error->message); |
385 | g_error_free (error); |
386 | return NULL; |
387 | } |
388 | @@ -724,7 +753,10 @@ |
389 | if (midori_debug ("bookmarks")) |
390 | sqlite3_trace (db, midori_bookmarks_db_dbtracer, NULL); |
391 | |
392 | - bookmarks = MIDORI_BOOKMARKS_DB (g_object_new (TYPE_MIDORI_BOOKMARKS_DB, NULL)); |
393 | + bookmarks = MIDORI_BOOKMARKS_DB (g_object_new (TYPE_MIDORI_BOOKMARKS_DB, |
394 | + "type", KATZE_TYPE_ITEM, |
395 | + NULL)); |
396 | + |
397 | bookmarks->db = db; |
398 | |
399 | g_object_set_data (G_OBJECT (bookmarks), "db", db); |
400 | @@ -776,6 +808,7 @@ |
401 | katze_item_set_meta_integer (item, "parentid", parentid); |
402 | midori_bookmarks_db_add_item (bookmarks, item); |
403 | } |
404 | + |
405 | g_list_free (list); |
406 | } |
407 | |
408 | @@ -859,7 +892,7 @@ |
409 | * @array: the main bookmark array |
410 | * @sqlcmd: the sqlcmd to execute |
411 | * |
412 | - * Internal function that process the requested @sqlcmd. |
413 | + * Internal function that processes the requested @sqlcmd. |
414 | * |
415 | * Return value: a #KatzeArray on success, %NULL otherwise |
416 | **/ |
417 | @@ -885,6 +918,12 @@ |
418 | * @fields: comma separated list of fields |
419 | * @condition: condition, like "folder = '%q'" |
420 | * @value: a value to be inserted if @condition contains %q |
421 | + * @order: a value to be inserted in "ORDER BY" |
422 | + * default order is : |
423 | + * (uri='') ASC, title DESC |
424 | + * @order is inserted before title. |
425 | + * order then becomes : |
426 | + * (uri='') ASC, @order title DESC |
427 | * @recursive: if %TRUE include children |
428 | * |
429 | * Stores the result in a #KatzeArray. |
430 | @@ -898,6 +937,7 @@ |
431 | const gchar* fields, |
432 | const gchar* condition, |
433 | const gchar* value, |
434 | + const gchar* order, |
435 | gboolean recursive) |
436 | { |
437 | gchar* sqlcmd; |
438 | @@ -911,7 +951,7 @@ |
439 | g_return_val_if_fail (condition, NULL); |
440 | |
441 | sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s " |
442 | - "ORDER BY (uri='') ASC, title DESC", fields, condition); |
443 | + "ORDER BY (uri='') ASC, %s title DESC", fields, condition, order ? order : ""); |
444 | if (strstr (condition, "%q")) |
445 | { |
446 | sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : ""); |
447 | @@ -932,7 +972,7 @@ |
448 | gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT, |
449 | katze_item_get_meta_integer (item, "id")); |
450 | KatzeArray* subarray = midori_bookmarks_db_query_recursive (bookmarks, |
451 | - fields, "parentid=%q", parentid, TRUE); |
452 | + fields, "parentid=%q", parentid, order, TRUE); |
453 | KatzeItem* subitem; |
454 | GList* sublist; |
455 | |
456 | @@ -1097,3 +1137,55 @@ |
457 | value, id, |
458 | recursive); |
459 | } |
460 | + |
461 | +/** |
462 | + * midori_bookmarks_db_populate_folder: |
463 | + **/ |
464 | + |
465 | +void |
466 | +midori_bookmarks_db_populate_folder (MidoriBookmarksDb* bookmarks, |
467 | + KatzeArray *folder) |
468 | +{ |
469 | + const gchar* id = katze_item_get_meta_string (KATZE_ITEM (folder), "id"); |
470 | + const gchar *condition; |
471 | + KatzeArray* array; |
472 | + KatzeItem* item; |
473 | + GList* list; |
474 | + |
475 | + if (id == NULL) |
476 | + { |
477 | + condition = "parentid is NULL"; |
478 | + } |
479 | + else |
480 | + { |
481 | + condition = "parentid = %q"; |
482 | + } |
483 | + |
484 | + array = midori_bookmarks_db_query_recursive (bookmarks, |
485 | + "id, title, parentid, uri, app, pos_panel, pos_bar", condition, id, "pos_panel ASC,", FALSE); |
486 | + |
487 | + if (IS_MIDORI_BOOKMARKS_DB (folder)) |
488 | + { |
489 | + KATZE_ARRAY_FOREACH_ITEM_L (item, folder, list) |
490 | + { |
491 | + KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->remove_item (folder, item); |
492 | + } |
493 | + |
494 | + KATZE_ARRAY_FOREACH_ITEM_L (item, array, list) |
495 | + { |
496 | + KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->add_item (folder, item); |
497 | + } |
498 | + } |
499 | + else |
500 | + { |
501 | + katze_array_clear(folder); |
502 | + |
503 | + KATZE_ARRAY_FOREACH_ITEM_L (item, array, list) |
504 | + { |
505 | + katze_array_add_item (folder, item); |
506 | + } |
507 | + } |
508 | + |
509 | + g_object_unref (array); |
510 | +} |
511 | + |
512 | |
513 | === modified file 'midori/midori-bookmarks-db.h' |
514 | --- midori/midori-bookmarks-db.h 2013-09-17 19:34:23 +0000 |
515 | +++ midori/midori-bookmarks-db.h 2014-01-30 21:24:26 +0000 |
516 | @@ -62,19 +62,21 @@ |
517 | const gchar* fields, |
518 | const gchar* condition, |
519 | const gchar* value, |
520 | + const gchar* order, |
521 | gboolean recursive); |
522 | |
523 | gint64 |
524 | midori_bookmarks_db_count_recursive (MidoriBookmarksDb* bookmarks, |
525 | - const gchar* condition, |
526 | + const gchar* condition, |
527 | const gchar* value, |
528 | - KatzeItem* folder, |
529 | - gboolean recursive); |
530 | - |
531 | -gint64 |
532 | -midori_bookmarks_insert_item_db (sqlite3* db, |
533 | - KatzeItem* item, |
534 | - gint64 parentid); |
535 | + KatzeItem* folder, |
536 | + gboolean recursive); |
537 | + |
538 | +void |
539 | +midori_bookmarks_db_on_quit (MidoriBookmarksDb* array); |
540 | + |
541 | +void |
542 | +midori_bookmarks_db_populate_folder (MidoriBookmarksDb* bookmarks, |
543 | + KatzeArray *folder); |
544 | |
545 | #endif /* !__MIDORI_BOOKMARKS_DB_H__ */ |
546 | - |
547 | |
548 | === modified file 'midori/midori-browser.c' |
549 | --- midori/midori-browser.c 2014-01-06 23:05:10 +0000 |
550 | +++ midori/midori-browser.c 2014-01-30 21:24:26 +0000 |
551 | @@ -1025,7 +1025,7 @@ |
552 | static gint64 |
553 | midori_bookmark_folder_button_get_active (GtkWidget* combo) |
554 | { |
555 | - gint64 id = 0; |
556 | + gint64 id = -1; |
557 | GtkTreeIter iter; |
558 | |
559 | g_return_val_if_fail (GTK_IS_COMBO_BOX (combo), 0); |
560 | @@ -3107,29 +3107,17 @@ |
561 | KatzeArray* folder, |
562 | MidoriBrowser* browser) |
563 | { |
564 | - KatzeArray* bookmarks; |
565 | - const gchar* id = katze_item_get_meta_string (KATZE_ITEM (folder), "id"); |
566 | - gchar* condition; |
567 | - |
568 | if (browser->bookmarks == NULL) |
569 | return FALSE; |
570 | |
571 | - if (id == NULL) |
572 | - condition = "parentid is NULL"; |
573 | - else |
574 | - condition = "parentid = %q"; |
575 | - |
576 | - bookmarks = midori_bookmarks_db_query_recursive (browser->bookmarks, |
577 | - "id, title, parentid, uri, app, pos_panel, pos_bar", condition, id, FALSE); |
578 | - if (!bookmarks) |
579 | - return FALSE; |
580 | + midori_bookmarks_db_populate_folder (browser->bookmarks, folder); |
581 | |
582 | /* Clear items from dummy array here */ |
583 | gtk_container_foreach (GTK_CONTAINER (menu), |
584 | (GtkCallback)(gtk_widget_destroy), NULL); |
585 | |
586 | /* "Import Bookmarks" and "Export Bookmarks" at the top */ |
587 | - if (id == NULL) |
588 | + if (folder == KATZE_ARRAY (browser->bookmarks)) |
589 | { |
590 | GtkWidget* menuitem; |
591 | menuitem = gtk_action_create_menu_item (_action_by_name (browser, "BookmarksImport")); |
592 | @@ -3143,7 +3131,7 @@ |
593 | gtk_widget_show (menuitem); |
594 | } |
595 | |
596 | - if (katze_array_is_empty (bookmarks)) |
597 | + if (katze_array_is_empty (folder)) |
598 | { |
599 | GtkWidget* menuitem = gtk_image_menu_item_new_with_label (_("Empty")); |
600 | gtk_widget_set_sensitive (menuitem, FALSE); |
601 | @@ -3152,7 +3140,7 @@ |
602 | return TRUE; |
603 | } |
604 | |
605 | - katze_array_action_generate_menu (KATZE_ARRAY_ACTION (action), bookmarks, |
606 | + katze_array_action_generate_menu (KATZE_ARRAY_ACTION (action), folder, |
607 | menu, GTK_WIDGET (browser)); |
608 | return TRUE; |
609 | } |
610 | @@ -4502,7 +4490,7 @@ |
611 | |
612 | error = NULL; |
613 | bookmarks = midori_bookmarks_db_query_recursive (browser->bookmarks, |
614 | - "*", "parentid IS NULL", NULL, TRUE); |
615 | + "*", "parentid IS NULL", NULL, NULL, TRUE); |
616 | if (!midori_array_to_file (bookmarks, path, format, &error)) |
617 | { |
618 | sokoke_message_dialog (GTK_MESSAGE_ERROR, |
619 | @@ -6702,7 +6690,7 @@ |
620 | gtk_separator_tool_item_new (), -1); |
621 | |
622 | array = midori_bookmarks_db_query_recursive (browser->bookmarks, |
623 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL, FALSE); |
624 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL, "pos_bar ASC,", FALSE); |
625 | if (!array) |
626 | { |
627 | _action_set_sensitive (browser, "BookmarkAdd", FALSE); |
628 | @@ -6756,6 +6744,10 @@ |
629 | midori_bookmarkbar_remove_item_cb, browser); |
630 | } |
631 | |
632 | + g_object_set (G_OBJECT (_action_by_name (browser, "Bookmarks")), |
633 | + "array", KATZE_ARRAY (bookmarks), |
634 | + NULL); |
635 | + |
636 | settings = midori_browser_get_settings (browser); |
637 | g_signal_handlers_disconnect_by_func (settings, |
638 | midori_browser_show_bookmarkbar_notify_value_cb, browser); |
639 | |
640 | === modified file 'panels/midori-bookmarks.c' |
641 | --- panels/midori-bookmarks.c 2014-01-24 23:04:05 +0000 |
642 | +++ panels/midori-bookmarks.c 2014-01-30 21:24:26 +0000 |
643 | @@ -26,6 +26,151 @@ |
644 | |
645 | #define COMPLETION_DELAY 200 |
646 | |
647 | +#define MIDORI_BOOKMARKS_TREE_MODEL_TARGET "GTK_TREE_MODEL_ROW" |
648 | + |
649 | +G_BEGIN_DECLS |
650 | + |
651 | +#define MIDORI_BOOKMARKS_TREE_STORE_TYPE \ |
652 | + (midori_bookmarks_tree_store_get_type ()) |
653 | +#define MIDORI_BOOKMARKS_TREE_STORE(obj) \ |
654 | + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_BOOKMARKS_TREE_STORE_TYPE, MidoriBookmarksTreeStore)) |
655 | +#define MIDORI_BOOKMARKS_TREE_STORE_CLASS(klass) \ |
656 | + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_BOOKMARKS_TREE_STORE_TYPE, MidoriBookmarksTreeStoreClass)) |
657 | + |
658 | +static gboolean |
659 | +midori_bookmarks_tree_store_drag_data_get (GtkTreeDragSource* drag_source, |
660 | + GtkTreePath* source_path, |
661 | + GtkSelectionData* selection_data); |
662 | +static gboolean |
663 | +midori_bookmarks_tree_store_drag_data_delete (GtkTreeDragSource* drag_source, |
664 | + GtkTreePath* source_path); |
665 | +static gboolean |
666 | +midori_bookmarks_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest, |
667 | + GtkTreePath *dest_path, |
668 | + GtkSelectionData *selection_data); |
669 | +static gboolean |
670 | +midori_bookmarks_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, |
671 | + GtkTreePath *dest_path, |
672 | + GtkSelectionData *selection_data); |
673 | + |
674 | +typedef struct _MidoriBookmarksTreeStore MidoriBookmarksTreeStore; |
675 | +typedef struct _MidoriBookmarksTreeStoreClass MidoriBookmarksTreeStoreClass; |
676 | +typedef struct _TreeRowData TreeRowData; |
677 | + |
678 | +struct _MidoriBookmarksTreeStore |
679 | +{ |
680 | + GtkTreeStore parent_instance; |
681 | + |
682 | + GList* stock_got_rows; |
683 | + GtkTreeView *_view; |
684 | +}; |
685 | + |
686 | +struct _MidoriBookmarksTreeStoreClass |
687 | +{ |
688 | + GtkTreeStoreClass parent_class; |
689 | +}; |
690 | + |
691 | +struct _TreeRowData |
692 | +{ |
693 | + GtkTreeModel *model; |
694 | + gchar path[4]; |
695 | +}; |
696 | + |
697 | +static GtkTreeDragSourceIface * |
698 | +gtk_tree_store_gtk_tree_drag_source_iface = NULL; |
699 | +static GtkTreeDragDestIface * |
700 | +gtk_tree_store_gtk_tree_drag_dest_iface = NULL; |
701 | + |
702 | +static void |
703 | +midori_bookmarks_tree_store_drag_source_init (GtkTreeDragSourceIface *iface) |
704 | +{ |
705 | + gtk_tree_store_gtk_tree_drag_source_iface = g_type_interface_peek_parent (iface); |
706 | + |
707 | + iface->drag_data_get = midori_bookmarks_tree_store_drag_data_get; |
708 | + iface->drag_data_delete = midori_bookmarks_tree_store_drag_data_delete; |
709 | +} |
710 | + |
711 | +static void |
712 | +midori_bookmarks_tree_store_drag_dest_init (GtkTreeDragDestIface *iface) |
713 | +{ |
714 | + gtk_tree_store_gtk_tree_drag_dest_iface = g_type_interface_peek_parent (iface); |
715 | + |
716 | + iface->row_drop_possible = midori_bookmarks_tree_store_row_drop_possible; |
717 | + iface->drag_data_received = midori_bookmarks_tree_store_drag_data_received; |
718 | +} |
719 | + |
720 | +static void |
721 | +midori_bookmarks_tree_store_init (MidoriBookmarksTreeStore* item) |
722 | +{ |
723 | + item->stock_got_rows = NULL; |
724 | + item->_view = NULL; |
725 | +} |
726 | + |
727 | +static void |
728 | +midori_bookmarks_tree_store_class_init (MidoriBookmarksTreeStoreClass *class) |
729 | +{ |
730 | +} |
731 | + |
732 | +G_DEFINE_TYPE_WITH_CODE (MidoriBookmarksTreeStore, |
733 | + midori_bookmarks_tree_store, |
734 | + GTK_TYPE_TREE_STORE, |
735 | + G_IMPLEMENT_INTERFACE ( |
736 | + GTK_TYPE_TREE_DRAG_SOURCE, |
737 | + midori_bookmarks_tree_store_drag_source_init) |
738 | + G_IMPLEMENT_INTERFACE ( |
739 | + GTK_TYPE_TREE_DRAG_DEST, |
740 | + midori_bookmarks_tree_store_drag_dest_init)); |
741 | + |
742 | + |
743 | +GtkTreeStore* |
744 | +midori_bookmarks_tree_store_new (gint n_columns, ...) |
745 | +{ |
746 | + GtkTreeStore* tree_store = GTK_TREE_STORE (g_object_new (MIDORI_BOOKMARKS_TREE_STORE_TYPE, NULL)); |
747 | + va_list ap; |
748 | + GType* types; |
749 | + gint n; |
750 | + |
751 | + if (!tree_store) |
752 | + return NULL; |
753 | + |
754 | + types = g_new (GType, n_columns); |
755 | + |
756 | + if (!types) |
757 | + { |
758 | + g_object_unref(tree_store); |
759 | + return NULL; |
760 | + } |
761 | + |
762 | + va_start(ap, n_columns); |
763 | + for (n = 0; n < n_columns; n++) |
764 | + { |
765 | + types[n] = va_arg(ap, GType); |
766 | + } |
767 | + va_end(ap); |
768 | + |
769 | + gtk_tree_store_set_column_types (tree_store, |
770 | + n_columns, |
771 | + types); |
772 | + |
773 | + g_free (types); |
774 | + return tree_store; |
775 | +} |
776 | + |
777 | +GtkTreeStore* |
778 | +midori_bookmarks_tree_store_newv (gint n_columns, GType *types) |
779 | +{ |
780 | + GtkTreeStore* tree_store = GTK_TREE_STORE (g_object_new (MIDORI_BOOKMARKS_TREE_STORE_TYPE, NULL)); |
781 | + |
782 | + if (!tree_store) |
783 | + return NULL; |
784 | + |
785 | + gtk_tree_store_set_column_types (tree_store, |
786 | + n_columns, |
787 | + types); |
788 | + |
789 | + return tree_store; |
790 | +} |
791 | + |
792 | gboolean |
793 | midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, |
794 | KatzeItem* bookmark_or_parent, |
795 | @@ -37,6 +182,12 @@ |
796 | midori_browser_open_bookmark (MidoriBrowser* browser, |
797 | KatzeItem* item); |
798 | |
799 | +static void |
800 | +midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
801 | + GtkTreePath* path, |
802 | + GtkTreeIter* iter, |
803 | + MidoriBookmarks* bookmarks); |
804 | + |
805 | struct _MidoriBookmarks |
806 | { |
807 | GtkVBox parent_instance; |
808 | @@ -50,7 +201,19 @@ |
809 | gint filter_timeout; |
810 | gchar* filter; |
811 | |
812 | + GList* pending_inserts; |
813 | KatzeItem* hovering_item; |
814 | + |
815 | + struct _stock_pending_event |
816 | + { |
817 | + gint x; |
818 | + gint y; |
819 | + } *pending_event, |
820 | + stock_pending_event; |
821 | + |
822 | + GHashTable* updated_items; |
823 | + GList* added_paths; |
824 | + GList* reordered_paths; |
825 | }; |
826 | |
827 | struct _MidoriBookmarksClass |
828 | @@ -88,36 +251,47 @@ |
829 | GParamSpec* pspec); |
830 | |
831 | static void |
832 | -midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
833 | - GtkTreePath* path, |
834 | - GtkTreeIter* iter, |
835 | - MidoriBookmarks* bookmarks); |
836 | - |
837 | +midori_bookmarks_update_cb (KatzeArray* array, |
838 | + MidoriBookmarks* bookmarks); |
839 | static void |
840 | midori_bookmarks_add_item_cb (KatzeArray* array, |
841 | KatzeItem* item, |
842 | MidoriBookmarks* bookmarks); |
843 | - |
844 | static void |
845 | midori_bookmarks_update_item_cb (KatzeArray* array, |
846 | - KatzeItem* item, |
847 | - MidoriBookmarks* bookmarks); |
848 | - |
849 | + KatzeItem* item, |
850 | + MidoriBookmarks* bookmarks); |
851 | static void |
852 | midori_bookmarks_remove_item_cb (KatzeArray* array, |
853 | KatzeItem* item, |
854 | MidoriBookmarks* bookmarks); |
855 | |
856 | static void |
857 | -midori_bookmarks_update_cb (KatzeArray* array, |
858 | - MidoriBookmarks* bookmarks); |
859 | +midori_bookmarks_row_inserted_cb (GtkTreeModel* model, |
860 | + GtkTreePath* path, |
861 | + GtkTreeIter* iter, |
862 | + MidoriBookmarks* bookmarks); |
863 | +static void |
864 | +midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
865 | + GtkTreePath* path, |
866 | + GtkTreeIter* iter, |
867 | + MidoriBookmarks* bookmarks); |
868 | +static void |
869 | +midori_bookmarks_row_deleted_cb (GtkTreeModel* model, |
870 | + GtkTreePath* path, |
871 | + MidoriBookmarks* bookmarks); |
872 | + |
873 | +static void |
874 | +midori_bookmarks_update_item (MidoriBookmarks* bookmarks, KatzeItem *item); |
875 | |
876 | static void |
877 | midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks); |
878 | |
879 | static void |
880 | -midori_bookmarks_add_item (KatzeItem* item, |
881 | - MidoriBookmarks* bookmarks); |
882 | +midori_bookmarks_idle_remove_item (MidoriBookmarks* bookmarks, KatzeItem *item); |
883 | + |
884 | +static gboolean |
885 | +midori_bookmarks_idle_func (gpointer data); |
886 | |
887 | static void |
888 | midori_bookmarks_class_init (MidoriBookmarksClass* class) |
889 | @@ -133,13 +307,13 @@ |
890 | flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; |
891 | |
892 | g_object_class_install_property (gobject_class, |
893 | - PROP_APP, |
894 | - g_param_spec_object ( |
895 | - "app", |
896 | - "App", |
897 | - "The app", |
898 | - MIDORI_TYPE_APP, |
899 | - flags)); |
900 | + PROP_APP, |
901 | + g_param_spec_object ( |
902 | + "app", |
903 | + "App", |
904 | + "The app", |
905 | + MIDORI_TYPE_APP, |
906 | + flags)); |
907 | } |
908 | |
909 | static const gchar* |
910 | @@ -168,7 +342,7 @@ |
911 | gchar* parent_id; |
912 | |
913 | parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid); |
914 | - if (!(root_array = midori_bookmarks_db_query_recursive (array, "*", "parentid = %q", parent_id, FALSE))) |
915 | + if (!(root_array = midori_bookmarks_db_query_recursive (array, "*", "parentid = %q", parent_id, "pos_panel DESC,", FALSE))) |
916 | { |
917 | g_free (parent_id); |
918 | return; |
919 | @@ -180,7 +354,7 @@ |
920 | subarray = katze_array_new (KATZE_TYPE_ARRAY); |
921 | katze_item_set_name (KATZE_ITEM (subarray), katze_item_get_name (item)); |
922 | midori_bookmarks_export_array_db (db, subarray, |
923 | - katze_item_get_meta_integer (item, "parentid")); |
924 | + katze_item_get_meta_integer (item, "parentid")); |
925 | katze_array_add_item (array, subarray); |
926 | } |
927 | else |
928 | @@ -201,20 +375,20 @@ |
929 | |
930 | if (keyword && *keyword) |
931 | array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db, |
932 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword, FALSE); |
933 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword, NULL, FALSE); |
934 | else |
935 | { |
936 | if (parentid > 0) |
937 | { |
938 | gchar* parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid); |
939 | array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db, |
940 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id, FALSE); |
941 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id, "pos_panel DESC, ", FALSE); |
942 | |
943 | g_free (parent_id); |
944 | } |
945 | else |
946 | array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db, |
947 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL, FALSE); |
948 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL, "pos_panel DESC, ", FALSE); |
949 | } |
950 | return array ? array : katze_array_new (KATZE_TYPE_ITEM); |
951 | } |
952 | @@ -231,24 +405,52 @@ |
953 | KatzeItem* item; |
954 | GtkTreeIter child; |
955 | |
956 | + g_signal_handlers_block_by_func (model, |
957 | + midori_bookmarks_row_changed_cb, |
958 | + bookmarks); |
959 | + |
960 | array = midori_bookmarks_read_from_db (bookmarks, parentid, keyword); |
961 | katze_bookmark_populate_tree_view (array, model, parent); |
962 | + |
963 | + g_signal_handlers_unblock_by_func (model, |
964 | + midori_bookmarks_row_changed_cb, |
965 | + bookmarks); |
966 | + |
967 | /* Remove invisible dummy row */ |
968 | last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent); |
969 | if (!last) |
970 | return; |
971 | + |
972 | + g_signal_handlers_block_by_func (model, |
973 | + midori_bookmarks_row_deleted_cb, |
974 | + bookmarks); |
975 | + |
976 | gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model), &child, parent, last - 1); |
977 | gtk_tree_model_get (GTK_TREE_MODEL (model), &child, 0, &item, -1); |
978 | if (KATZE_ITEM_IS_SEPARATOR (item)) |
979 | gtk_tree_store_remove (model, &child); |
980 | else |
981 | g_object_unref (item); |
982 | + |
983 | + g_signal_handlers_unblock_by_func (model, |
984 | + midori_bookmarks_row_deleted_cb, |
985 | + bookmarks); |
986 | + |
987 | } |
988 | |
989 | +static void |
990 | +midori_bookmarks_add_item (KatzeItem* item, |
991 | + MidoriBookmarks* bookmarks); |
992 | + |
993 | +static void |
994 | +add_parent_to_reorder (GtkTreeModel* model, |
995 | + GtkTreePath* path, |
996 | + MidoriBookmarks* bookmarks); |
997 | + |
998 | static gboolean |
999 | midori_bookmarks_reach_item_recurse (GtkTreeModel* model, |
1000 | - GtkTreeIter* iter, |
1001 | - gint64 id) |
1002 | + GtkTreeIter* iter, |
1003 | + gint64 id) |
1004 | { |
1005 | do |
1006 | { |
1007 | @@ -258,7 +460,7 @@ |
1008 | |
1009 | gtk_tree_model_get (model, iter, 0, &item, -1); |
1010 | |
1011 | - if (!KATZE_ITEM_IS_SEPARATOR(item)) |
1012 | + if (item) |
1013 | { |
1014 | itemid = katze_item_get_meta_integer (item, "id"); |
1015 | g_object_unref (item); |
1016 | @@ -267,13 +469,11 @@ |
1017 | if (id == itemid) |
1018 | return TRUE; |
1019 | |
1020 | - if (gtk_tree_model_iter_children (model, &child, iter)) |
1021 | + if (gtk_tree_model_iter_children (model, &child, iter) |
1022 | + && midori_bookmarks_reach_item_recurse (model, &child, id)) |
1023 | { |
1024 | - if (midori_bookmarks_reach_item_recurse (model, &child, id)) |
1025 | - { |
1026 | - *iter = child; |
1027 | - return TRUE; |
1028 | - } |
1029 | + *iter = child; |
1030 | + return TRUE; |
1031 | } |
1032 | } |
1033 | while (gtk_tree_model_iter_next(model, iter)); |
1034 | @@ -283,8 +483,8 @@ |
1035 | |
1036 | static gboolean |
1037 | midori_bookmarks_reach_item (GtkTreeModel* model, |
1038 | - GtkTreeIter* iter, |
1039 | - gint64 id) |
1040 | + GtkTreeIter* iter, |
1041 | + gint64 id) |
1042 | { |
1043 | if (!gtk_tree_model_get_iter_first(model, iter)) |
1044 | return FALSE; |
1045 | @@ -293,38 +493,73 @@ |
1046 | } |
1047 | |
1048 | static void |
1049 | -midori_bookmarks_add_item_to_model(GtkTreeStore* model, |
1050 | - GtkTreeIter* parent, |
1051 | - KatzeItem* item) |
1052 | +midori_bookmarks_add_item_to_model(MidoriBookmarks* bookmarks, |
1053 | + GtkTreeModel* model, |
1054 | + GtkTreeIter* parent, |
1055 | + KatzeItem* item) |
1056 | { |
1057 | + GtkTreeStore* tree_store = GTK_TREE_STORE (model); |
1058 | + gint last; |
1059 | + GtkTreeIter child; |
1060 | + |
1061 | if (KATZE_ITEM_IS_BOOKMARK (item)) |
1062 | { |
1063 | + gint position = 0; |
1064 | + |
1065 | + /* skip the folders to be consistent with the db query order */ |
1066 | + if (gtk_tree_model_iter_children (model, &child, parent)) |
1067 | + while (gtk_tree_model_iter_has_child (model, &child)) |
1068 | + { |
1069 | + position++; |
1070 | + if (!gtk_tree_model_iter_next (model, &child)) |
1071 | + break; |
1072 | + } |
1073 | + |
1074 | gchar* tooltip = g_markup_escape_text (katze_item_get_uri (item), -1); |
1075 | |
1076 | - gtk_tree_store_insert_with_values (model, NULL, parent, |
1077 | - 0, |
1078 | + gtk_tree_store_insert_with_values (tree_store, NULL, parent, |
1079 | + position, |
1080 | 0, item, 1, tooltip, -1); |
1081 | g_free (tooltip); |
1082 | } |
1083 | - else |
1084 | + else if (KATZE_ITEM_IS_FOLDER (item)) |
1085 | { |
1086 | GtkTreeIter root_iter; |
1087 | |
1088 | - gtk_tree_store_insert_with_values (model, &root_iter, parent, |
1089 | + gtk_tree_store_insert_with_values (tree_store, &root_iter, parent, |
1090 | 0, 0, item, -1); |
1091 | |
1092 | /* That's an invisible dummy, so we always have an expander */ |
1093 | - gtk_tree_store_insert_with_values (model, NULL, &root_iter, |
1094 | - 0, |
1095 | - 0, NULL, -1); |
1096 | + gtk_tree_store_insert_with_values (tree_store, NULL, &root_iter, |
1097 | + 0, 0, NULL, -1); |
1098 | } |
1099 | + |
1100 | + /* Remove invisible dummy row */ |
1101 | + last = gtk_tree_model_iter_n_children (model, parent); |
1102 | + if (!last) |
1103 | + return; |
1104 | + |
1105 | + g_signal_handlers_block_by_func (model, |
1106 | + midori_bookmarks_row_deleted_cb, |
1107 | + bookmarks); |
1108 | + |
1109 | + gtk_tree_model_iter_nth_child (model, &child, parent, last - 1); |
1110 | + gtk_tree_model_get (model, &child, 0, &item, -1); |
1111 | + if (KATZE_ITEM_IS_SEPARATOR (item)) |
1112 | + gtk_tree_store_remove (tree_store, &child); |
1113 | + else |
1114 | + g_object_unref (item); |
1115 | + |
1116 | + g_signal_handlers_unblock_by_func (model, |
1117 | + midori_bookmarks_row_deleted_cb, |
1118 | + bookmarks); |
1119 | } |
1120 | |
1121 | static void |
1122 | midori_bookmarks_update_item_in_model(MidoriBookmarks* bookmarks, |
1123 | - GtkTreeStore* model, |
1124 | - GtkTreeIter* iter, |
1125 | - KatzeItem* item) |
1126 | + GtkTreeStore* model, |
1127 | + GtkTreeIter* iter, |
1128 | + KatzeItem* item) |
1129 | { |
1130 | g_signal_handlers_block_by_func (model, |
1131 | midori_bookmarks_row_changed_cb, |
1132 | @@ -350,18 +585,48 @@ |
1133 | bookmarks); |
1134 | } |
1135 | |
1136 | +static gboolean |
1137 | +midori_bookmarks_idle_pending (MidoriBookmarks* bookmarks) |
1138 | +{ |
1139 | + if (bookmarks->pending_inserts |
1140 | + || bookmarks->added_paths |
1141 | + || bookmarks->reordered_paths |
1142 | + || g_hash_table_size (bookmarks->updated_items)) |
1143 | + return TRUE; |
1144 | + return FALSE; |
1145 | +} |
1146 | + |
1147 | +/** |
1148 | + * midori_bookmarks_idle_start: |
1149 | + * @bookmarks: the bookmarks panel |
1150 | + * |
1151 | + * Internal function that checks whether idle processing is pending, |
1152 | + * if not, add a new one. |
1153 | + **/ |
1154 | +static void |
1155 | +midori_bookmarks_idle_start (MidoriBookmarks* bookmarks) |
1156 | +{ |
1157 | + if (midori_bookmarks_idle_pending (bookmarks)) |
1158 | + return; |
1159 | + |
1160 | + g_idle_add (midori_bookmarks_idle_func, bookmarks); |
1161 | +} |
1162 | + |
1163 | static void |
1164 | midori_bookmarks_add_item (KatzeItem* item, |
1165 | MidoriBookmarks* bookmarks); |
1166 | + |
1167 | static void |
1168 | midori_bookmarks_add_item_cb (KatzeArray* array, |
1169 | KatzeItem* item, |
1170 | MidoriBookmarks* bookmarks) |
1171 | { |
1172 | - midori_bookmarks_add_item (item, bookmarks); |
1173 | + midori_bookmarks_idle_start (bookmarks); |
1174 | + |
1175 | + g_object_ref (item); |
1176 | + bookmarks->pending_inserts = g_list_append (bookmarks->pending_inserts, item); |
1177 | } |
1178 | |
1179 | - |
1180 | static void |
1181 | midori_bookmarks_add_item (KatzeItem* item, |
1182 | MidoriBookmarks* bookmarks) |
1183 | @@ -370,18 +635,16 @@ |
1184 | GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
1185 | GtkTreeIter iter; |
1186 | |
1187 | - if (!parentid) |
1188 | - { |
1189 | - midori_bookmarks_add_item_to_model (GTK_TREE_STORE (model), NULL, item); |
1190 | - } |
1191 | + if (parentid == katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id")) |
1192 | + midori_bookmarks_add_item_to_model (bookmarks, model, NULL, item); |
1193 | else if (midori_bookmarks_reach_item (model, &iter, parentid)) |
1194 | { |
1195 | GtkTreePath* path = gtk_tree_model_get_path(model, &iter); |
1196 | + gint n_children = gtk_tree_model_iter_n_children (model, &iter); |
1197 | |
1198 | - if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path)) |
1199 | - { |
1200 | - midori_bookmarks_add_item_to_model (GTK_TREE_STORE (model), &iter, item); |
1201 | - } |
1202 | + if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path) |
1203 | + || !n_children) |
1204 | + midori_bookmarks_add_item_to_model (bookmarks, model, &iter, item); |
1205 | |
1206 | gtk_tree_path_free (path); |
1207 | } |
1208 | @@ -389,8 +652,8 @@ |
1209 | |
1210 | static void |
1211 | midori_bookmarks_update_item_cb (KatzeArray* array, |
1212 | - KatzeItem* item, |
1213 | - MidoriBookmarks* bookmarks) |
1214 | + KatzeItem* item, |
1215 | + MidoriBookmarks* bookmarks) |
1216 | { |
1217 | gint64 id = katze_item_get_meta_integer (item, "id"); |
1218 | gint64 parentid = katze_item_get_meta_integer (item, "parentid"); |
1219 | @@ -433,7 +696,7 @@ |
1220 | midori_bookmarks_add_item (item, bookmarks); |
1221 | } |
1222 | } |
1223 | - else if (parentid == 0) |
1224 | + else if (parentid == katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id")) |
1225 | { |
1226 | midori_bookmarks_update_item_in_model (bookmarks, GTK_TREE_STORE (model), &iter, item); |
1227 | } |
1228 | @@ -457,6 +720,10 @@ |
1229 | GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
1230 | GtkTreeIter iter; |
1231 | |
1232 | + g_assert (KATZE_IS_ITEM (item)); |
1233 | + |
1234 | + midori_bookmarks_idle_remove_item (bookmarks, item); |
1235 | + |
1236 | if (midori_bookmarks_reach_item (model, &iter, id)) |
1237 | { |
1238 | GtkTreeIter parent; |
1239 | @@ -486,12 +753,869 @@ |
1240 | midori_bookmarks_update_cb (KatzeArray* array, |
1241 | MidoriBookmarks* bookmarks) |
1242 | { |
1243 | +#if 1 |
1244 | + g_print ("midori_bookmarks_update_cb: ignored ********\n"); |
1245 | +#else |
1246 | GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
1247 | + |
1248 | gtk_tree_store_clear (GTK_TREE_STORE (model)); |
1249 | midori_bookmarks_read_from_db_to_model (bookmarks, |
1250 | GTK_TREE_STORE (model), NULL, 0, bookmarks->filter); |
1251 | -} |
1252 | - |
1253 | +#endif |
1254 | +} |
1255 | + |
1256 | +gboolean |
1257 | +midori_bookmarks_tree_set_row_drag_data (GtkSelectionData *selection_data, |
1258 | + GtkTreeModel *tree_model, |
1259 | + GList* rows) |
1260 | +{ |
1261 | + TreeRowData *trd; |
1262 | + gint len; |
1263 | + gint struct_size; |
1264 | + gint length; |
1265 | + gint i; |
1266 | + GString *data; |
1267 | + |
1268 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
1269 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE); |
1270 | + g_return_val_if_fail (rows != NULL, FALSE); |
1271 | + |
1272 | + data = g_string_new(""); |
1273 | + |
1274 | + length = g_list_length (rows); |
1275 | + for (i = 0; i < length; i++) |
1276 | + { |
1277 | + GtkTreePath *path = (GtkTreePath *)g_list_nth_data (rows, i); |
1278 | + gchar *path_str = gtk_tree_path_to_string (path); |
1279 | + |
1280 | + g_string_append (data, path_str); |
1281 | + if (i < length-1) |
1282 | + g_string_append_c (data, '\n'); |
1283 | + } |
1284 | + |
1285 | + len = data->len; |
1286 | + |
1287 | + /* the old allocate-end-of-struct-to-hold-string trick */ |
1288 | + struct_size = sizeof (TreeRowData) + len + 1 - |
1289 | + (sizeof (TreeRowData) - G_STRUCT_OFFSET (TreeRowData, path)); |
1290 | + |
1291 | + trd = g_malloc (struct_size); |
1292 | + |
1293 | + strcpy (trd->path, data->str); |
1294 | + |
1295 | + g_string_free (data, TRUE); |
1296 | + |
1297 | + trd->model = tree_model; |
1298 | + |
1299 | + gtk_selection_data_set (selection_data, |
1300 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET), |
1301 | + 8, /* bytes */ |
1302 | + (void*)trd, |
1303 | + struct_size); |
1304 | + |
1305 | + g_free (trd); |
1306 | + |
1307 | + return TRUE; |
1308 | +} |
1309 | + |
1310 | +static gboolean |
1311 | +midori_bookmarks_tree_store_drag_data_get (GtkTreeDragSource* drag_source, |
1312 | + GtkTreePath* source_path, |
1313 | + GtkSelectionData* selection_data) |
1314 | +{ |
1315 | + MidoriBookmarksTreeStore *tree_store; |
1316 | + gboolean status = FALSE; |
1317 | + |
1318 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
1319 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (drag_source), FALSE); |
1320 | + g_return_val_if_fail (source_path != NULL, FALSE); |
1321 | + |
1322 | + tree_store = MIDORI_BOOKMARKS_TREE_STORE(drag_source); |
1323 | + |
1324 | + if (tree_store->stock_got_rows) |
1325 | + { |
1326 | + g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free); |
1327 | + tree_store->stock_got_rows = NULL; |
1328 | + } |
1329 | + |
1330 | + if (gtk_selection_data_get_target (selection_data) == |
1331 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET)) |
1332 | + { |
1333 | + GtkTreeModel *model; |
1334 | + GList* rows; |
1335 | + if (katze_tree_view_get_selected_rows ( |
1336 | + tree_store->_view, &model, &rows)) |
1337 | + { |
1338 | + status = midori_bookmarks_tree_set_row_drag_data (selection_data, model, rows); |
1339 | + |
1340 | + tree_store->stock_got_rows = rows; |
1341 | + } |
1342 | + } |
1343 | + |
1344 | + return status; |
1345 | +} |
1346 | + |
1347 | +static void |
1348 | +update_path_list_for_insert (GList * rows, GtkTreePath* path) |
1349 | +{ |
1350 | + gint length = g_list_length (rows); |
1351 | + gint i; |
1352 | + |
1353 | + for (i = 0; i < length; i++ ) |
1354 | + { |
1355 | + GtkTreePath *src_path_r = (GtkTreePath *)g_list_nth_data (rows, i); |
1356 | + gint la = gtk_tree_path_get_depth (path); |
1357 | + gint lb = gtk_tree_path_get_depth (src_path_r); |
1358 | + gint *ia = gtk_tree_path_get_indices (path); |
1359 | + gint *ib = gtk_tree_path_get_indices (src_path_r); |
1360 | + gint j; |
1361 | + |
1362 | + if (la > lb) /* insert was donne in a deeper branch than source */ |
1363 | + continue; |
1364 | + |
1365 | + if (ia[la-1] > ib[la-1]) /* insert was donne after source */ |
1366 | + continue; |
1367 | + |
1368 | + for (j = 0; j < la; j++) |
1369 | + { |
1370 | + if (ia[j] != ib[j]) break; |
1371 | + } |
1372 | + |
1373 | + if (j < la-1) /* insert and source are not in the same branch */ |
1374 | + continue; |
1375 | + |
1376 | + /* source at depth level of insert must be incremented due to the insert */ |
1377 | + ib[la-1] += 1; |
1378 | + } |
1379 | +} |
1380 | + |
1381 | +static gint |
1382 | +midori_tree_path_compare (const GtkTreePath *a, |
1383 | + const GtkTreePath *b) |
1384 | +{ |
1385 | + if (!gtk_tree_path_get_depth ((GtkTreePath *)a)) |
1386 | + { |
1387 | + if (!gtk_tree_path_get_depth ((GtkTreePath *)b)) |
1388 | + return 0; |
1389 | + |
1390 | + return -1; |
1391 | + } |
1392 | + |
1393 | + if (!gtk_tree_path_get_depth ((GtkTreePath *)b)) |
1394 | + return 1; |
1395 | + |
1396 | + return gtk_tree_path_compare (a, b); |
1397 | +} |
1398 | + |
1399 | +static GList* |
1400 | +update_path_list_for_delete (GList* rows, GtkTreePath* removed_path) |
1401 | +{ |
1402 | + GList* new_rows = rows; |
1403 | + |
1404 | + while (rows) |
1405 | + { |
1406 | + GtkTreePath *source_path = (GtkTreePath *)rows->data; |
1407 | + gint la = gtk_tree_path_get_depth (removed_path); |
1408 | + gint lb = gtk_tree_path_get_depth (source_path); |
1409 | + gint *ia = gtk_tree_path_get_indices (removed_path); |
1410 | + gint *ib = gtk_tree_path_get_indices (source_path); |
1411 | + gint cmp = midori_tree_path_compare (removed_path, source_path); |
1412 | + gint j; |
1413 | + |
1414 | + if (cmp == 1) /* removal was done after source => kip source as it is */ |
1415 | + goto keep_source; |
1416 | + |
1417 | + if (cmp == 0) /* source is removed => remove source */ |
1418 | + goto remove_source; |
1419 | + |
1420 | + /* if removal is an ancestor of the source => remove source */ |
1421 | + if (gtk_tree_path_is_ancestor (removed_path, source_path)) |
1422 | + goto remove_source; |
1423 | + |
1424 | + if (la > lb) /* removal was donne in a deeper branch than source */ |
1425 | + goto keep_source; |
1426 | + |
1427 | + for (j = 0; j < la; j++) |
1428 | + { |
1429 | + if (ia[j] != ib[j]) break; |
1430 | + } |
1431 | + |
1432 | + if (j < la-1) /* removal and source are not in the same branch */ |
1433 | + goto keep_source; |
1434 | + |
1435 | + /* source at depth level of removal must be decremented due to the removal */ |
1436 | + ib[la-1] -= 1; |
1437 | + |
1438 | + if (ib[la-1] >= 0) |
1439 | + goto keep_source; |
1440 | + |
1441 | + remove_source: |
1442 | + /* remove source entry */ |
1443 | + gtk_tree_path_free (source_path); |
1444 | + { |
1445 | + GList *next_rows = g_list_next (rows); |
1446 | + new_rows = g_list_delete_link (new_rows, rows); |
1447 | + rows = next_rows; |
1448 | + } |
1449 | + continue; |
1450 | + |
1451 | + keep_source: |
1452 | + rows = g_list_next (rows); |
1453 | + } |
1454 | + |
1455 | + return new_rows; |
1456 | +} |
1457 | + |
1458 | +static gboolean |
1459 | +midori_bookmarks_tree_store_drag_data_delete (GtkTreeDragSource* drag_source, |
1460 | + GtkTreePath* source_path) |
1461 | +{ |
1462 | + gboolean status = TRUE; |
1463 | + MidoriBookmarksTreeStore *tree_store = MIDORI_BOOKMARKS_TREE_STORE(drag_source); |
1464 | + GtkTreeModel* model = GTK_TREE_MODEL(drag_source); |
1465 | + |
1466 | + if (!tree_store->stock_got_rows) |
1467 | + return TRUE; |
1468 | + |
1469 | + while (tree_store->stock_got_rows) |
1470 | + { |
1471 | + GtkTreePath *prev = (GtkTreePath *)tree_store->stock_got_rows->data; |
1472 | + GtkTreeIter iter; |
1473 | + |
1474 | + tree_store->stock_got_rows = g_list_delete_link (tree_store->stock_got_rows, |
1475 | + tree_store->stock_got_rows); |
1476 | + |
1477 | + if (gtk_tree_model_get_iter (model, &iter, prev)) |
1478 | + { |
1479 | + /* remove item updating source paths */ |
1480 | + gtk_tree_store_remove (GTK_TREE_STORE (drag_source), &iter); |
1481 | + |
1482 | + tree_store->stock_got_rows = update_path_list_for_delete (tree_store->stock_got_rows, prev); |
1483 | + } |
1484 | + else |
1485 | + status = FALSE; |
1486 | + |
1487 | + gtk_tree_path_free (prev); |
1488 | + } |
1489 | + |
1490 | + return status; |
1491 | +} |
1492 | + |
1493 | +static gboolean |
1494 | +midori_bookmarks_tree_store_get_rows_drag_data (GtkSelectionData *selection_data, |
1495 | + GtkTreeModel **tree_model, |
1496 | + GList **rows) |
1497 | +{ |
1498 | + TreeRowData *trd; |
1499 | + |
1500 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
1501 | + |
1502 | + if (tree_model) |
1503 | + *tree_model = NULL; |
1504 | + |
1505 | + if (rows) |
1506 | + *rows = NULL; |
1507 | + |
1508 | + if (gtk_selection_data_get_target (selection_data) != |
1509 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET)) |
1510 | + return FALSE; |
1511 | + |
1512 | + if (gtk_selection_data_get_length (selection_data) < 0) |
1513 | + return FALSE; |
1514 | + |
1515 | + trd = (void*) gtk_selection_data_get_data (selection_data); |
1516 | + |
1517 | + if (tree_model) |
1518 | + *tree_model = trd->model; |
1519 | + |
1520 | + if (rows) |
1521 | + { |
1522 | + GList *list = NULL; |
1523 | + gchar *trd_path = g_strdup (trd->path); |
1524 | + gchar *path_str; |
1525 | + |
1526 | + path_str = strtok(trd_path, "\n"); |
1527 | + while (path_str && *path_str) |
1528 | + { |
1529 | + list = g_list_append (list, gtk_tree_path_new_from_string (path_str)); |
1530 | + path_str = strtok (NULL, "\n"); |
1531 | + } |
1532 | + |
1533 | + *rows = list; |
1534 | + g_free (trd_path); |
1535 | + } |
1536 | + |
1537 | + return TRUE; |
1538 | +} |
1539 | + |
1540 | +#if !GTK_CHECK_VERSION (3,0,0) |
1541 | +gboolean |
1542 | +gtk_tree_model_iter_previous (GtkTreeModel *tree_model, |
1543 | + GtkTreeIter *iter) |
1544 | +{ |
1545 | + GtkTreePath* path = gtk_tree_model_get_path (tree_model, iter); |
1546 | + gboolean result = gtk_tree_path_prev (path); |
1547 | + |
1548 | + if (result) |
1549 | + result = gtk_tree_model_get_iter (tree_model, iter, path); |
1550 | + else |
1551 | + { |
1552 | + GtkTreeIter invalid = {0}; |
1553 | + *iter = invalid; |
1554 | + } |
1555 | + |
1556 | + gtk_tree_path_free (path); |
1557 | + return result; |
1558 | +} |
1559 | +#endif |
1560 | + |
1561 | +static gboolean |
1562 | +midori_bookmarks_tree_store_row_drop_possible (GtkTreeDragDest* drag_dest, |
1563 | + GtkTreePath* dest_path, |
1564 | + GtkSelectionData* selection_data) |
1565 | +{ |
1566 | + GtkTreeModel* dest_model = GTK_TREE_MODEL(drag_dest); |
1567 | + GtkTreePath *parent; |
1568 | + GtkTreeIter dest_parent; |
1569 | + GtkTreeIter *dest_parent_p = NULL; |
1570 | + gboolean row_drop_possible = TRUE; |
1571 | + GtkTreeViewDropPosition drop_position; |
1572 | + |
1573 | + gtk_tree_view_get_drag_dest_row (MIDORI_BOOKMARKS_TREE_STORE (dest_model)->_view, |
1574 | + NULL, &drop_position); |
1575 | + |
1576 | + parent = gtk_tree_path_copy (dest_path); |
1577 | + if ((gtk_tree_path_get_depth (parent) > 1) |
1578 | + && gtk_tree_path_up (parent) |
1579 | + && gtk_tree_model_get_iter (dest_model, &dest_parent, parent)) |
1580 | + dest_parent_p = &dest_parent; |
1581 | + |
1582 | + gtk_tree_path_free (parent); |
1583 | + |
1584 | + if (dest_parent_p) |
1585 | + { |
1586 | + KatzeItem* item; |
1587 | + |
1588 | + gtk_tree_model_get (dest_model, dest_parent_p, 0, &item, -1); |
1589 | + |
1590 | + if (!KATZE_ITEM_IS_FOLDER (item)) |
1591 | + { |
1592 | +#ifdef DEBUG_DROP |
1593 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
1594 | + |
1595 | + g_print ("%s: can only drop into folders\n", dest_path_str); |
1596 | + g_free (dest_path_str); |
1597 | +#endif /* DEBUG_DROP */ |
1598 | + row_drop_possible = FALSE; |
1599 | + } |
1600 | + |
1601 | + if (item) |
1602 | + g_object_unref (item); |
1603 | + } |
1604 | + |
1605 | + if (row_drop_possible |
1606 | + && (gtk_selection_data_get_target (selection_data) == |
1607 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET))) |
1608 | + { |
1609 | + GtkTreeModel *src_model; |
1610 | + GList* rows; |
1611 | + |
1612 | + if (midori_bookmarks_tree_store_get_rows_drag_data (selection_data, |
1613 | + &src_model, &rows)) |
1614 | + { |
1615 | + GtkTreeIter dest_iter; |
1616 | + GList* src_row; |
1617 | + gboolean dest_is_folder = FALSE; |
1618 | + /* gboolean dest_is_bookmark = FALSE; */ |
1619 | + gboolean src_has_folders = FALSE; |
1620 | + gboolean src_has_bookmarks = FALSE; |
1621 | + |
1622 | + if (gtk_tree_model_get_iter (dest_model, &dest_iter, dest_path)) |
1623 | + { |
1624 | + if (gtk_tree_model_iter_has_child (dest_model, &dest_iter)) |
1625 | + dest_is_folder = TRUE; |
1626 | +/* |
1627 | + else |
1628 | + { |
1629 | + KatzeItem* item; |
1630 | + gtk_tree_model_get (dest_model, &dest_iter, 0, &item, -1); |
1631 | + if (item) |
1632 | + { |
1633 | + dest_is_bookmark = TRUE; |
1634 | + g_object_unref (item); |
1635 | + } |
1636 | + } |
1637 | +*/ |
1638 | + } |
1639 | + |
1640 | + for (src_row = rows ; src_row ; src_row = g_list_next (src_row)) |
1641 | + { |
1642 | + GtkTreePath* src_path = (GtkTreePath*)src_row->data; |
1643 | + GtkTreeIter src_iter; |
1644 | + KatzeItem* item; |
1645 | + |
1646 | + if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path)) |
1647 | + continue; |
1648 | + |
1649 | + gtk_tree_model_get (src_model, &src_iter, 0, &item, -1); |
1650 | + if (item) |
1651 | + { |
1652 | + if (!src_has_folders && KATZE_ITEM_IS_FOLDER (item)) |
1653 | + src_has_folders = TRUE; |
1654 | + else if (!src_has_bookmarks && KATZE_ITEM_IS_BOOKMARK (item)) |
1655 | + src_has_bookmarks = TRUE; |
1656 | + |
1657 | + g_object_unref (item); |
1658 | + } |
1659 | + if (src_has_bookmarks && src_has_folders) |
1660 | + break; |
1661 | + } |
1662 | + |
1663 | + if (src_has_bookmarks) |
1664 | + { |
1665 | + switch (drop_position) |
1666 | + { |
1667 | + case GTK_TREE_VIEW_DROP_BEFORE: |
1668 | + case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: |
1669 | + if (dest_is_folder) |
1670 | + { |
1671 | +#ifdef DEBUG_DROP |
1672 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
1673 | + |
1674 | + g_print ("%s: cannot drop bookmarks in folders group\n", dest_path_str); |
1675 | + g_free (dest_path_str); |
1676 | +#endif /* DEBUG_DROP */ |
1677 | + row_drop_possible = FALSE; |
1678 | + goto done; |
1679 | + } |
1680 | + break; |
1681 | + case GTK_TREE_VIEW_DROP_AFTER: |
1682 | + case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: |
1683 | + if (dest_is_folder) |
1684 | + { |
1685 | + gboolean next_dest_is_folder = FALSE; |
1686 | + |
1687 | + if (gtk_tree_model_iter_next (dest_model, &dest_iter)) |
1688 | + if (gtk_tree_model_iter_has_child (dest_model, &dest_iter)) |
1689 | + next_dest_is_folder = TRUE; |
1690 | + |
1691 | + if (next_dest_is_folder) |
1692 | + { |
1693 | +#ifdef DEBUG_DROP |
1694 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
1695 | + |
1696 | + g_print ("%s: cannot drop bookmarks in folders group\n", dest_path_str); |
1697 | + g_free (dest_path_str); |
1698 | +#endif /* DEBUG_DROP */ |
1699 | + row_drop_possible = FALSE; |
1700 | + goto done; |
1701 | + } |
1702 | + } |
1703 | + break; |
1704 | + default: |
1705 | + break; |
1706 | + } |
1707 | + } |
1708 | + else if (src_has_folders) |
1709 | + { |
1710 | + gboolean prev_dest_is_folder = TRUE; |
1711 | + |
1712 | + if (gtk_tree_model_iter_previous (dest_model, &dest_iter)) |
1713 | + if (!gtk_tree_model_iter_has_child (dest_model, &dest_iter)) |
1714 | + prev_dest_is_folder = FALSE; |
1715 | + |
1716 | + if (!prev_dest_is_folder) |
1717 | + { |
1718 | +#ifdef DEBUG_DROP |
1719 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
1720 | + |
1721 | + g_print ("%s: cannot drop folders in bookmarks group\n", dest_path_str); |
1722 | + g_free (dest_path_str); |
1723 | +#endif /* DEBUG_DROP */ |
1724 | + row_drop_possible = FALSE; |
1725 | + goto done; |
1726 | + } |
1727 | + } |
1728 | + |
1729 | + if (src_model == dest_model) |
1730 | + { |
1731 | + for (src_row = rows ; src_row ; src_row = g_list_next (src_row)) |
1732 | + { |
1733 | + GtkTreePath* src_path = (GtkTreePath*)src_row->data; |
1734 | + |
1735 | + /* Can't drop into ourself. */ |
1736 | + if (gtk_tree_path_is_ancestor (src_path, dest_path)) |
1737 | + { |
1738 | +#ifdef DEBUG_DROP |
1739 | + g_print ("cannot drop into source folders\n"); |
1740 | +#endif /* DEBUG_DROP */ |
1741 | + row_drop_possible = FALSE; |
1742 | + goto done; |
1743 | + } |
1744 | + update_path_list_for_insert (rows, dest_path); |
1745 | + } |
1746 | + } |
1747 | + done: |
1748 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
1749 | + } |
1750 | + else |
1751 | + row_drop_possible = FALSE; |
1752 | + } |
1753 | + else |
1754 | + row_drop_possible = FALSE; |
1755 | + |
1756 | +#ifdef DEBUG_DROP |
1757 | + if (row_drop_possible) |
1758 | + { |
1759 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
1760 | + gchar *drop_position_str = "unknown"; |
1761 | + switch (drop_position) |
1762 | + { |
1763 | + case GTK_TREE_VIEW_DROP_BEFORE: |
1764 | + drop_position_str = "before"; |
1765 | + break; |
1766 | + case GTK_TREE_VIEW_DROP_AFTER: |
1767 | + drop_position_str = "after"; |
1768 | + break; |
1769 | + case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: |
1770 | + drop_position_str = "into or before"; |
1771 | + break; |
1772 | + case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: |
1773 | + drop_position_str = "into or after"; |
1774 | + break; |
1775 | + } |
1776 | + |
1777 | + g_print ("%s: row drop possible (%s)\n", dest_path_str, drop_position_str); |
1778 | + g_free (dest_path_str); |
1779 | + } |
1780 | +#endif /* DEBUG_DROP */ |
1781 | + |
1782 | + return row_drop_possible; |
1783 | +} |
1784 | + |
1785 | +static void |
1786 | +copy_node_data (GtkTreeStore *src_store, |
1787 | + GtkTreeIter *src_iter, |
1788 | + GtkTreeStore *dest_store, |
1789 | + GtkTreeIter *dest_iter) |
1790 | +{ |
1791 | + gint i; |
1792 | + gint n_columns; |
1793 | + GtkTreeModel* src_model = GTK_TREE_MODEL (src_store); |
1794 | + |
1795 | + n_columns = gtk_tree_model_get_n_columns (src_model); |
1796 | + |
1797 | + for (i = 0; i < n_columns; i++) |
1798 | + { |
1799 | + void *item; |
1800 | + |
1801 | + gtk_tree_model_get (src_model, src_iter, i, &item, -1); |
1802 | + gtk_tree_store_set (dest_store, dest_iter, i, item, -1); |
1803 | + } |
1804 | +} |
1805 | + |
1806 | +static void |
1807 | +recursive_node_copy (GtkTreeStore *src_store, |
1808 | + GtkTreeIter *src_iter, |
1809 | + GtkTreeStore *dest_store, |
1810 | + GtkTreeIter *dest_iter) |
1811 | +{ |
1812 | + GtkTreeIter child; |
1813 | + GtkTreeModel *src_model = GTK_TREE_MODEL (src_store); |
1814 | + |
1815 | + copy_node_data (src_store, src_iter, dest_store, dest_iter); |
1816 | + |
1817 | + if (gtk_tree_model_iter_children (src_model, &child, src_iter)) |
1818 | + { |
1819 | + /* Need to create children and recurse. Note our |
1820 | + * dependence on persistent iterators here. |
1821 | + */ |
1822 | + do |
1823 | + { |
1824 | + GtkTreeIter copy; |
1825 | + |
1826 | + /* Gee, a really slow algorithm... ;-) FIXME */ |
1827 | + gtk_tree_store_append (dest_store, |
1828 | + ©, |
1829 | + dest_iter); |
1830 | + |
1831 | + recursive_node_copy (src_store, &child, dest_store, ©); |
1832 | + } |
1833 | + while (gtk_tree_model_iter_next (src_model, &child)); |
1834 | + } |
1835 | +} |
1836 | + |
1837 | +static gboolean |
1838 | +midori_bookmarks_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, |
1839 | + GtkTreePath *dest_path, |
1840 | + GtkSelectionData *selection_data) |
1841 | +{ |
1842 | + gboolean status = TRUE; |
1843 | + |
1844 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
1845 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (drag_dest), FALSE); |
1846 | + g_return_val_if_fail (dest_path != NULL, FALSE); |
1847 | + |
1848 | + if (gtk_selection_data_get_target (selection_data) == |
1849 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET)) |
1850 | + { |
1851 | + GtkTreeStore *dest_store = GTK_TREE_STORE (drag_dest); |
1852 | + GtkTreeModel *dest_model = GTK_TREE_MODEL (drag_dest); |
1853 | + GtkTreeModel *src_model; |
1854 | + GList* rows; |
1855 | + |
1856 | + if (midori_bookmarks_tree_store_get_rows_drag_data (selection_data, |
1857 | + &src_model, &rows)) |
1858 | + { |
1859 | + GtkTreeStore *src_store = GTK_TREE_STORE (src_model); |
1860 | + GtkTreePath *prev = gtk_tree_path_copy (dest_path); |
1861 | + |
1862 | + gint count = 0; |
1863 | + gint length = g_list_length (rows); |
1864 | + gint i; |
1865 | + |
1866 | + for (i = 0; i < length; i++) |
1867 | + { |
1868 | + GtkTreeIter dest_iter; |
1869 | + GtkTreeIter src_iter; |
1870 | + GtkTreePath *src_path = (GtkTreePath *)g_list_nth_data (rows, i); |
1871 | + |
1872 | + if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path)) |
1873 | + continue; |
1874 | + |
1875 | + /* Get the path to insert _after_ (dest is the path to insert _before_) */ |
1876 | + if (i == 0) |
1877 | + { |
1878 | + if (!gtk_tree_path_prev (prev)) |
1879 | + { /* Get the parent, NULL if parent is the root */ |
1880 | + GtkTreeIter dest_parent; |
1881 | + GtkTreePath *parent = gtk_tree_path_copy (dest_path); |
1882 | + GtkTreeIter *dest_parent_p = NULL; |
1883 | + |
1884 | + if (gtk_tree_path_up (parent) && |
1885 | + gtk_tree_path_get_depth (parent) > 0) |
1886 | + { |
1887 | + gtk_tree_model_get_iter (dest_model, |
1888 | + &dest_parent, parent); |
1889 | + dest_parent_p = &dest_parent; |
1890 | + } |
1891 | + gtk_tree_path_free (parent); |
1892 | + |
1893 | + gtk_tree_store_prepend (dest_store, &dest_iter, dest_parent_p); |
1894 | + } |
1895 | + else if (gtk_tree_model_get_iter (dest_model, &dest_iter, prev)) |
1896 | + { |
1897 | + GtkTreeIter tmp_iter = dest_iter; |
1898 | + |
1899 | + gtk_tree_store_insert_after (dest_store, &dest_iter, NULL, |
1900 | + &tmp_iter); |
1901 | + } |
1902 | + } |
1903 | + else if (gtk_tree_model_get_iter (dest_model, &dest_iter, prev)) |
1904 | + { |
1905 | + GtkTreeIter tmp_iter = dest_iter; |
1906 | + |
1907 | + gtk_tree_store_insert_after (dest_store, &dest_iter, NULL, |
1908 | + &tmp_iter); |
1909 | + } |
1910 | + |
1911 | + gtk_tree_path_free (prev); |
1912 | + |
1913 | + recursive_node_copy (src_store, &src_iter, dest_store, &dest_iter); |
1914 | + count++; |
1915 | + |
1916 | + prev = gtk_tree_model_get_path (dest_model, &dest_iter); |
1917 | + |
1918 | + if (src_store != dest_store) |
1919 | + continue; |
1920 | + |
1921 | + update_path_list_for_insert (rows, prev); |
1922 | + } |
1923 | + |
1924 | + gtk_tree_path_free (prev); |
1925 | + |
1926 | + g_assert (count == length); |
1927 | + |
1928 | + if (src_store == dest_store) |
1929 | + { |
1930 | + MidoriBookmarksTreeStore *tree_store = MIDORI_BOOKMARKS_TREE_STORE(src_store); |
1931 | + |
1932 | + g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free); |
1933 | + tree_store->stock_got_rows = rows; |
1934 | + } |
1935 | + else |
1936 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
1937 | + } |
1938 | + } |
1939 | + |
1940 | + return status; |
1941 | +} |
1942 | + |
1943 | +static void |
1944 | +midori_bookmarks_set_item_positon (GtkTreeModel* model, |
1945 | + GtkTreeIter* iter, |
1946 | + gint64 parentid, |
1947 | + MidoriBookmarks* bookmarks) |
1948 | +{ |
1949 | + KatzeItem* item; |
1950 | + gint position = 0; |
1951 | + GtkTreeIter next = *iter; |
1952 | + |
1953 | + do { |
1954 | + gboolean update = FALSE; |
1955 | + gtk_tree_model_get (model, &next, 0, &item, -1); |
1956 | + |
1957 | + if (!KATZE_IS_ITEM (item)) |
1958 | + continue; |
1959 | + |
1960 | + if (position != katze_item_get_meta_integer (item, "pos_panel")) |
1961 | + { |
1962 | + katze_item_set_meta_integer (item, "pos_panel", position); |
1963 | + update = TRUE; |
1964 | + } |
1965 | + if (parentid != katze_item_get_meta_integer (item, "parentid")) |
1966 | + { |
1967 | + katze_item_set_meta_integer (item, "parentid", parentid); |
1968 | + update = TRUE; |
1969 | + } |
1970 | + |
1971 | + if (update) |
1972 | + midori_bookmarks_update_item (bookmarks, item); |
1973 | + |
1974 | + position++; |
1975 | + |
1976 | + g_object_unref (item); |
1977 | + } |
1978 | + while (gtk_tree_model_iter_next (model, &next)); |
1979 | +} |
1980 | + |
1981 | +static void |
1982 | +assert_reorder_are_folders (GtkTreeModel* model, |
1983 | + MidoriBookmarks* bookmarks) |
1984 | +{ |
1985 | + GList* iter; |
1986 | + for (iter = bookmarks->reordered_paths; iter ; iter = g_list_next (iter)) |
1987 | + { |
1988 | + GtkTreePath* path = (GtkTreePath*)iter->data; |
1989 | + GtkTreeIter tree_iter; |
1990 | + |
1991 | + if (!gtk_tree_path_get_depth (path)) |
1992 | + continue; |
1993 | + |
1994 | + if (gtk_tree_model_get_iter (model, &tree_iter, path)) |
1995 | + { |
1996 | + KatzeItem *item; |
1997 | + |
1998 | + gtk_tree_model_get (model, &tree_iter, 0, &item, -1); |
1999 | + |
2000 | + g_assert (KATZE_ITEM_IS_FOLDER (item)); |
2001 | + } |
2002 | + } |
2003 | +} |
2004 | + |
2005 | +static void |
2006 | +add_parent_to_reorder (GtkTreeModel* model, |
2007 | + GtkTreePath* path, |
2008 | + MidoriBookmarks* bookmarks) |
2009 | +{ |
2010 | + GtkTreePath* path_copy = gtk_tree_path_copy (path); |
2011 | + GList* found; |
2012 | + |
2013 | + midori_bookmarks_idle_start (bookmarks); |
2014 | + |
2015 | + if (gtk_tree_path_get_depth (path_copy) > 1 |
2016 | + && gtk_tree_path_up (path_copy)) |
2017 | + { |
2018 | + GtkTreeIter iter; |
2019 | + if (gtk_tree_model_get_iter (model, &iter, path_copy)) |
2020 | + { |
2021 | + KatzeItem* item; |
2022 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
2023 | + if (item) |
2024 | + { |
2025 | + g_assert (KATZE_ITEM_IS_FOLDER (item)); |
2026 | + g_object_unref (item); |
2027 | + } |
2028 | + else |
2029 | + g_assert_not_reached (); |
2030 | + } |
2031 | + else |
2032 | + g_assert_not_reached (); |
2033 | + } |
2034 | + else |
2035 | + { |
2036 | + gtk_tree_path_free (path_copy); |
2037 | + path_copy = gtk_tree_path_new (); |
2038 | + } |
2039 | + |
2040 | + if ((found = g_list_find_custom (bookmarks->reordered_paths, |
2041 | + path_copy, (GCompareFunc)midori_tree_path_compare)) != NULL) |
2042 | + { |
2043 | + gtk_tree_path_free (path_copy); |
2044 | + return; |
2045 | + } |
2046 | + |
2047 | + bookmarks->reordered_paths = g_list_append (bookmarks->reordered_paths, path_copy); |
2048 | +} |
2049 | + |
2050 | +static void |
2051 | +midori_bookmarks_row_inserted_cb (GtkTreeModel* model, |
2052 | + GtkTreePath* path, |
2053 | + GtkTreeIter* iter, |
2054 | + MidoriBookmarks* bookmarks) |
2055 | +{ |
2056 | + midori_bookmarks_idle_start (bookmarks); |
2057 | + |
2058 | + update_path_list_for_insert (bookmarks->added_paths, path); |
2059 | + update_path_list_for_insert (bookmarks->reordered_paths, path); |
2060 | + assert_reorder_are_folders (model, bookmarks); |
2061 | + |
2062 | + if (g_list_find_custom (bookmarks->added_paths, |
2063 | + path, (GCompareFunc)midori_tree_path_compare)) |
2064 | + return; |
2065 | + |
2066 | + bookmarks->added_paths = g_list_append (bookmarks->added_paths, gtk_tree_path_copy (path)); |
2067 | +} |
2068 | + |
2069 | +#ifdef DEBUG_LIST |
2070 | +static void |
2071 | +print_path_list (GList* iter) |
2072 | +{ |
2073 | + for ( ; iter ; iter = g_list_next (iter)) |
2074 | + { |
2075 | + gchar* str = gtk_tree_path_to_string ((GtkTreePath*)iter->data); |
2076 | + g_print ("%s ", str); |
2077 | + g_free (str); |
2078 | + } |
2079 | + g_print ("\n"); |
2080 | +} |
2081 | +#endif /* DEBUG_LIST */ |
2082 | + |
2083 | +static void |
2084 | +midori_bookmarks_row_deleted_cb (GtkTreeModel* model, |
2085 | + GtkTreePath* path, |
2086 | + MidoriBookmarks* bookmarks) |
2087 | +{ |
2088 | +#ifdef DEBUG_LIST |
2089 | + gchar* str = gtk_tree_path_to_string (path); |
2090 | + g_print ("midori_bookmarks_row_deleted_cb: path: %s\n", str); |
2091 | + g_free (str); |
2092 | +#endif /* DEBUG_LIST */ |
2093 | + |
2094 | + midori_bookmarks_idle_start (bookmarks); |
2095 | + |
2096 | + bookmarks->added_paths = update_path_list_for_delete (bookmarks->added_paths, path); |
2097 | +#ifdef DEBUG_LIST |
2098 | + print_path_list (bookmarks->reordered_paths); |
2099 | +#endif /* DEBUG_LIST */ |
2100 | + bookmarks->reordered_paths = update_path_list_for_delete (bookmarks->reordered_paths, path); |
2101 | +#ifdef DEBUG_LIST |
2102 | + print_path_list (bookmarks->reordered_paths); |
2103 | +#endif /* DEBUG_LIST */ |
2104 | + assert_reorder_are_folders (model, bookmarks); |
2105 | + add_parent_to_reorder (model, path, bookmarks); |
2106 | + assert_reorder_are_folders (model, bookmarks); |
2107 | +} |
2108 | |
2109 | static void |
2110 | midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
2111 | @@ -499,41 +1623,8 @@ |
2112 | GtkTreeIter* iter, |
2113 | MidoriBookmarks* bookmarks) |
2114 | { |
2115 | - KatzeItem* item; |
2116 | - GtkTreeIter parent; |
2117 | - KatzeItem* new_parent = NULL; |
2118 | - gint64 parentid; |
2119 | - |
2120 | - gtk_tree_model_get (model, iter, 0, &item, -1); |
2121 | - |
2122 | - if (gtk_tree_model_iter_parent (model, &parent, iter)) |
2123 | - { |
2124 | - gtk_tree_model_get (model, &parent, 0, &new_parent, -1); |
2125 | - |
2126 | - /* Bookmarks must not be moved into non-folder items */ |
2127 | - if (!KATZE_ITEM_IS_FOLDER (new_parent)) |
2128 | - parentid = 0; |
2129 | - else |
2130 | - parentid = katze_item_get_meta_integer (new_parent, "id"); |
2131 | - } |
2132 | - else |
2133 | - parentid = 0; |
2134 | - |
2135 | - katze_item_set_meta_integer (item, "parentid", parentid); |
2136 | - |
2137 | - g_signal_handlers_block_by_func (bookmarks->bookmarks_db, |
2138 | - midori_bookmarks_update_item_cb, |
2139 | - bookmarks); |
2140 | - |
2141 | - midori_bookmarks_db_update_item (bookmarks->bookmarks_db, item); |
2142 | - |
2143 | - g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db, |
2144 | - midori_bookmarks_update_item_cb, |
2145 | - bookmarks); |
2146 | - |
2147 | - g_object_unref (item); |
2148 | - if (new_parent) |
2149 | - g_object_unref (new_parent); |
2150 | + add_parent_to_reorder (model, path, bookmarks); |
2151 | + assert_reorder_are_folders (model, bookmarks); |
2152 | } |
2153 | |
2154 | static void |
2155 | @@ -596,7 +1687,7 @@ |
2156 | GtkTreeIter iter; |
2157 | |
2158 | if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview), |
2159 | - &model, &iter)) |
2160 | + &model, &iter)) |
2161 | { |
2162 | KatzeItem* item; |
2163 | MidoriBrowser* browser; |
2164 | @@ -616,15 +1707,17 @@ |
2165 | static void |
2166 | midori_bookmarks_toolbar_update (MidoriBookmarks *bookmarks) |
2167 | { |
2168 | - gboolean selected; |
2169 | + gint selected; |
2170 | |
2171 | - selected = katze_tree_view_get_selected_iter ( |
2172 | + selected = katze_tree_view_get_selected_rows ( |
2173 | GTK_TREE_VIEW (bookmarks->treeview), NULL, NULL); |
2174 | - gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->delete), selected); |
2175 | - gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->edit), selected); |
2176 | + gtk_widget_set_sensitive ( |
2177 | + GTK_WIDGET (bookmarks->delete), (selected > 0 ? TRUE : FALSE)); |
2178 | + gtk_widget_set_sensitive ( |
2179 | + GTK_WIDGET (bookmarks->edit), (selected == 1 ? TRUE : FALSE)); |
2180 | } |
2181 | |
2182 | -static gchar* |
2183 | +static gchar* |
2184 | midori_bookmarks_statusbar_bookmarks_str (gint count) |
2185 | { |
2186 | if (!count) |
2187 | @@ -634,7 +1727,7 @@ |
2188 | return g_strdup_printf (ngettext ("%d bookmark", "%d bookmarks", count), count); |
2189 | } |
2190 | |
2191 | -static gchar* |
2192 | +static gchar* |
2193 | midori_bookmarks_statusbar_subfolders_str (gint count) |
2194 | { |
2195 | if (!count) |
2196 | @@ -648,78 +1741,141 @@ |
2197 | midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks) |
2198 | { |
2199 | gchar* text = NULL; |
2200 | - |
2201 | - if (bookmarks->hovering_item) |
2202 | - { |
2203 | - KatzeItem* item = bookmarks->hovering_item; |
2204 | - |
2205 | - g_assert (!KATZE_ITEM_IS_SEPARATOR (item)); |
2206 | - |
2207 | - if (KATZE_ITEM_IS_FOLDER (item)) |
2208 | + GtkTreeModel* model; |
2209 | + GList *rows; |
2210 | + gint selected; |
2211 | + |
2212 | + selected = katze_tree_view_get_selected_rows ( |
2213 | + GTK_TREE_VIEW (bookmarks->treeview), &model, &rows); |
2214 | + |
2215 | + if (selected > 1) |
2216 | + { |
2217 | + gint i; |
2218 | + gint selected_folders_count = 0; |
2219 | + gint selected_bookmarks_count = 0; |
2220 | + gchar* selected_folders_str = midori_bookmarks_statusbar_subfolders_str (selected_folders_count); |
2221 | + gchar* selected_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (selected_bookmarks_count); |
2222 | + |
2223 | + for (i = 0 ; i < selected ; i++) |
2224 | + { |
2225 | + GtkTreeIter iter; |
2226 | + KatzeItem* item; |
2227 | + |
2228 | + if (!gtk_tree_model_get_iter ( |
2229 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, i))) |
2230 | + continue; |
2231 | + |
2232 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
2233 | + |
2234 | + g_assert (!KATZE_ITEM_IS_SEPARATOR (item)); |
2235 | + |
2236 | + if (KATZE_ITEM_IS_FOLDER (item)) |
2237 | + { |
2238 | + selected_folders_count++; |
2239 | + } |
2240 | + else |
2241 | + { |
2242 | + selected_bookmarks_count++; |
2243 | + } |
2244 | + } |
2245 | + |
2246 | + selected_folders_str = midori_bookmarks_statusbar_subfolders_str (selected_folders_count); |
2247 | + selected_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (selected_bookmarks_count); |
2248 | + |
2249 | + if (!selected_bookmarks_count && !selected_folders_count) |
2250 | + g_assert_not_reached (); |
2251 | + else if (!selected_bookmarks_count && (selected_folders_count >= 1)) |
2252 | + /* i18n: Selection containing [[n] folder(s)] and no bookmark */ |
2253 | + text = g_strdup_printf (_("Selection containing %s and no bookmark"), |
2254 | + selected_folders_str); |
2255 | + else if ((selected_bookmarks_count >= 1) && !selected_folders_count) |
2256 | + /* i18n: Selection containing [[n] bookmark(s)] */ |
2257 | + text = g_strdup_printf (_("Selection containing %s"), selected_bookmarks_str); |
2258 | + else if ((selected_bookmarks_count >= 1) && (selected_folders_count >= 1)) |
2259 | + /* i18n: Selection containing [[n] bookmark(s)] and [[n] folder(s)] */ |
2260 | + text = g_strdup_printf (_("Selection containing %s and %s"), |
2261 | + selected_bookmarks_str, selected_folders_str); |
2262 | + |
2263 | + g_free (selected_folders_str); |
2264 | + g_free (selected_bookmarks_str); |
2265 | + |
2266 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2267 | + } |
2268 | + else |
2269 | + { |
2270 | + if (selected) |
2271 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2272 | + |
2273 | + if (bookmarks->hovering_item) |
2274 | + { |
2275 | + KatzeItem* item = bookmarks->hovering_item; |
2276 | + |
2277 | + if (KATZE_ITEM_IS_FOLDER (item)) |
2278 | + { |
2279 | + gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
2280 | + "uri = ''", NULL, item, FALSE); |
2281 | + gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
2282 | + "uri <> ''", NULL, item, FALSE); |
2283 | + gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count); |
2284 | + gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count); |
2285 | + |
2286 | + if (!child_bookmarks_count && !child_folders_count) |
2287 | + /* i18n: Empty folder */ |
2288 | + text = g_strdup_printf (_("Empty folder")); |
2289 | + else if (!child_bookmarks_count && (child_folders_count >= 1)) |
2290 | + /* i18n: Folder containing [[n] folder(s)] and no bookmark */ |
2291 | + text = g_strdup_printf (_("Folder containing %s and no bookmark"), |
2292 | + child_folders_str); |
2293 | + else if ((child_bookmarks_count >= 1) && !child_folders_count) |
2294 | + /* i18n: Folder containing [[n] bookmark(s)] */ |
2295 | + text = g_strdup_printf (_("Folder containing %s"), child_bookmarks_str); |
2296 | + else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1)) |
2297 | + /* i18n: Folder containing [[n] bookmark(s)] and [[n] folder(s)] */ |
2298 | + text = g_strdup_printf (_("Folder containing %s and %s"), |
2299 | + child_bookmarks_str, child_folders_str); |
2300 | + |
2301 | + g_free (child_folders_str); |
2302 | + g_free (child_bookmarks_str); |
2303 | + } |
2304 | + else if (KATZE_ITEM_IS_BOOKMARK (item)) |
2305 | + { |
2306 | + const gchar* uri = katze_item_get_uri (item); |
2307 | + |
2308 | + /* i18n: Bookmark leading to: [bookmark uri] */ |
2309 | + text = g_strdup_printf (_("Bookmark leading to: %s"), uri); |
2310 | + } |
2311 | + } |
2312 | + else |
2313 | { |
2314 | gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
2315 | - "uri = ''", NULL, item, FALSE); |
2316 | + "uri = ''", NULL, NULL, FALSE); |
2317 | gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
2318 | - "uri <> ''", NULL, item, FALSE); |
2319 | + "uri <> ''", NULL, NULL, FALSE); |
2320 | gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count); |
2321 | gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count); |
2322 | |
2323 | - if (!child_bookmarks_count && !child_folders_count) |
2324 | - /* i18n: Empty folder */ |
2325 | - text = g_strdup_printf (_("Empty folder")); |
2326 | - else if (!child_bookmarks_count && (child_folders_count >= 1)) |
2327 | - /* i18n: Folder containing [[n] folder(s)] and no bookmark */ |
2328 | - text = g_strdup_printf (_("Folder containing %s and no bookmark"), |
2329 | + if (!child_bookmarks_count && (child_folders_count >= 1)) |
2330 | + /* i18n: [[n] folder(s)] and no bookmark */ |
2331 | + text = g_strdup_printf (_("%s and no bookmark"), |
2332 | child_folders_str); |
2333 | else if ((child_bookmarks_count >= 1) && !child_folders_count) |
2334 | - /* i18n: Folder containing [[n] bookmark(s)] */ |
2335 | - text = g_strdup_printf (_("Folder containing %s"), child_bookmarks_str); |
2336 | + text = g_strdup (child_bookmarks_str); |
2337 | else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1)) |
2338 | - /* i18n: Folder containing [[n] bookmark(s)] and [[n] folder(s)] */ |
2339 | - text = g_strdup_printf (_("Folder containing %s and %s"), |
2340 | + /* i18n: [[n] bookmark(s)] and [[n] folder(s)] */ |
2341 | + text = g_strdup_printf (_("%s and %s"), |
2342 | child_bookmarks_str, child_folders_str); |
2343 | |
2344 | g_free (child_folders_str); |
2345 | g_free (child_bookmarks_str); |
2346 | } |
2347 | - else if (KATZE_ITEM_IS_BOOKMARK (item)) |
2348 | - { |
2349 | - const gchar* uri = katze_item_get_uri (item); |
2350 | - |
2351 | - /* i18n: Bookmark leading to: [bookmark uri] */ |
2352 | - text = g_strdup_printf (_("Bookmark leading to: %s"), uri); |
2353 | - } |
2354 | - } |
2355 | - else |
2356 | - { |
2357 | - gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
2358 | - "uri = ''", NULL, NULL, FALSE); |
2359 | - gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
2360 | - "uri <> ''", NULL, NULL, FALSE); |
2361 | - gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count); |
2362 | - gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count); |
2363 | - |
2364 | - if (!child_bookmarks_count && (child_folders_count >= 1)) |
2365 | - /* i18n: [[n] folder(s)] and no bookmark */ |
2366 | - text = g_strdup_printf (_("%s and no bookmark"), |
2367 | - child_folders_str); |
2368 | - else if ((child_bookmarks_count >= 1) && !child_folders_count) |
2369 | - text = g_strdup (child_bookmarks_str); |
2370 | - else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1)) |
2371 | - /* i18n: [[n] bookmark(s)] and [[n] folder(s)] */ |
2372 | - text = g_strdup_printf (_("%s and %s"), |
2373 | - child_bookmarks_str, child_folders_str); |
2374 | - |
2375 | - g_free (child_folders_str); |
2376 | - g_free (child_bookmarks_str); |
2377 | } |
2378 | |
2379 | if (text) |
2380 | { |
2381 | MidoriBrowser* browser = midori_browser_get_for_widget (bookmarks->treeview); |
2382 | - |
2383 | + |
2384 | g_object_set (browser, "statusbar-text", text, NULL); |
2385 | - |
2386 | + |
2387 | g_free(text); |
2388 | } |
2389 | } |
2390 | @@ -729,19 +1885,33 @@ |
2391 | MidoriBookmarks* bookmarks) |
2392 | { |
2393 | GtkTreeModel* model; |
2394 | - GtkTreeIter iter; |
2395 | - |
2396 | - if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview), |
2397 | - &model, &iter)) |
2398 | + GList* rows; |
2399 | + GList* iter_row; |
2400 | + |
2401 | + if (!katze_tree_view_get_selected_rows(GTK_TREE_VIEW (bookmarks->treeview), |
2402 | + &model, &rows)) |
2403 | + return; |
2404 | + |
2405 | + for (iter_row = rows ; iter_row ; iter_row = g_list_next (iter_row)) |
2406 | { |
2407 | - KatzeItem* item; |
2408 | - |
2409 | - gtk_tree_model_get (model, &iter, 0, &item, -1); |
2410 | - |
2411 | - midori_bookmarks_db_remove_item (bookmarks->bookmarks_db, item); |
2412 | - |
2413 | - g_object_unref (item); |
2414 | + GtkTreeIter iter; |
2415 | + |
2416 | + if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *)iter_row->data)) |
2417 | + { |
2418 | + KatzeItem* item; |
2419 | + |
2420 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
2421 | + |
2422 | + if (item) |
2423 | + { |
2424 | + midori_bookmarks_db_remove_item (bookmarks->bookmarks_db, item); |
2425 | + |
2426 | + g_object_unref (item); |
2427 | + } |
2428 | + } |
2429 | } |
2430 | + |
2431 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2432 | } |
2433 | |
2434 | static GtkWidget* |
2435 | @@ -759,7 +1929,7 @@ |
2436 | toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK_ADD); |
2437 | gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkAdd"); |
2438 | gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), |
2439 | - _("Add a new bookmark")); |
2440 | + _("Add a new bookmark")); |
2441 | gtk_tool_item_set_is_important (toolitem, TRUE); |
2442 | g_signal_connect (toolitem, "clicked", |
2443 | G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks); |
2444 | @@ -767,7 +1937,7 @@ |
2445 | gtk_widget_show (GTK_WIDGET (toolitem)); |
2446 | toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_EDIT); |
2447 | gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), |
2448 | - _("Edit the selected bookmark")); |
2449 | + _("Edit the selected bookmark")); |
2450 | g_signal_connect (toolitem, "clicked", |
2451 | G_CALLBACK (midori_bookmarks_edit_clicked_cb), bookmarks); |
2452 | gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); |
2453 | @@ -775,7 +1945,7 @@ |
2454 | bookmarks->edit = GTK_WIDGET (toolitem); |
2455 | toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE); |
2456 | gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), |
2457 | - _("Delete the selected bookmark")); |
2458 | + _("Delete the selected bookmark")); |
2459 | g_signal_connect (toolitem, "clicked", |
2460 | G_CALLBACK (midori_bookmarks_delete_clicked_cb), bookmarks); |
2461 | gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); |
2462 | @@ -791,7 +1961,7 @@ |
2463 | toolitem = gtk_tool_button_new_from_stock (STOCK_FOLDER_NEW); |
2464 | gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkFolderAdd"); |
2465 | gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), |
2466 | - _("Add a new folder")); |
2467 | + _("Add a new folder")); |
2468 | g_signal_connect (toolitem, "clicked", |
2469 | G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks); |
2470 | gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); |
2471 | @@ -841,6 +2011,12 @@ |
2472 | G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks); |
2473 | g_signal_connect (bookmarks->bookmarks_db, "update", |
2474 | G_CALLBACK (midori_bookmarks_update_cb), bookmarks); |
2475 | + g_signal_connect_after (model, "row-inserted", |
2476 | + G_CALLBACK (midori_bookmarks_row_inserted_cb), |
2477 | + bookmarks); |
2478 | + g_signal_connect_after (model, "row-deleted", |
2479 | + G_CALLBACK (midori_bookmarks_row_deleted_cb), |
2480 | + bookmarks); |
2481 | g_signal_connect_after (model, "row-changed", |
2482 | G_CALLBACK (midori_bookmarks_row_changed_cb), |
2483 | bookmarks); |
2484 | @@ -856,12 +2032,12 @@ |
2485 | |
2486 | switch (prop_id) |
2487 | { |
2488 | - case PROP_APP: |
2489 | - midori_bookmarks_set_app (bookmarks, g_value_get_object (value)); |
2490 | - break; |
2491 | - default: |
2492 | - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
2493 | - break; |
2494 | + case PROP_APP: |
2495 | + midori_bookmarks_set_app (bookmarks, g_value_get_object (value)); |
2496 | + break; |
2497 | + default: |
2498 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
2499 | + break; |
2500 | } |
2501 | } |
2502 | |
2503 | @@ -875,12 +2051,12 @@ |
2504 | |
2505 | switch (prop_id) |
2506 | { |
2507 | - case PROP_APP: |
2508 | - g_value_set_object (value, bookmarks->app); |
2509 | - break; |
2510 | - default: |
2511 | - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
2512 | - break; |
2513 | + case PROP_APP: |
2514 | + g_value_set_object (value, bookmarks->app); |
2515 | + break; |
2516 | + default: |
2517 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
2518 | + break; |
2519 | } |
2520 | } |
2521 | |
2522 | @@ -918,8 +2094,8 @@ |
2523 | if (item && katze_item_get_name (item)) |
2524 | { |
2525 | g_object_set (renderer, "markup", NULL, |
2526 | - "ellipsize", PANGO_ELLIPSIZE_END, |
2527 | - "text", katze_item_get_name (item), NULL); |
2528 | + "ellipsize", PANGO_ELLIPSIZE_END, |
2529 | + "text", katze_item_get_name (item), NULL); |
2530 | } |
2531 | else |
2532 | g_object_set (renderer, "markup", _("<i>Separator</i>"), NULL); |
2533 | @@ -976,7 +2152,7 @@ |
2534 | menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL); |
2535 | if (label) |
2536 | gtk_label_set_text_with_mnemonic (GTK_LABEL (gtk_bin_get_child ( |
2537 | - GTK_BIN (menuitem))), label); |
2538 | + GTK_BIN (menuitem))), label); |
2539 | if (!strcmp (stock_id, GTK_STOCK_EDIT)) |
2540 | gtk_widget_set_sensitive (menuitem, |
2541 | !KATZE_ITEM_IS_SEPARATOR (item)); |
2542 | @@ -1007,39 +2183,103 @@ |
2543 | } |
2544 | } |
2545 | |
2546 | -static void |
2547 | -midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem, |
2548 | - MidoriBookmarks* bookmarks) |
2549 | -{ |
2550 | - KatzeItem* item; |
2551 | - const gchar* uri; |
2552 | - |
2553 | - item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem"); |
2554 | - if (KATZE_ITEM_IS_FOLDER (item)) |
2555 | +static GtkWidget* |
2556 | +midori_bookmarks_open_bookmark_in_tab (KatzeItem *item, |
2557 | + MidoriBrowser* browser) |
2558 | +{ |
2559 | + const gchar* uri = katze_item_get_uri (item); |
2560 | + |
2561 | + if (!uri || !*uri) |
2562 | + return NULL; |
2563 | + |
2564 | + return midori_browser_add_item (browser, item); |
2565 | +} |
2566 | + |
2567 | +static GtkWidget* |
2568 | +midori_bookmarks_open_folder_in_tab (gint64 parentid, |
2569 | + MidoriBookmarks* bookmarks, |
2570 | + MidoriBrowser* browser) |
2571 | +{ |
2572 | + GtkWidget* last_view = NULL; |
2573 | + KatzeArray* array; |
2574 | + |
2575 | + array = midori_bookmarks_read_from_db (bookmarks, parentid, NULL); |
2576 | + |
2577 | + if (KATZE_IS_ARRAY (array)) |
2578 | { |
2579 | KatzeItem* child; |
2580 | - KatzeArray* array; |
2581 | - |
2582 | - array = midori_bookmarks_read_from_db (bookmarks, |
2583 | - katze_item_get_meta_integer (item, "parentid"), NULL); |
2584 | - |
2585 | - g_return_if_fail (KATZE_IS_ARRAY (array)); |
2586 | + |
2587 | KATZE_ARRAY_FOREACH_ITEM (child, array) |
2588 | { |
2589 | - if ((uri = katze_item_get_uri (child)) && *uri) |
2590 | + GtkWidget* view = midori_bookmarks_open_bookmark_in_tab (child, browser); |
2591 | + if (view) |
2592 | + last_view = view; |
2593 | + } |
2594 | + } |
2595 | + |
2596 | + return last_view; |
2597 | +} |
2598 | + |
2599 | +static void |
2600 | +midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem, |
2601 | + MidoriBookmarks* bookmarks) |
2602 | +{ |
2603 | + GtkWidget* last_view = NULL; |
2604 | + MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
2605 | + GtkTreeModel* model; |
2606 | + GList* rows; |
2607 | + gint length; |
2608 | + |
2609 | + length = katze_tree_view_get_selected_rows (GTK_TREE_VIEW (bookmarks->treeview), |
2610 | + &model, &rows); |
2611 | + |
2612 | + if (!length) |
2613 | + { |
2614 | + KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db); |
2615 | + KatzeItem* item = KATZE_ITEM (g_object_get_data (G_OBJECT (menuitem), "KatzeItem")); |
2616 | + |
2617 | + if (item != root) |
2618 | + return; |
2619 | + |
2620 | + last_view = midori_bookmarks_open_folder_in_tab (0, bookmarks, browser); |
2621 | + } |
2622 | + else |
2623 | + { |
2624 | + gint i; |
2625 | + |
2626 | + for (i = 0 ; i < length; i++) |
2627 | + { |
2628 | + GtkTreeIter iter; |
2629 | + |
2630 | + if (gtk_tree_model_get_iter ( |
2631 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, i))) |
2632 | { |
2633 | - MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
2634 | - GtkWidget* view = midori_browser_add_item (browser, child); |
2635 | - midori_browser_set_current_tab_smartly (browser, view); |
2636 | + GtkWidget* view = NULL; |
2637 | + KatzeItem* item; |
2638 | + |
2639 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
2640 | + |
2641 | + if (KATZE_ITEM_IS_SEPARATOR(item)) |
2642 | + continue; |
2643 | + |
2644 | + if (KATZE_ITEM_IS_FOLDER (item)) |
2645 | + view = midori_bookmarks_open_folder_in_tab ( |
2646 | + katze_item_get_meta_integer (item, "id"), bookmarks, browser); |
2647 | + else |
2648 | + view = midori_bookmarks_open_bookmark_in_tab (item, browser); |
2649 | + |
2650 | + g_object_unref (item); |
2651 | + |
2652 | + if (view) |
2653 | + last_view = view; |
2654 | } |
2655 | } |
2656 | - } |
2657 | - else if ((uri = katze_item_get_uri (item)) && *uri) |
2658 | - { |
2659 | - MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
2660 | - GtkWidget* view = midori_browser_add_item (browser, item); |
2661 | - midori_browser_set_current_tab_smartly (browser, view); |
2662 | - } |
2663 | + |
2664 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2665 | + } |
2666 | + |
2667 | + if (last_view) |
2668 | + midori_browser_set_current_tab_smartly (browser, last_view); |
2669 | } |
2670 | |
2671 | static void |
2672 | @@ -1067,18 +2307,20 @@ |
2673 | KatzeItem* item, |
2674 | MidoriBookmarks* bookmarks) |
2675 | { |
2676 | + KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db); |
2677 | GtkWidget* menu; |
2678 | GtkWidget* menuitem; |
2679 | |
2680 | menu = gtk_menu_new (); |
2681 | - if (KATZE_ITEM_IS_FOLDER (item)) |
2682 | + if ((item == root) |
2683 | + || KATZE_ITEM_IS_FOLDER (item)) |
2684 | { |
2685 | gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
2686 | "uri <> ''", NULL, item, FALSE); |
2687 | |
2688 | midori_bookmarks_popup_item (menu, |
2689 | - STOCK_TAB_NEW, _("Open all in _Tabs"), item, |
2690 | - (!child_bookmarks_count ? NULL : midori_bookmarks_open_in_tab_activate_cb), |
2691 | + STOCK_TAB_NEW, _("Open all in _Tabs"), item, |
2692 | + (!child_bookmarks_count ? NULL : midori_bookmarks_open_in_tab_activate_cb), |
2693 | bookmarks); |
2694 | } |
2695 | else |
2696 | @@ -1094,11 +2336,59 @@ |
2697 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
2698 | gtk_widget_show (menuitem); |
2699 | midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL, |
2700 | - item, midori_bookmarks_edit_clicked_cb, bookmarks); |
2701 | - midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
2702 | - item, midori_bookmarks_delete_clicked_cb, bookmarks); |
2703 | - |
2704 | - katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
2705 | + item, (item == root) ? NULL : midori_bookmarks_edit_clicked_cb, bookmarks); |
2706 | + midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
2707 | + item, (item == root) ? NULL : midori_bookmarks_delete_clicked_cb, bookmarks); |
2708 | + |
2709 | + katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
2710 | +} |
2711 | + |
2712 | +static void |
2713 | +midori_bookmarks_multi_popup (GtkWidget* widget, |
2714 | + GdkEventButton* event, |
2715 | + MidoriBookmarks* bookmarks, |
2716 | + GtkTreeModel* model, |
2717 | + gint count, |
2718 | + GList* rows) |
2719 | +{ |
2720 | + GtkWidget* menu; |
2721 | + GtkWidget* menuitem; |
2722 | + |
2723 | + menu = gtk_menu_new (); |
2724 | + |
2725 | + midori_bookmarks_popup_item (menu, |
2726 | + STOCK_TAB_NEW, _("Open all in _Tabs"), |
2727 | + KATZE_ITEM(bookmarks->bookmarks_db), midori_bookmarks_open_in_tab_activate_cb, bookmarks); |
2728 | + menuitem = gtk_separator_menu_item_new (); |
2729 | + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
2730 | + gtk_widget_show (menuitem); |
2731 | + |
2732 | + midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL, |
2733 | + NULL, NULL, bookmarks); |
2734 | + midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
2735 | + KATZE_ITEM(bookmarks->bookmarks_db), midori_bookmarks_delete_clicked_cb, bookmarks); |
2736 | + |
2737 | + katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
2738 | +} |
2739 | + |
2740 | +static gboolean |
2741 | +midori_bookmarks_do_block_selection (GtkTreeSelection *selection, |
2742 | + GtkTreeModel *model, |
2743 | + GtkTreePath *path, |
2744 | + gboolean path_currently_selected, |
2745 | + gpointer data) |
2746 | +{ |
2747 | + return FALSE; |
2748 | +} |
2749 | + |
2750 | +static gboolean |
2751 | +midori_bookmarks_do_not_block_selection (GtkTreeSelection *selection, |
2752 | + GtkTreeModel *model, |
2753 | + GtkTreePath *path, |
2754 | + gboolean path_currently_selected, |
2755 | + gpointer data) |
2756 | +{ |
2757 | + return TRUE; |
2758 | } |
2759 | |
2760 | static gboolean |
2761 | @@ -1109,32 +2399,194 @@ |
2762 | GtkTreeModel* model; |
2763 | GtkTreeIter iter; |
2764 | |
2765 | - if (event->button != 2 && event->button != 3) |
2766 | + if (bookmarks->pending_event) |
2767 | + { |
2768 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
2769 | + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); |
2770 | + gint x = bookmarks->stock_pending_event.x; |
2771 | + gint y = bookmarks->stock_pending_event.y; |
2772 | + |
2773 | + bookmarks->pending_event = NULL; |
2774 | + gtk_tree_selection_set_select_function ( |
2775 | + selection, midori_bookmarks_do_not_block_selection, NULL, NULL); |
2776 | + |
2777 | + if (x != event->x || y != event->y) |
2778 | + return FALSE; |
2779 | + } |
2780 | + |
2781 | + if (event->button == 3) |
2782 | + return TRUE; |
2783 | + |
2784 | + if (event->button != 2) |
2785 | return FALSE; |
2786 | |
2787 | if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter)) |
2788 | { |
2789 | + gboolean done = FALSE; |
2790 | KatzeItem* item; |
2791 | |
2792 | gtk_tree_model_get (model, &iter, 0, &item, -1); |
2793 | |
2794 | - if (event->button == 2) |
2795 | + if (KATZE_ITEM_IS_BOOKMARK (item)) |
2796 | { |
2797 | - const gchar* uri; |
2798 | - if (KATZE_ITEM_IS_BOOKMARK (item) && (uri = katze_item_get_uri (item)) && *uri) |
2799 | + MidoriBrowser* browser = midori_browser_get_for_widget (widget); |
2800 | + GtkWidget* view = midori_bookmarks_open_bookmark_in_tab ( |
2801 | + item, browser); |
2802 | + |
2803 | + if (widget) |
2804 | { |
2805 | - MidoriBrowser* browser = midori_browser_get_for_widget (widget); |
2806 | - GtkWidget* view = midori_browser_add_uri (browser, uri); |
2807 | - midori_browser_set_current_tab (browser, view); |
2808 | + midori_browser_set_current_tab_smartly (browser, view); |
2809 | + done = TRUE; |
2810 | } |
2811 | } |
2812 | - else |
2813 | - midori_bookmarks_popup (widget, event, item, bookmarks); |
2814 | - |
2815 | - if (item != NULL) |
2816 | - g_object_unref (item); |
2817 | - return TRUE; |
2818 | - } |
2819 | + |
2820 | + g_object_unref (item); |
2821 | + |
2822 | + return done; |
2823 | + } |
2824 | + |
2825 | + return FALSE; |
2826 | +} |
2827 | + |
2828 | +static gboolean |
2829 | +midori_bookmarks_block_selection(GtkWidget* widget, |
2830 | + GdkEventButton* event, |
2831 | + MidoriBookmarks* bookmarks) |
2832 | +{ |
2833 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
2834 | + GtkTreePath* path; |
2835 | + GtkTreeSelection* selection; |
2836 | + gint cell_x; |
2837 | + gint cell_y; |
2838 | + |
2839 | + if (!gtk_tree_view_get_path_at_pos ( |
2840 | + treeview, event->x, event->y, |
2841 | + &path, NULL, &cell_x, &cell_y)) |
2842 | + return FALSE; |
2843 | + |
2844 | + gtk_widget_grab_focus (widget); |
2845 | + |
2846 | + selection = gtk_tree_view_get_selection (treeview); |
2847 | + |
2848 | + if (gtk_tree_selection_path_is_selected (selection, path) |
2849 | + && !(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK))) |
2850 | + { |
2851 | + bookmarks->pending_event = &bookmarks->stock_pending_event; |
2852 | + bookmarks->stock_pending_event.x = event->x; |
2853 | + bookmarks->stock_pending_event.y = event->y; |
2854 | + gtk_tree_selection_set_select_function ( |
2855 | + selection, midori_bookmarks_do_block_selection, NULL, NULL); |
2856 | + } |
2857 | + else |
2858 | + { |
2859 | + bookmarks->pending_event = NULL; |
2860 | + gtk_tree_selection_set_select_function ( |
2861 | + selection, midori_bookmarks_do_not_block_selection, NULL, NULL); |
2862 | + } |
2863 | + |
2864 | + return FALSE; |
2865 | +} |
2866 | + |
2867 | +static gboolean |
2868 | +midori_bookmarks_button_press_event_cb (GtkWidget* widget, |
2869 | + GdkEventButton* event, |
2870 | + MidoriBookmarks* bookmarks) |
2871 | +{ |
2872 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
2873 | + GtkTreePath* path; |
2874 | + GtkTreeSelection* selection; |
2875 | + GtkTreeModel* model; |
2876 | + gint selected; |
2877 | + GList* rows; |
2878 | + gint cell_x; |
2879 | + gint cell_y; |
2880 | + |
2881 | + if (event->button == 1) |
2882 | + return midori_bookmarks_block_selection (widget, event, bookmarks); |
2883 | + |
2884 | + if (event->button != 3) |
2885 | + return FALSE; |
2886 | + |
2887 | + selection = gtk_tree_view_get_selection (treeview); |
2888 | + |
2889 | + if (!gtk_tree_view_get_path_at_pos ( |
2890 | + treeview, event->x, event->y, |
2891 | + &path, NULL, &cell_x, &cell_y)) |
2892 | + { |
2893 | + /* FIXME: popup opening below treeview |
2894 | + * Rationale: the user is actually in ROOT folder |
2895 | + * we may need to have a non editable, non deletable, ROOT folder popup |
2896 | + * Open all in Tabs |
2897 | + * Separator |
2898 | + * Edit [inactive] |
2899 | + * Delete [inactive] |
2900 | + * Here we just mimic the Files behaviour: |
2901 | + * 1- unselect all |
2902 | + * 2- let popup based on selection process |
2903 | + */ |
2904 | + |
2905 | + gtk_tree_selection_unselect_all (selection); |
2906 | + } |
2907 | + else if (!gtk_tree_selection_path_is_selected (selection, path)) |
2908 | + { |
2909 | + /* Use case: popup opening on item not in selection |
2910 | + * Rationale: the user is addressing a single item not in selection |
2911 | + * we may need a single item popup with callbacks working on the item, |
2912 | + * not the selection. |
2913 | + * Here we just mimic the Files behaviour: |
2914 | + * 1- change the selection to the item the popup is opened on |
2915 | + * 2- let popup based on selection process |
2916 | + */ |
2917 | + |
2918 | + gtk_tree_selection_unselect_all (selection); |
2919 | + gtk_tree_selection_select_path (selection, path); |
2920 | + } |
2921 | + |
2922 | + selected = katze_tree_view_get_selected_rows(GTK_TREE_VIEW (widget), &model, &rows); |
2923 | + |
2924 | + if (!selected) |
2925 | + { |
2926 | + KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db); |
2927 | + |
2928 | + midori_bookmarks_popup (widget, event, root, bookmarks); |
2929 | + |
2930 | + return TRUE; |
2931 | + } |
2932 | + |
2933 | + if (selected == 1) |
2934 | + { |
2935 | + GtkTreeIter iter; |
2936 | + KatzeItem* item; |
2937 | + |
2938 | + if (!gtk_tree_model_get_iter ( |
2939 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, 0))) |
2940 | + { |
2941 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2942 | + |
2943 | + return FALSE; |
2944 | + } |
2945 | + |
2946 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
2947 | + |
2948 | + midori_bookmarks_popup (widget, event, item, bookmarks); |
2949 | + |
2950 | + g_object_unref (item); |
2951 | + |
2952 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2953 | + |
2954 | + return TRUE; |
2955 | + } |
2956 | + |
2957 | + if (selected > 1) |
2958 | + { |
2959 | + midori_bookmarks_multi_popup (widget, event, bookmarks, |
2960 | + model, selected, rows); |
2961 | + |
2962 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2963 | + |
2964 | + return TRUE; |
2965 | + } |
2966 | + |
2967 | return FALSE; |
2968 | } |
2969 | |
2970 | @@ -1165,39 +2617,74 @@ |
2971 | } |
2972 | } |
2973 | |
2974 | -static void |
2975 | -midori_bookmarks_row_expanded_cb (GtkTreeView* treeview, |
2976 | - GtkTreeIter* iter, |
2977 | - GtkTreePath* path, |
2978 | - MidoriBookmarks* bookmarks) |
2979 | +static gboolean |
2980 | +midori_bookmarks_test_expand_row_cb (GtkTreeView* treeview, |
2981 | + GtkTreeIter* iter, |
2982 | + GtkTreePath* path, |
2983 | + MidoriBookmarks* bookmarks) |
2984 | { |
2985 | GtkTreeModel* model; |
2986 | + GtkTreeIter child; |
2987 | KatzeItem* item; |
2988 | + gint64 id; |
2989 | |
2990 | model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); |
2991 | + |
2992 | gtk_tree_model_get (model, iter, 0, &item, -1); |
2993 | + |
2994 | + g_return_val_if_fail (KATZE_IS_ITEM(item), TRUE); |
2995 | + |
2996 | + g_signal_handlers_block_by_func (model, |
2997 | + midori_bookmarks_row_deleted_cb, |
2998 | + bookmarks); |
2999 | + |
3000 | + id = katze_item_get_meta_integer (item, "id"); |
3001 | + |
3002 | + g_object_unref (item); |
3003 | + |
3004 | + while (gtk_tree_model_iter_children (model, &child, iter)) |
3005 | + gtk_tree_store_remove (GTK_TREE_STORE (model), &child); |
3006 | + /* That's an invisible dummy, so we always have an expander */ |
3007 | + gtk_tree_store_insert_with_values (GTK_TREE_STORE (model), &child, iter, |
3008 | + 0, 0, NULL, -1); |
3009 | + |
3010 | + g_signal_handlers_unblock_by_func (model, |
3011 | + midori_bookmarks_row_deleted_cb, |
3012 | + bookmarks); |
3013 | + |
3014 | midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), |
3015 | - iter, katze_item_get_meta_integer (item, "id"), NULL); |
3016 | - g_object_unref (item); |
3017 | + iter, id, NULL); |
3018 | + |
3019 | + return FALSE; |
3020 | } |
3021 | |
3022 | static void |
3023 | midori_bookmarks_row_collapsed_cb (GtkTreeView *treeview, |
3024 | GtkTreeIter *parent, |
3025 | GtkTreePath *path, |
3026 | - gpointer user_data) |
3027 | + MidoriBookmarks* bookmarks) |
3028 | { |
3029 | GtkTreeModel* model; |
3030 | GtkTreeStore* treestore; |
3031 | GtkTreeIter child; |
3032 | |
3033 | model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); |
3034 | + |
3035 | + g_signal_handlers_block_by_func (model, |
3036 | + midori_bookmarks_row_deleted_cb, |
3037 | + bookmarks); |
3038 | + |
3039 | treestore = GTK_TREE_STORE (model); |
3040 | while (gtk_tree_model_iter_nth_child (model, &child, parent, 0)) |
3041 | gtk_tree_store_remove (treestore, &child); |
3042 | /* That's an invisible dummy, so we always have an expander */ |
3043 | gtk_tree_store_insert_with_values (treestore, &child, parent, |
3044 | 0, 0, NULL, -1); |
3045 | + |
3046 | + g_signal_handlers_block_by_func (model, |
3047 | + midori_bookmarks_row_deleted_cb, |
3048 | + bookmarks); |
3049 | + |
3050 | } |
3051 | |
3052 | static void |
3053 | @@ -1205,26 +2692,27 @@ |
3054 | MidoriBookmarks *bookmarks) |
3055 | { |
3056 | midori_bookmarks_toolbar_update (bookmarks); |
3057 | + midori_bookmarks_statusbar_update (bookmarks); |
3058 | } |
3059 | |
3060 | static KatzeItem* |
3061 | midori_bookmarks_get_item_at_pos (GtkTreeView *treeview, |
3062 | gint x, gint y) |
3063 | -{ |
3064 | +{ |
3065 | GtkTreeModel* model = gtk_tree_view_get_model (treeview); |
3066 | GtkTreePath* path; |
3067 | GtkTreeIter iter; |
3068 | KatzeItem* item = NULL; |
3069 | |
3070 | gtk_tree_view_get_path_at_pos (treeview, x, y, |
3071 | - &path, NULL, NULL, NULL); |
3072 | - |
3073 | + &path, NULL, NULL, NULL); |
3074 | + |
3075 | if (!path) |
3076 | return NULL; |
3077 | - |
3078 | + |
3079 | if (gtk_tree_model_get_iter (model, &iter, path)) |
3080 | gtk_tree_model_get (model, &iter, 0, &item, -1); |
3081 | - |
3082 | + |
3083 | gtk_tree_path_free (path); |
3084 | |
3085 | return item; |
3086 | @@ -1296,7 +2784,7 @@ |
3087 | |
3088 | if (bookmarks->hovering_item) |
3089 | g_object_unref (bookmarks->hovering_item); |
3090 | - |
3091 | + |
3092 | bookmarks->hovering_item = NULL; |
3093 | |
3094 | g_object_set (browser, "statusbar-text", "", NULL); |
3095 | @@ -1337,6 +2825,183 @@ |
3096 | midori_bookmarks_filter_timeout_cb, bookmarks, NULL); |
3097 | } |
3098 | |
3099 | +static GtkTargetEntry midori_bookmarks_dnd_target_entries[]= |
3100 | +{ |
3101 | + {MIDORI_BOOKMARKS_TREE_MODEL_TARGET, GTK_TARGET_SAME_WIDGET, 0}, |
3102 | +}; |
3103 | + |
3104 | +#define MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES \ |
3105 | + G_N_ELEMENTS (midori_bookmarks_dnd_target_entries) |
3106 | + |
3107 | +static guint |
3108 | +item_hash (gconstpointer item) |
3109 | +{ |
3110 | + gint64 id = katze_item_get_meta_integer (KATZE_ITEM (item), "id"); |
3111 | + return g_int64_hash (&id); |
3112 | +} |
3113 | + |
3114 | +static gboolean |
3115 | +item_equal (gconstpointer item_a, gconstpointer item_b) |
3116 | +{ |
3117 | + gint64 id_a = katze_item_get_meta_integer (KATZE_ITEM (item_a), "id"); |
3118 | + gint64 id_b = katze_item_get_meta_integer (KATZE_ITEM (item_b), "id"); |
3119 | + return (id_a == id_b)? TRUE : FALSE; |
3120 | +} |
3121 | + |
3122 | +static gboolean |
3123 | +midori_bookmarks_idle_func (gpointer data) |
3124 | +{ |
3125 | + MidoriBookmarks* bookmarks = MIDORI_BOOKMARKS (data); |
3126 | + GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
3127 | + GHashTableIter hash_iter; |
3128 | + gpointer key, value; |
3129 | + GList* list_iter; |
3130 | + |
3131 | + /* update remaining additions */ |
3132 | + assert_reorder_are_folders (model, bookmarks); |
3133 | + for (list_iter = bookmarks->added_paths; list_iter ; list_iter = g_list_next (list_iter)) |
3134 | + { |
3135 | + GtkTreePath* path = (GtkTreePath*)list_iter->data; |
3136 | + |
3137 | + add_parent_to_reorder (model, path, bookmarks); |
3138 | + assert_reorder_are_folders (model, bookmarks); |
3139 | + } |
3140 | + |
3141 | + g_list_free_full (bookmarks->added_paths, (GDestroyNotify) gtk_tree_path_free); |
3142 | + bookmarks->added_paths = NULL; |
3143 | + |
3144 | + /* do actual reordering */ |
3145 | + for (list_iter = bookmarks->reordered_paths; list_iter ; list_iter = g_list_next (list_iter)) |
3146 | + { |
3147 | + GtkTreeIter local_iter; |
3148 | + GtkTreePath* path = (GtkTreePath*)list_iter->data; |
3149 | + |
3150 | + if (gtk_tree_path_get_depth (path)) |
3151 | + { |
3152 | + GtkTreeIter parent; |
3153 | + |
3154 | + if (gtk_tree_model_get_iter (model, &parent, path)) |
3155 | + { |
3156 | + KatzeItem *item; |
3157 | + gint64 id; |
3158 | + |
3159 | + gtk_tree_model_get (model, &parent, 0, &item, -1); |
3160 | + |
3161 | + g_assert (KATZE_ITEM_IS_FOLDER (item)); |
3162 | + |
3163 | + id = katze_item_get_meta_integer (item, "id"); |
3164 | + |
3165 | + if (gtk_tree_model_iter_children (model, &local_iter, &parent)) |
3166 | + midori_bookmarks_set_item_positon(model, &local_iter, id, bookmarks); |
3167 | + |
3168 | + /* update folder array for menu update */ |
3169 | + katze_array_update (KATZE_ARRAY (item)); |
3170 | + |
3171 | + g_object_unref (item); |
3172 | + } |
3173 | + } |
3174 | + else |
3175 | + { |
3176 | + if (gtk_tree_model_get_iter_first (model, &local_iter)) |
3177 | + midori_bookmarks_set_item_positon(model, &local_iter, |
3178 | + katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id"), |
3179 | + bookmarks); |
3180 | + |
3181 | + g_signal_handlers_block_by_func (bookmarks->bookmarks_db, |
3182 | + midori_bookmarks_update_cb, |
3183 | + bookmarks); |
3184 | + |
3185 | + /* update folder array for menu update */ |
3186 | + katze_array_update (KATZE_ARRAY (bookmarks->bookmarks_db)); |
3187 | + |
3188 | + g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db, |
3189 | + midori_bookmarks_update_cb, |
3190 | + bookmarks); |
3191 | + } |
3192 | + } |
3193 | + |
3194 | + g_list_free_full (bookmarks->reordered_paths, (GDestroyNotify) gtk_tree_path_free); |
3195 | + bookmarks->reordered_paths = NULL; |
3196 | + |
3197 | + /* then finalize updates */ |
3198 | + g_signal_handlers_block_by_func (bookmarks->bookmarks_db, |
3199 | + midori_bookmarks_update_item_cb, |
3200 | + bookmarks); |
3201 | + |
3202 | + g_hash_table_iter_init (&hash_iter, bookmarks->updated_items); |
3203 | + |
3204 | + while (g_hash_table_iter_next (&hash_iter, &key, &value)) |
3205 | + { |
3206 | + midori_bookmarks_db_update_item (bookmarks->bookmarks_db, KATZE_ITEM (value)); |
3207 | + g_object_unref (value); |
3208 | + } |
3209 | + |
3210 | + g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db, |
3211 | + midori_bookmarks_update_item_cb, |
3212 | + bookmarks); |
3213 | + |
3214 | + g_hash_table_remove_all (bookmarks->updated_items); |
3215 | + |
3216 | + /* process pending additions of inserted bookmarks */ |
3217 | + for (list_iter = bookmarks->pending_inserts; list_iter; list_iter = g_list_next (list_iter)) |
3218 | + { |
3219 | + KatzeItem *item = KATZE_ITEM (list_iter->data); |
3220 | + |
3221 | + midori_bookmarks_add_item (item, bookmarks); |
3222 | + |
3223 | + g_object_unref (item); |
3224 | + } |
3225 | + |
3226 | + g_list_free (bookmarks->pending_inserts); |
3227 | + bookmarks->pending_inserts = NULL; |
3228 | + return midori_bookmarks_idle_pending (bookmarks); |
3229 | +} |
3230 | + |
3231 | +static void |
3232 | +midori_bookmarks_update_item (MidoriBookmarks* bookmarks, KatzeItem *item) |
3233 | +{ |
3234 | + midori_bookmarks_idle_start (bookmarks); |
3235 | + |
3236 | + if (g_hash_table_lookup (bookmarks->updated_items, item)) |
3237 | + return; |
3238 | + |
3239 | + g_object_ref (item); |
3240 | + g_hash_table_insert (bookmarks->updated_items, item, item); |
3241 | +} |
3242 | + |
3243 | +static void |
3244 | +midori_bookmarks_idle_remove_item (MidoriBookmarks* bookmarks, KatzeItem *item) |
3245 | +{ |
3246 | + gpointer found; |
3247 | + |
3248 | + if (KATZE_ITEM_IS_FOLDER (item)) |
3249 | + { |
3250 | + gint64 id = katze_item_get_meta_integer (item, "id"); |
3251 | + GHashTableIter iter; |
3252 | + gpointer key, value; |
3253 | + |
3254 | + g_hash_table_iter_init (&iter, bookmarks->updated_items); |
3255 | + |
3256 | + while (g_hash_table_iter_next (&iter, &key, &value)) |
3257 | + { |
3258 | + KatzeItem *hash_item = KATZE_ITEM(key); |
3259 | + |
3260 | + gint64 parentid = katze_item_get_meta_integer (hash_item, "parentid"); |
3261 | + if (parentid == id) |
3262 | + { |
3263 | + g_hash_table_iter_remove (&iter); |
3264 | + g_object_unref (hash_item); |
3265 | + } |
3266 | + } |
3267 | + } |
3268 | + |
3269 | + if ((found = g_hash_table_lookup (bookmarks->updated_items, item)) != NULL) |
3270 | + { |
3271 | + g_hash_table_remove (bookmarks->updated_items, found); |
3272 | + g_object_unref (found); |
3273 | + } |
3274 | +} |
3275 | + |
3276 | static void |
3277 | midori_bookmarks_init (MidoriBookmarks* bookmarks) |
3278 | { |
3279 | @@ -1349,6 +3014,8 @@ |
3280 | GtkCellRenderer* renderer_text; |
3281 | GtkTreeSelection* selection; |
3282 | |
3283 | + bookmarks->pending_event = NULL; |
3284 | + |
3285 | /* Create the filter entry */ |
3286 | entry = sokoke_search_entry_new (_("Search Bookmarks")); |
3287 | g_signal_connect_after (entry, "changed", |
3288 | @@ -1359,7 +3026,7 @@ |
3289 | gtk_box_pack_start (GTK_BOX (bookmarks), box, FALSE, FALSE, 5); |
3290 | |
3291 | /* Create the treeview */ |
3292 | - model = gtk_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING); |
3293 | + model = midori_bookmarks_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING); |
3294 | treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); |
3295 | gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); |
3296 | gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), 1); |
3297 | @@ -1376,19 +3043,32 @@ |
3298 | (GtkTreeCellDataFunc)midori_bookmarks_treeview_render_text_cb, |
3299 | treeview, NULL); |
3300 | gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); |
3301 | - gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE); |
3302 | + gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), FALSE); |
3303 | + gtk_tree_view_enable_model_drag_source ( |
3304 | + GTK_TREE_VIEW (treeview), |
3305 | + GDK_BUTTON1_MASK, |
3306 | + midori_bookmarks_dnd_target_entries, |
3307 | + MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES, |
3308 | + GDK_ACTION_MOVE|GDK_ACTION_LINK); |
3309 | + gtk_tree_view_enable_model_drag_dest ( |
3310 | + GTK_TREE_VIEW (treeview), |
3311 | + midori_bookmarks_dnd_target_entries, |
3312 | + MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES, |
3313 | + GDK_ACTION_MOVE|GDK_ACTION_LINK); |
3314 | g_object_unref (model); |
3315 | g_object_connect (treeview, |
3316 | "signal::row-activated", |
3317 | midori_bookmarks_row_activated_cb, bookmarks, |
3318 | + "signal::button-press-event", |
3319 | + midori_bookmarks_button_press_event_cb, bookmarks, |
3320 | "signal::button-release-event", |
3321 | midori_bookmarks_button_release_event_cb, bookmarks, |
3322 | "signal::key-release-event", |
3323 | midori_bookmarks_key_release_event_cb, bookmarks, |
3324 | "signal::popup-menu", |
3325 | midori_bookmarks_popup_menu_cb, bookmarks, |
3326 | - "signal::row-expanded", |
3327 | - midori_bookmarks_row_expanded_cb, bookmarks, |
3328 | + "signal::test-expand-row", |
3329 | + midori_bookmarks_test_expand_row_cb, bookmarks, |
3330 | "signal::row-collapsed", |
3331 | midori_bookmarks_row_collapsed_cb, bookmarks, |
3332 | "signal::enter-notify-event", |
3333 | @@ -1398,18 +3078,27 @@ |
3334 | "signal::leave-notify-event", |
3335 | midori_bookmarks_leave_notify_event_cb, bookmarks, |
3336 | NULL); |
3337 | - gtk_widget_add_events (GTK_WIDGET (treeview), |
3338 | - GDK_POINTER_MOTION_MASK |
3339 | - | GDK_POINTER_MOTION_HINT_MASK); |
3340 | + |
3341 | + MIDORI_BOOKMARKS_TREE_STORE (model)->_view = GTK_TREE_VIEW (treeview); |
3342 | + |
3343 | + gtk_widget_add_events (GTK_WIDGET (treeview), |
3344 | + GDK_POINTER_MOTION_MASK |
3345 | + | GDK_POINTER_MOTION_HINT_MASK); |
3346 | |
3347 | selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); |
3348 | + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); |
3349 | g_signal_connect_after (selection, "changed", |
3350 | - G_CALLBACK (midori_bookmarks_selection_changed_cb), |
3351 | - bookmarks); |
3352 | + G_CALLBACK (midori_bookmarks_selection_changed_cb), |
3353 | + bookmarks); |
3354 | gtk_widget_show (treeview); |
3355 | gtk_box_pack_start (GTK_BOX (bookmarks), treeview, TRUE, TRUE, 0); |
3356 | bookmarks->treeview = treeview; |
3357 | + bookmarks->pending_inserts = NULL; |
3358 | bookmarks->hovering_item = NULL; |
3359 | + bookmarks->pending_inserts = NULL; |
3360 | + bookmarks->updated_items = g_hash_table_new (item_hash, item_equal); |
3361 | + bookmarks->added_paths = NULL; |
3362 | + bookmarks->reordered_paths = NULL; |
3363 | } |
3364 | |
3365 | static void |
3366 | @@ -1420,5 +3109,16 @@ |
3367 | if (bookmarks->app) |
3368 | g_object_unref (bookmarks->app); |
3369 | if (bookmarks->hovering_item) |
3370 | - g_object_unref (bookmarks->hovering_item); |
3371 | + g_object_unref (bookmarks->hovering_item); |
3372 | + |
3373 | + if (g_idle_remove_by_data (bookmarks)) |
3374 | + { |
3375 | + g_list_free_full (bookmarks->pending_inserts, (GDestroyNotify) g_object_unref); |
3376 | + bookmarks->pending_inserts = NULL; |
3377 | + g_hash_table_unref (bookmarks->updated_items); |
3378 | + g_list_free_full (bookmarks->added_paths, (GDestroyNotify) gtk_tree_path_free); |
3379 | + bookmarks->added_paths = NULL; |
3380 | + g_list_free_full (bookmarks->reordered_paths, (GDestroyNotify) gtk_tree_path_free); |
3381 | + bookmarks->reordered_paths = NULL; |
3382 | + } |
3383 | } |
3384 | |
3385 | === modified file 'tests/bookmarks.c' |
3386 | --- tests/bookmarks.c 2013-08-05 19:52:52 +0000 |
3387 | +++ tests/bookmarks.c 2014-01-30 21:24:26 +0000 |
3388 | @@ -128,7 +128,7 @@ |
3389 | } |
3390 | |
3391 | db_items = midori_bookmarks_db_query_recursive (db_bookmarks, |
3392 | - "*", "title='%q'", katze_item_get_name (test_item), FALSE); |
3393 | + "*", "title='%q'", katze_item_get_name (test_item), NULL, FALSE); |
3394 | |
3395 | /* FIXME g_assert_cmpint (katze_array_get_length (db_items), ==, 1); */ |
3396 | db_item = katze_array_get_nth_item (db_items, 0); |
Updated with merge in of lp:~aauzi/midori/fix-1179200-9 and lp:midori.
Bookmark item positions are now properly managed in both menus and panel.
Multiple bookmark selection and drag-n-drop in the bookmark panel allow bookmark ordering.