Merge lp:~aauzi/midori/fix-1006629 into lp:midori
- fix-1006629
- Merge into trunk
Proposed by
André Auzi
Status: | Work in progress | ||||||||
---|---|---|---|---|---|---|---|---|---|
Proposed branch: | lp:~aauzi/midori/fix-1006629 | ||||||||
Merge into: | lp:midori | ||||||||
Diff against target: |
4720 lines (+3164/-334) 13 files modified
katze/katze-array.c (+53/-2) katze/katze-arrayaction.c (+270/-2) katze/katze-utils.c (+156/-3) katze/katze-utils.h (+11/-0) midori/midori-array.c (+7/-0) midori/midori-bookmarks-db.c (+106/-15) midori/midori-bookmarks-db.h (+11/-9) midori/midori-browser.c (+390/-31) midori/midori-locationaction.c (+78/-10) midori/midori-locationaction.h (+8/-0) midori/midori-view.c (+110/-1) panels/midori-bookmarks.c (+1963/-260) tests/bookmarks.c (+1/-1) |
||||||||
To merge this branch: | bzr merge lp:~aauzi/midori/fix-1006629 | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Midori Devs | Pending | ||
Review via email: mp+203255@code.launchpad.net |
Commit message
Description of the change
Coming after lp:~aauzi/midori/fix-894143, this proposes bookmark creation by Dnd from Location bar into the bookmarkbar and ordering of the bookmarkbar with Dnd.
Preliminary code for Dnd creation from tabs is deactivated. It needs rework to adapt to recent tabby evolutions.
To post a comment you must log in.
lp:~aauzi/midori/fix-1006629
updated
- 6212. By André Auzi
-
merge lp:midori
Unmerged revisions
- 6212. By André Auzi
-
merge lp:midori
- 6211. By André Auzi
-
Merge lp:~aauzi/midori/fix-894143 with pos_bar order
- 6210. By André Auzi
-
Fix bookmarkbar item position updates
- 6209. By André Auzi
-
Put traces in midori_debug ("bookmarks")
- 6208. By André Auzi
-
merge lp:midori, remove tab drag-n-drop due to tabby evolutions
- 6207. By André Auzi
-
merge lp:midori
- 6206. By André Auzi
-
connect menu button press event
- 6205. By André Auzi
-
merge lp:midori
- 6204. By André Auzi
-
fix hilight item width
- 6203. By André Auzi
-
merge lp:midori
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-26 19:44:25 +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-26 19:44:25 +0000 |
105 | @@ -29,6 +29,10 @@ |
106 | |
107 | KatzeArray* array; |
108 | gboolean reversed; |
109 | + |
110 | + GtkTargetList* dnd_targets; |
111 | + GdkEventButton *press_event; |
112 | + GdkEventButton stock_press_event; |
113 | }; |
114 | |
115 | struct _KatzeArrayActionClass |
116 | @@ -43,7 +47,8 @@ |
117 | PROP_0, |
118 | |
119 | PROP_ARRAY, |
120 | - PROP_REVERSED |
121 | + PROP_REVERSED, |
122 | + PROP_DND_TARGETS |
123 | }; |
124 | |
125 | enum |
126 | @@ -215,6 +220,20 @@ |
127 | "Whether the array should be walked backwards when building menus", |
128 | FALSE, |
129 | G_PARAM_READWRITE)); |
130 | + /** |
131 | + * KatzeArrayAction:dnd-targets: |
132 | + * |
133 | + * GtkTargetList* the array supports. |
134 | + * |
135 | + * Since: 0.5.2 |
136 | + **/ |
137 | + g_object_class_install_property (gobject_class, |
138 | + PROP_DND_TARGETS, |
139 | + g_param_spec_pointer ( |
140 | + "dnd-targets", |
141 | + "DNDTargets", |
142 | + "GtkTargetList* the array supports", |
143 | + G_PARAM_READABLE|G_PARAM_WRITABLE)); |
144 | } |
145 | |
146 | static void |
147 | @@ -222,6 +241,8 @@ |
148 | { |
149 | array_action->array = NULL; |
150 | array_action->reversed = FALSE; |
151 | + array_action->dnd_targets = NULL; |
152 | + array_action->press_event = NULL; |
153 | } |
154 | |
155 | static void |
156 | @@ -229,6 +250,9 @@ |
157 | { |
158 | KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object); |
159 | |
160 | + if (array_action->dnd_targets) |
161 | + gtk_target_list_unref (array_action->dnd_targets); |
162 | + |
163 | katze_object_assign (array_action->array, NULL); |
164 | |
165 | G_OBJECT_CLASS (katze_array_action_parent_class)->finalize (object); |
166 | @@ -250,6 +274,9 @@ |
167 | case PROP_REVERSED: |
168 | array_action->reversed = g_value_get_boolean (value); |
169 | break; |
170 | + case PROP_DND_TARGETS: |
171 | + array_action->dnd_targets = (GtkTargetList*)g_value_get_pointer (value); |
172 | + break; |
173 | default: |
174 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
175 | break; |
176 | @@ -272,6 +299,9 @@ |
177 | case PROP_REVERSED: |
178 | g_value_set_boolean (value, array_action->reversed); |
179 | break; |
180 | + case PROP_DND_TARGETS: |
181 | + g_value_set_pointer (value, array_action->dnd_targets); |
182 | + break; |
183 | default: |
184 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
185 | break; |
186 | @@ -310,8 +340,29 @@ |
187 | GdkEventButton* event, |
188 | KatzeArrayAction* array_action) |
189 | { |
190 | + array_action->stock_press_event = *event; |
191 | + array_action->press_event = &array_action->stock_press_event; |
192 | + |
193 | + return FALSE; |
194 | +} |
195 | + |
196 | +static gboolean |
197 | +katze_array_action_menu_button_release_cb (GtkWidget* proxy, |
198 | + GdkEventButton* event, |
199 | + KatzeArrayAction* array_action) |
200 | +{ |
201 | KatzeItem* item = g_object_get_data (G_OBJECT (proxy), "KatzeItem"); |
202 | |
203 | + if (array_action->press_event) |
204 | + { |
205 | + gint x = array_action->press_event->x; |
206 | + gint y = array_action->press_event->y; |
207 | + array_action->press_event = NULL; |
208 | + |
209 | + if (x != event->x || y != event->y) |
210 | + return TRUE; |
211 | + } |
212 | + |
213 | katze_array_action_activate_item (array_action, item, event->button); |
214 | |
215 | /* we need to block the 'activate' handler which would be called |
216 | @@ -323,6 +374,120 @@ |
217 | } |
218 | |
219 | static void |
220 | +katze_array_action_item_drag_source_drag_data_get ( |
221 | + KatzeItem *item, |
222 | + GdkDragContext *drag_context, |
223 | + GtkSelectionData *data, |
224 | + guint info, |
225 | + guint time, |
226 | + KatzeArrayAction* action) |
227 | +{ |
228 | + g_return_if_fail (KATZE_IS_ITEM (item)); |
229 | + |
230 | + switch (gdk_drag_context_get_selected_action (drag_context)) |
231 | + { |
232 | + default: |
233 | + break; |
234 | + case GDK_ACTION_MOVE: |
235 | + case GDK_ACTION_COPY: |
236 | + if (selection_data_from_katze_item (data, item)) |
237 | + break; |
238 | + case GDK_ACTION_LINK: |
239 | + if (KATZE_ITEM_IS_BOOKMARK (item)) |
240 | + { |
241 | + const gchar* uri = katze_item_get_uri (item); |
242 | + if (uri && *uri) |
243 | + { |
244 | + gchar* src_uris[2]; |
245 | + gchar** uris; |
246 | + |
247 | + src_uris[0] = (gchar*)uri; |
248 | + src_uris[1] = NULL; |
249 | + |
250 | + uris = g_strdupv (src_uris); |
251 | + |
252 | + gtk_selection_data_set_uris (data, uris); |
253 | + gtk_selection_data_set_text (data, uri, -1); |
254 | + |
255 | + g_strfreev (uris); |
256 | + } |
257 | + } |
258 | + break; |
259 | + } |
260 | +} |
261 | + |
262 | +static void |
263 | +katze_array_action_menu_item_drag_source_drag_data_get_cb ( |
264 | + GtkWidget *widget, |
265 | + GdkDragContext *drag_context, |
266 | + GtkSelectionData *data, |
267 | + guint info, |
268 | + guint time, |
269 | + KatzeArrayAction* action) |
270 | +{ |
271 | + KatzeItem* item = (KatzeItem*)g_object_get_data (G_OBJECT (widget), "KatzeItem"); |
272 | + |
273 | + katze_array_action_item_drag_source_drag_data_get (item, drag_context, data, info, time, action); |
274 | +} |
275 | + |
276 | +static void |
277 | +katze_array_action_tool_item_child_drag_source_drag_data_get_cb ( |
278 | + GtkWidget *widget, |
279 | + GdkDragContext *drag_context, |
280 | + GtkSelectionData *data, |
281 | + guint info, |
282 | + guint time, |
283 | + KatzeArrayAction *action) |
284 | +{ |
285 | + GtkWidget* proxy = gtk_widget_get_parent (widget); |
286 | + KatzeItem* item = (KatzeItem*)g_object_get_data (G_OBJECT (proxy), "KatzeItem"); |
287 | + GtkToolbar* toolbar = GTK_TOOLBAR (gtk_widget_get_parent (proxy)); |
288 | + gint pos; |
289 | + |
290 | + g_return_if_fail (KATZE_IS_ITEM (item)); |
291 | + |
292 | + pos = gtk_toolbar_get_item_index (toolbar, GTK_TOOL_ITEM (proxy)); |
293 | + if (pos != katze_item_get_meta_integer (item, "pos_bar")) |
294 | + katze_item_set_meta_integer (item, "pos_bar", pos); |
295 | + |
296 | + katze_array_action_item_drag_source_drag_data_get (item, drag_context, data, info, time, action); |
297 | +} |
298 | + |
299 | +extern void midori_bookmarkbar_position_items (GtkWidget *widget); |
300 | + |
301 | + |
302 | +static void |
303 | +katze_array_action_tool_item_child_drag_source_drag_data_delete_cb ( |
304 | + GtkWidget *widget, |
305 | + GdkDragContext *drag_context, |
306 | + KatzeArrayAction* action) |
307 | +{ |
308 | + GtkWidget* proxy = gtk_widget_get_parent (widget); |
309 | + KatzeItem* item = (KatzeItem*)g_object_get_data (G_OBJECT (proxy), "KatzeItem"); |
310 | + GtkToolbar* toolbar = GTK_TOOLBAR (gtk_widget_get_parent (proxy)); |
311 | + |
312 | + g_return_if_fail (KATZE_IS_ITEM (item)); |
313 | + |
314 | + gtk_container_remove (GTK_CONTAINER (toolbar), proxy); |
315 | + |
316 | + midori_bookmarkbar_position_items (GTK_WIDGET (toolbar)); |
317 | +} |
318 | + |
319 | +static void |
320 | +katze_array_action_menu_item_drag_source_drag_data_delete_cb ( |
321 | + GtkWidget *proxy, |
322 | + GdkDragContext *drag_context, |
323 | + KatzeArrayAction* action) |
324 | +{ |
325 | + KatzeItem* item = (KatzeItem*)g_object_get_data (G_OBJECT (proxy), "KatzeItem"); |
326 | + GtkMenuShell* menu = GTK_MENU_SHELL (gtk_widget_get_parent (proxy)); |
327 | + |
328 | + g_return_if_fail (KATZE_IS_ITEM (item)); |
329 | + |
330 | + gtk_container_remove (GTK_CONTAINER (menu), proxy); |
331 | +} |
332 | + |
333 | +static void |
334 | katze_array_action_menu_item_select_cb (GtkWidget* proxy, |
335 | KatzeArrayAction* array_action); |
336 | |
337 | @@ -407,6 +572,24 @@ |
338 | G_CALLBACK (katze_array_action_menu_item_select_cb), array_action); |
339 | g_signal_connect (menuitem, "activate", |
340 | G_CALLBACK (katze_array_action_menu_item_select_cb), array_action); |
341 | +#if 0 |
342 | + /* TODO: insert menu DND dest code here */ |
343 | + if (array_action->dnd_targets) |
344 | + { |
345 | + gtk_drag_dest_set (submenu, GTK_DEST_DEFAULT_ALL, NULL, 0, |
346 | + GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_LINK); |
347 | + gtk_drag_dest_set_target_list (submenu, array_action->dnd_targets); |
348 | + g_signal_connect (submenu, "drag-motion", |
349 | + G_CALLBACK (katze_array_action_menu_drag_dest_drag_motion_cb), |
350 | + array_action); |
351 | + g_signal_connect (submenu, "drag-leave", |
352 | + G_CALLBACK (katze_array_action_menu_drag_dest_drag_leave_cb), |
353 | + array_action); |
354 | + g_signal_connect (submenu, "drag-data-received", |
355 | + G_CALLBACK (katze_array_action_menu_drag_dest_drag_data_received_cb), |
356 | + array_action); |
357 | + } |
358 | +#endif |
359 | } |
360 | else |
361 | { |
362 | @@ -416,6 +599,23 @@ |
363 | } |
364 | g_signal_connect (menuitem, "button-press-event", |
365 | G_CALLBACK (katze_array_action_menu_button_press_cb), array_action); |
366 | + g_signal_connect (menuitem, "button-release-event", |
367 | + G_CALLBACK (katze_array_action_menu_button_release_cb), array_action); |
368 | + |
369 | + |
370 | + if (array_action->dnd_targets) |
371 | + { |
372 | + gtk_drag_source_set (menuitem, GDK_BUTTON1_MASK, NULL, 0, |
373 | + GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_LINK); |
374 | + gtk_drag_source_set_target_list (menuitem, array_action->dnd_targets); |
375 | + g_signal_connect (menuitem, "drag-data-get", |
376 | + G_CALLBACK (katze_array_action_menu_item_drag_source_drag_data_get_cb), |
377 | + array_action); |
378 | + g_signal_connect (menuitem, "drag-data-delete", |
379 | + G_CALLBACK (katze_array_action_menu_item_drag_source_drag_data_delete_cb), |
380 | + array_action); |
381 | + } |
382 | + |
383 | gtk_widget_show (menuitem); |
384 | } |
385 | } |
386 | @@ -622,15 +822,49 @@ |
387 | gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu); |
388 | g_signal_connect (menuitem, "select", |
389 | G_CALLBACK (katze_array_action_menu_item_select_cb), array_action); |
390 | +#if 0 |
391 | + /* TODO: insert menu DND menu code here */ |
392 | + if (array_action->dnd_targets) |
393 | + { |
394 | + gtk_drag_dest_set (submenu, GTK_DEST_DEFAULT_ALL, NULL, 0, |
395 | + GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_LINK); |
396 | + gtk_drag_dest_set_target_list (submenu, array_action->dnd_targets); |
397 | + g_signal_connect (submenu, "drag-motion", |
398 | + G_CALLBACK (katze_array_action_menu_drag_dest_drag_motion_cb), |
399 | + array_action); |
400 | + g_signal_connect (submenu, "drag-leave", |
401 | + G_CALLBACK (katze_array_action_menu_drag_dest_drag_leave_cb), |
402 | + array_action); |
403 | + g_signal_connect (submenu, "drag-data-received", |
404 | + G_CALLBACK (katze_array_action_menu_drag_dest_drag_data_received_cb), |
405 | + array_action); |
406 | + } |
407 | +#endif |
408 | } |
409 | else |
410 | { |
411 | g_signal_connect (menuitem, "button-press-event", |
412 | G_CALLBACK (katze_array_action_menu_button_press_cb), array_action); |
413 | + g_signal_connect (menuitem, "button-release-event", |
414 | + G_CALLBACK (katze_array_action_menu_button_release_cb), array_action); |
415 | /* we need the 'activate' signal as well for keyboard events */ |
416 | g_signal_connect (menuitem, "activate", |
417 | G_CALLBACK (katze_array_action_menu_activate_cb), array_action); |
418 | } |
419 | + |
420 | + if (array_action->dnd_targets) |
421 | + { |
422 | + gtk_drag_source_set (menuitem, GDK_BUTTON1_MASK, NULL, 0, |
423 | + GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_LINK); |
424 | + gtk_drag_source_set_target_list (menuitem, array_action->dnd_targets); |
425 | + g_signal_connect (menuitem, "drag-data-get", |
426 | + G_CALLBACK (katze_array_action_menu_item_drag_source_drag_data_get_cb), |
427 | + array_action); |
428 | + g_signal_connect (menuitem, "drag-data-delete", |
429 | + G_CALLBACK (katze_array_action_menu_item_drag_source_drag_data_delete_cb), |
430 | + array_action); |
431 | + } |
432 | + |
433 | gtk_tool_item_set_proxy_menu_item (GTK_TOOL_ITEM (proxy), |
434 | "katze-tool-item-menu", menuitem); |
435 | return TRUE; |
436 | @@ -706,9 +940,33 @@ |
437 | else |
438 | gtk_tool_item_set_tooltip_text (toolitem, uri); |
439 | |
440 | - g_object_set_data (G_OBJECT (toolitem), "KatzeArray", item); |
441 | + g_object_set_data (G_OBJECT (toolitem), "KatzeItem", item); |
442 | g_signal_connect (toolitem, "clicked", |
443 | G_CALLBACK (katze_array_action_proxy_clicked_cb), array_action); |
444 | + if (KATZE_IS_ITEM (item)) |
445 | + { |
446 | + GtkWidget* child = gtk_bin_get_child (GTK_BIN (toolitem)); |
447 | + |
448 | + if (KATZE_ITEM_IS_FOLDER (item) && array_action->dnd_targets) |
449 | + { |
450 | +#if 0 |
451 | + /* TODO: add toggle button DND dest code here */ |
452 | +#endif |
453 | + } |
454 | + |
455 | + if (array_action->dnd_targets) |
456 | + { |
457 | + gtk_drag_source_set (child, GDK_BUTTON1_MASK, NULL, 0, |
458 | + GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_LINK); |
459 | + gtk_drag_source_set_target_list (child, array_action->dnd_targets); |
460 | + g_signal_connect (child, "drag-data-get", |
461 | + G_CALLBACK (katze_array_action_tool_item_child_drag_source_drag_data_get_cb), |
462 | + array_action); |
463 | + g_signal_connect (child, "drag-data-delete", |
464 | + G_CALLBACK (katze_array_action_tool_item_child_drag_source_drag_data_delete_cb), |
465 | + array_action); |
466 | + } |
467 | + } |
468 | |
469 | g_object_set_data (G_OBJECT (toolitem), "KatzeArrayAction", array_action); |
470 | g_signal_connect (item, "notify", |
471 | @@ -767,12 +1025,14 @@ |
472 | KatzeArray* array) |
473 | { |
474 | GSList* proxies; |
475 | + KatzeArray *old_array = NULL; |
476 | |
477 | g_return_if_fail (KATZE_IS_ARRAY_ACTION (array_action)); |
478 | g_return_if_fail (!array || katze_array_is_a (array, KATZE_TYPE_ITEM)); |
479 | |
480 | /* FIXME: Disconnect old array */ |
481 | |
482 | + old_array = array_action->array; |
483 | if (array) |
484 | g_object_ref (array); |
485 | katze_object_assign (array_action->array, array); |
486 | @@ -793,7 +1053,15 @@ |
487 | |
488 | do |
489 | { |
490 | + KatzeArray* item = g_object_get_data (G_OBJECT (proxies->data), "KatzeItem"); |
491 | + |
492 | + if (item && (item == old_array)) |
493 | + g_object_set_data (G_OBJECT (proxies->data), "KatzeItem", array); |
494 | + |
495 | gtk_widget_set_sensitive (proxies->data, array != NULL); |
496 | } |
497 | while ((proxies = g_slist_next (proxies))); |
498 | + |
499 | + if (array) |
500 | + katze_array_update (KATZE_ARRAY (array)); |
501 | } |
502 | |
503 | === modified file 'katze/katze-utils.c' |
504 | --- katze/katze-utils.c 2013-11-05 21:51:18 +0000 |
505 | +++ katze/katze-utils.c 2014-01-26 19:44:25 +0000 |
506 | @@ -29,6 +29,13 @@ |
507 | #include <unistd.h> |
508 | #endif |
509 | |
510 | +typedef struct _KatzeArrayData KatzeArrayData; |
511 | + |
512 | +struct _KatzeArrayData |
513 | +{ |
514 | + KatzeItem* items[1]; |
515 | +}; |
516 | + |
517 | #define I_ g_intern_static_string |
518 | |
519 | static void |
520 | @@ -1002,12 +1009,99 @@ |
521 | |
522 | g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE); |
523 | |
524 | - if ((selection = gtk_tree_view_get_selection (treeview))) |
525 | - if (gtk_tree_selection_get_selected (selection, model, iter)) |
526 | - return TRUE; |
527 | + selection = gtk_tree_view_get_selection(treeview); |
528 | + |
529 | + switch (gtk_tree_selection_get_mode (selection)) |
530 | + { |
531 | + default: |
532 | + break; |
533 | + |
534 | + case GTK_SELECTION_SINGLE: |
535 | + case GTK_SELECTION_BROWSE: |
536 | + if (gtk_tree_selection_get_selected (selection, model, iter)) |
537 | + return TRUE; |
538 | + break; |
539 | + |
540 | + case GTK_SELECTION_MULTIPLE: |
541 | + if (gtk_tree_selection_count_selected_rows (selection) == 1) |
542 | + { |
543 | + GtkTreeModel *stock_model; |
544 | + GList *list = gtk_tree_selection_get_selected_rows (selection, &stock_model); |
545 | + |
546 | + if (model) |
547 | + *model = stock_model; |
548 | + |
549 | + if (list) |
550 | + { |
551 | + GtkTreePath *path = (GtkTreePath *)g_list_nth_data (list, 0); |
552 | + |
553 | + if (path && (!iter || gtk_tree_model_get_iter (stock_model, iter, path))) |
554 | + { |
555 | + g_list_free_full(list, (GDestroyNotify) gtk_tree_path_free); |
556 | + return TRUE; |
557 | + } |
558 | + |
559 | + g_list_free_full(list, (GDestroyNotify) gtk_tree_path_free); |
560 | + } |
561 | + } |
562 | + } |
563 | + |
564 | return FALSE; |
565 | } |
566 | |
567 | +/** |
568 | + * katze_tree_view_get_selected_rows: |
569 | + * @treeview: a #GtkTreeView |
570 | + * @model: a pointer to store the #GtkTreeModel, or %NULL |
571 | + * @rows: a pointer to store the #GList of #GtkTreePath, or %NULL |
572 | + * |
573 | + * Determines whether there is a selection in @treeview |
574 | + * and sets the @rows to the current selection. |
575 | + * |
576 | + * If there is a selection and @model is not %NULL, it is |
577 | + * set to the model. If @model is %NULL, the @rows will be |
578 | + * set to %NULL. |
579 | + * |
580 | + * Either @model or @rows or both can be %NULL in which case |
581 | + * no value will be assigned in any case. |
582 | + * |
583 | + * When @rows is not %NULL it must be freed using: |
584 | + * g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); |
585 | + * |
586 | + * Return value: the count of selected rows |
587 | + * |
588 | + * Since: 0.4.7.aau.1 |
589 | + **/ |
590 | + |
591 | +gint |
592 | +katze_tree_view_get_selected_rows (GtkTreeView* treeview, |
593 | + GtkTreeModel** model, |
594 | + GList** rows) |
595 | +{ |
596 | + gint count; |
597 | + GtkTreeSelection* selection; |
598 | + |
599 | + if (model) |
600 | + *model = NULL; |
601 | + if (rows) |
602 | + *rows = NULL; |
603 | + |
604 | + g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), 0); |
605 | + |
606 | + selection = gtk_tree_view_get_selection(treeview); |
607 | + |
608 | + count = gtk_tree_selection_count_selected_rows (selection); |
609 | + if (count > 0) |
610 | + { |
611 | + if (model && rows) |
612 | + { |
613 | + *rows = gtk_tree_selection_get_selected_rows (selection, model); |
614 | + } |
615 | + } |
616 | + |
617 | + return count; |
618 | +} |
619 | + |
620 | void |
621 | katze_bookmark_populate_tree_view (KatzeArray* array, |
622 | GtkTreeStore* model, |
623 | @@ -1377,3 +1471,62 @@ |
624 | gtk_widget_set_size_request (GTK_WIDGET (window), 700, 100); |
625 | } |
626 | |
627 | +gboolean |
628 | +selection_data_from_katze_item (GtkSelectionData* selection_data, KatzeItem* item) |
629 | +{ |
630 | + GdkAtom katze_array_atom = gdk_atom_intern_static_string ("KATZE_ARRAY"); |
631 | + KatzeArrayData *kad; |
632 | + |
633 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
634 | + g_return_val_if_fail (KATZE_IS_ITEM (item), FALSE); |
635 | + |
636 | + if (gtk_selection_data_get_target (selection_data) != katze_array_atom) |
637 | + return FALSE; |
638 | + |
639 | + kad = g_malloc (sizeof (KatzeArrayData)); |
640 | + |
641 | + kad->items[0] = item; |
642 | + |
643 | + gtk_selection_data_set (selection_data, |
644 | + katze_array_atom, |
645 | + 8, /* bytes */ |
646 | + (void*)kad, |
647 | + sizeof (KatzeArrayData)); |
648 | + |
649 | + g_free (kad); |
650 | + return TRUE; |
651 | +} |
652 | + |
653 | +KatzeArray* |
654 | +katze_array_from_selection_data (GtkSelectionData* selection_data) |
655 | +{ |
656 | + GdkAtom katze_array_atom = gdk_atom_intern_static_string ("KATZE_ARRAY"); |
657 | + KatzeArrayData *kad; |
658 | + KatzeArray *array; |
659 | + gint size; |
660 | + gint count; |
661 | + gint i; |
662 | + |
663 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
664 | + |
665 | + if (gtk_selection_data_get_target (selection_data) != katze_array_atom) |
666 | + return NULL; |
667 | + |
668 | + if (gtk_selection_data_get_format (selection_data) != 8) |
669 | + return NULL; |
670 | + |
671 | + size = gtk_selection_data_get_length (selection_data); |
672 | + if (size <= 0) |
673 | + return NULL; |
674 | + |
675 | + kad = (void*) gtk_selection_data_get_data (selection_data); |
676 | + |
677 | + count = (size - G_STRUCT_OFFSET (KatzeArrayData, items))/sizeof(KatzeItem*); |
678 | + |
679 | + array = katze_array_new (KATZE_TYPE_ARRAY); |
680 | + |
681 | + for ( i = 0; i < count; i++ ) |
682 | + katze_array_add_item (array, kad->items[i]); |
683 | + |
684 | + return array; |
685 | +} |
686 | |
687 | === modified file 'katze/katze-utils.h' |
688 | --- katze/katze-utils.h 2013-04-16 22:10:56 +0000 |
689 | +++ katze/katze-utils.h 2014-01-26 19:44:25 +0000 |
690 | @@ -88,6 +88,11 @@ |
691 | GtkTreeModel** model, |
692 | GtkTreeIter* iter); |
693 | |
694 | +gint |
695 | +katze_tree_view_get_selected_rows (GtkTreeView* treeview, |
696 | + GtkTreeModel** model, |
697 | + GList** rows); |
698 | + |
699 | void |
700 | katze_bookmark_populate_tree_view (KatzeArray* array, |
701 | GtkTreeStore* model, |
702 | @@ -138,6 +143,12 @@ |
703 | void |
704 | katze_window_set_sensible_default_size (GtkWindow* window); |
705 | |
706 | +gboolean |
707 | +selection_data_from_katze_item (GtkSelectionData* selection_data, KatzeItem* item); |
708 | + |
709 | +KatzeArray* |
710 | +katze_array_from_selection_data (GtkSelectionData* selection_data); |
711 | + |
712 | G_END_DECLS |
713 | |
714 | #endif /* __KATZE_UTILS_H__ */ |
715 | |
716 | === modified file 'midori/midori-array.c' |
717 | --- midori/midori-array.c 2013-08-05 19:52:52 +0000 |
718 | +++ midori/midori-array.c 2014-01-26 19:44:25 +0000 |
719 | @@ -1031,9 +1031,16 @@ |
720 | || g_str_equal (name, "last_visit") || g_str_equal (name, "visit_count") |
721 | || g_str_equal (name, "pos_panel") || g_str_equal (name, "pos_bar")) |
722 | { |
723 | +#if 0 |
724 | gint value; |
725 | value = sqlite3_column_int64 (stmt, column); |
726 | katze_item_set_meta_integer (item, name, value); |
727 | +#else |
728 | + /* use text to properly handle NULL values */ |
729 | + const unsigned char* text; |
730 | + text = sqlite3_column_text (stmt, column); |
731 | + katze_item_set_meta_string (item, name, (gchar*)text); |
732 | +#endif |
733 | } |
734 | else if (g_str_equal (name, "desc")) |
735 | { |
736 | |
737 | === modified file 'midori/midori-bookmarks-db.c' |
738 | --- midori/midori-bookmarks-db.c 2014-01-24 23:04:05 +0000 |
739 | +++ midori/midori-bookmarks-db.c 2014-01-26 19:44:25 +0000 |
740 | @@ -181,14 +181,29 @@ |
741 | midori_bookmarks_db_get_item_parent (MidoriBookmarksDb* bookmarks, |
742 | gpointer item) |
743 | { |
744 | + gint64 parentid = katze_item_get_meta_integer (KATZE_ITEM (item), "parentid"); |
745 | + KatzeItem *search = katze_item_new (); |
746 | KatzeArray* parent; |
747 | - gint64 parentid; |
748 | - |
749 | - parentid = katze_item_get_meta_integer (KATZE_ITEM (item), "parentid"); |
750 | - |
751 | - if (parentid == 0) |
752 | - { |
753 | + |
754 | + if (!parentid) |
755 | + { |
756 | + parentid = katze_item_get_meta_integer (KATZE_ITEM (bookmarks), "id"); |
757 | + katze_item_set_meta_integer (KATZE_ITEM (item), "parentid", parentid); |
758 | + } |
759 | + |
760 | + katze_item_set_meta_integer(search, "id", parentid); |
761 | + |
762 | + parent = KATZE_ARRAY (g_hash_table_lookup (bookmarks->all_items, search)); |
763 | + |
764 | + g_object_unref (search); |
765 | + |
766 | + if (!parent) |
767 | + { |
768 | + g_warning ("item parent not found\n"); |
769 | + |
770 | parent = KATZE_ARRAY (bookmarks); |
771 | + katze_item_set_meta_integer (KATZE_ITEM (item), "parentid", |
772 | + katze_item_get_meta_integer (KATZE_ITEM (bookmarks), "id")); |
773 | } |
774 | else |
775 | { |
776 | @@ -267,7 +282,10 @@ |
777 | |
778 | g_return_if_fail (parent); |
779 | |
780 | - katze_array_update (parent); |
781 | + if (IS_MIDORI_BOOKMARKS_DB (parent)) |
782 | + KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->update (parent); |
783 | + else |
784 | + katze_array_update (parent); |
785 | } |
786 | |
787 | /** |
788 | @@ -479,7 +497,7 @@ |
789 | else if (old_parent && katze_item_get_meta_integer (old_parent, "id") > 0) |
790 | new_parentid = g_strdup_printf ("%" G_GINT64_FORMAT, katze_item_get_meta_integer (old_parent, "id")); |
791 | else |
792 | - new_parentid = g_strdup_printf ("NULL"); |
793 | + new_parentid = g_strdup ("NULL"); |
794 | |
795 | sqlcmd = sqlite3_mprintf ( |
796 | "INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) " |
797 | @@ -557,7 +575,8 @@ |
798 | |
799 | sqlcmd = sqlite3_mprintf ( |
800 | "UPDATE bookmarks SET " |
801 | - "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d " |
802 | + "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d, " |
803 | + "pos_bar=%d, pos_panel=%d " |
804 | "WHERE id = %q ;", |
805 | parentid, |
806 | katze_item_get_name (item), |
807 | @@ -565,6 +584,8 @@ |
808 | katze_str_non_null (katze_item_get_meta_string (item, "desc")), |
809 | katze_item_get_meta_boolean (item, "toolbar"), |
810 | katze_item_get_meta_boolean (item, "app"), |
811 | + (gint)katze_item_get_meta_integer (item, "pos_bar"), |
812 | + (gint)katze_item_get_meta_integer (item, "pos_panel"), |
813 | id); |
814 | |
815 | updated = TRUE; |
816 | @@ -579,6 +600,14 @@ |
817 | g_free (parentid); |
818 | g_free (id); |
819 | |
820 | +#ifdef DEBUG_DB_UPDATE |
821 | + g_print ("update:%s - parentid: %s, pos_bar:%d, pos_panel:%d\n", |
822 | + katze_item_get_name (item), |
823 | + parentid, |
824 | + (gint)katze_item_get_meta_integer (item, "pos_bar"), |
825 | + (gint)katze_item_get_meta_integer (item, "pos_panel")); |
826 | +#endif |
827 | + |
828 | return updated; |
829 | } |
830 | |
831 | @@ -710,10 +739,10 @@ |
832 | g_return_val_if_fail (errmsg != NULL, NULL); |
833 | |
834 | database = midori_bookmarks_database_new (&error); |
835 | - |
836 | + |
837 | if (error != NULL) |
838 | { |
839 | - *errmsg = g_strdup (error->message); |
840 | + *errmsg = g_strdup (error->message); |
841 | g_error_free (error); |
842 | return NULL; |
843 | } |
844 | @@ -724,7 +753,10 @@ |
845 | if (midori_debug ("bookmarks")) |
846 | sqlite3_trace (db, midori_bookmarks_db_dbtracer, NULL); |
847 | |
848 | - bookmarks = MIDORI_BOOKMARKS_DB (g_object_new (TYPE_MIDORI_BOOKMARKS_DB, NULL)); |
849 | + bookmarks = MIDORI_BOOKMARKS_DB (g_object_new (TYPE_MIDORI_BOOKMARKS_DB, |
850 | + "type", KATZE_TYPE_ITEM, |
851 | + NULL)); |
852 | + |
853 | bookmarks->db = db; |
854 | |
855 | g_object_set_data (G_OBJECT (bookmarks), "db", db); |
856 | @@ -776,6 +808,7 @@ |
857 | katze_item_set_meta_integer (item, "parentid", parentid); |
858 | midori_bookmarks_db_add_item (bookmarks, item); |
859 | } |
860 | + |
861 | g_list_free (list); |
862 | } |
863 | |
864 | @@ -859,7 +892,7 @@ |
865 | * @array: the main bookmark array |
866 | * @sqlcmd: the sqlcmd to execute |
867 | * |
868 | - * Internal function that process the requested @sqlcmd. |
869 | + * Internal function that processes the requested @sqlcmd. |
870 | * |
871 | * Return value: a #KatzeArray on success, %NULL otherwise |
872 | **/ |
873 | @@ -885,6 +918,10 @@ |
874 | * @fields: comma separated list of fields |
875 | * @condition: condition, like "folder = '%q'" |
876 | * @value: a value to be inserted if @condition contains %q |
877 | + * @order: a value to be inserted in "ORDER BY" |
878 | + * default order is : |
879 | + * (uri='') ASC, title DESC |
880 | + * given @order, when not %NULL, replaces the term: (uri='') ASC |
881 | * @recursive: if %TRUE include children |
882 | * |
883 | * Stores the result in a #KatzeArray. |
884 | @@ -898,6 +935,7 @@ |
885 | const gchar* fields, |
886 | const gchar* condition, |
887 | const gchar* value, |
888 | + const gchar* order, |
889 | gboolean recursive) |
890 | { |
891 | gchar* sqlcmd; |
892 | @@ -911,7 +949,8 @@ |
893 | g_return_val_if_fail (condition, NULL); |
894 | |
895 | sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s " |
896 | - "ORDER BY (uri='') ASC, title DESC", fields, condition); |
897 | + "ORDER BY %s, title DESC", fields, condition, order ? order : "(uri='') ASC"); |
898 | + |
899 | if (strstr (condition, "%q")) |
900 | { |
901 | sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : ""); |
902 | @@ -932,7 +971,7 @@ |
903 | gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT, |
904 | katze_item_get_meta_integer (item, "id")); |
905 | KatzeArray* subarray = midori_bookmarks_db_query_recursive (bookmarks, |
906 | - fields, "parentid=%q", parentid, TRUE); |
907 | + fields, "parentid=%q", parentid, order, TRUE); |
908 | KatzeItem* subitem; |
909 | GList* sublist; |
910 | |
911 | @@ -1097,3 +1136,55 @@ |
912 | value, id, |
913 | recursive); |
914 | } |
915 | + |
916 | +/** |
917 | + * midori_bookmarks_db_populate_folder: |
918 | + **/ |
919 | + |
920 | +void |
921 | +midori_bookmarks_db_populate_folder (MidoriBookmarksDb* bookmarks, |
922 | + KatzeArray *folder) |
923 | +{ |
924 | + const gchar* id = katze_item_get_meta_string (KATZE_ITEM (folder), "id"); |
925 | + const gchar *condition; |
926 | + KatzeArray* array; |
927 | + KatzeItem* item; |
928 | + GList* list; |
929 | + |
930 | + if (id == NULL) |
931 | + { |
932 | + condition = "parentid is NULL"; |
933 | + } |
934 | + else |
935 | + { |
936 | + condition = "parentid = %q"; |
937 | + } |
938 | + |
939 | + array = midori_bookmarks_db_query_recursive (bookmarks, |
940 | + "id, title, parentid, uri, app, pos_panel, pos_bar", condition, id, "(uri='') ASC, pos_panel ASC", FALSE); |
941 | + |
942 | + if (IS_MIDORI_BOOKMARKS_DB (folder)) |
943 | + { |
944 | + KATZE_ARRAY_FOREACH_ITEM_L (item, folder, list) |
945 | + { |
946 | + KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->remove_item (folder, item); |
947 | + } |
948 | + |
949 | + KATZE_ARRAY_FOREACH_ITEM_L (item, array, list) |
950 | + { |
951 | + KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->add_item (folder, item); |
952 | + } |
953 | + } |
954 | + else |
955 | + { |
956 | + katze_array_clear(folder); |
957 | + |
958 | + KATZE_ARRAY_FOREACH_ITEM_L (item, array, list) |
959 | + { |
960 | + katze_array_add_item (folder, item); |
961 | + } |
962 | + } |
963 | + |
964 | + g_object_unref (array); |
965 | +} |
966 | + |
967 | |
968 | === modified file 'midori/midori-bookmarks-db.h' |
969 | --- midori/midori-bookmarks-db.h 2013-09-17 19:34:23 +0000 |
970 | +++ midori/midori-bookmarks-db.h 2014-01-26 19:44:25 +0000 |
971 | @@ -62,19 +62,21 @@ |
972 | const gchar* fields, |
973 | const gchar* condition, |
974 | const gchar* value, |
975 | + const gchar* order, |
976 | gboolean recursive); |
977 | |
978 | gint64 |
979 | midori_bookmarks_db_count_recursive (MidoriBookmarksDb* bookmarks, |
980 | - const gchar* condition, |
981 | + const gchar* condition, |
982 | const gchar* value, |
983 | - KatzeItem* folder, |
984 | - gboolean recursive); |
985 | - |
986 | -gint64 |
987 | -midori_bookmarks_insert_item_db (sqlite3* db, |
988 | - KatzeItem* item, |
989 | - gint64 parentid); |
990 | + KatzeItem* folder, |
991 | + gboolean recursive); |
992 | + |
993 | +void |
994 | +midori_bookmarks_db_on_quit (MidoriBookmarksDb* array); |
995 | + |
996 | +void |
997 | +midori_bookmarks_db_populate_folder (MidoriBookmarksDb* bookmarks, |
998 | + KatzeArray *folder); |
999 | |
1000 | #endif /* !__MIDORI_BOOKMARKS_DB_H__ */ |
1001 | - |
1002 | |
1003 | === modified file 'midori/midori-browser.c' |
1004 | --- midori/midori-browser.c 2014-01-06 23:05:10 +0000 |
1005 | +++ midori/midori-browser.c 2014-01-26 19:44:25 +0000 |
1006 | @@ -99,9 +99,24 @@ |
1007 | guint maximum_history_age; |
1008 | guint last_web_search; |
1009 | |
1010 | + struct _BookmarkbarDNDControl |
1011 | + { |
1012 | + GtkTargetList* source_targets; |
1013 | + GtkTargetList* dest_targets; |
1014 | + |
1015 | + struct _BookmarkbarDragDestControl |
1016 | + { |
1017 | + GtkToolItem* highligth_item; |
1018 | + gboolean hovering; |
1019 | + int n; |
1020 | + } drag_dest_control; |
1021 | + } bookmarkbar_dnd_control; |
1022 | gboolean bookmarkbar_populate; |
1023 | }; |
1024 | |
1025 | +typedef struct _BookmarkbarDNDControl BookmarkbarDNDControl; |
1026 | +typedef struct _BookmarkbarDragDestControl BookmarkbarDragDestControl; |
1027 | + |
1028 | G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW) |
1029 | |
1030 | enum |
1031 | @@ -173,11 +188,22 @@ |
1032 | midori_bookmarkbar_populate (MidoriBrowser* browser); |
1033 | static void |
1034 | midori_bookmarkbar_populate_idle (MidoriBrowser* browser); |
1035 | +void |
1036 | +midori_bookmarkbar_position_items (GtkWidget* widget); |
1037 | |
1038 | static void |
1039 | midori_bookmarkbar_clear (GtkWidget* toolbar); |
1040 | |
1041 | static void |
1042 | +bookmarkbar_dnd_control_init (BookmarkbarDNDControl* control, MidoriBrowser* browser); |
1043 | + |
1044 | +static void |
1045 | +bookmarkbar_dnd_control_finalize (BookmarkbarDNDControl* control); |
1046 | + |
1047 | +static void |
1048 | +bookmarkbar_dnd_control_install (BookmarkbarDNDControl* control, GtkToolbar* bookmarkbar); |
1049 | + |
1050 | +static void |
1051 | _midori_browser_set_toolbar_style (MidoriBrowser* browser, |
1052 | MidoriToolbarStyle toolbar_style); |
1053 | |
1054 | @@ -716,6 +742,8 @@ |
1055 | const gchar* title) |
1056 | { |
1057 | const gchar* custom_title = midori_settings_get_custom_title (MIDORI_SETTINGS (browser->settings)); |
1058 | + GtkAction* action = _action_by_name (browser, "Location"); |
1059 | + midori_location_action_set_title (MIDORI_LOCATION_ACTION (action), title); |
1060 | if (custom_title && *custom_title) |
1061 | gtk_window_set_title (GTK_WINDOW (browser), custom_title); |
1062 | else if (katze_object_get_boolean (browser->settings, "enable-private-browsing")) |
1063 | @@ -885,14 +913,14 @@ |
1064 | gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo)); |
1065 | |
1066 | renderer = gtk_cell_renderer_pixbuf_new (); |
1067 | - g_object_set (G_OBJECT (renderer), |
1068 | + g_object_set (G_OBJECT (renderer), |
1069 | "stock-id", GTK_STOCK_DIRECTORY, |
1070 | "stock-size", GTK_ICON_SIZE_MENU, |
1071 | NULL); |
1072 | gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, FALSE); |
1073 | |
1074 | renderer = katze_cell_renderer_combobox_text_new (); |
1075 | - g_object_set (G_OBJECT (renderer), |
1076 | + g_object_set (G_OBJECT (renderer), |
1077 | "width-chars", 40, /* FIXME: figure out a way to define an acceptable string length */ |
1078 | "ellipsize", PANGO_ELLIPSIZE_END, |
1079 | "unfolded-text", _("Select [text]"), |
1080 | @@ -916,7 +944,7 @@ |
1081 | folders = g_list_append (folders, folder); |
1082 | } |
1083 | |
1084 | - sqlite3_clear_bindings (statement); |
1085 | + sqlite3_clear_bindings (statement); |
1086 | sqlite3_reset (statement); |
1087 | } |
1088 | |
1089 | @@ -1025,7 +1053,7 @@ |
1090 | static gint64 |
1091 | midori_bookmark_folder_button_get_active (GtkWidget* combo) |
1092 | { |
1093 | - gint64 id = 0; |
1094 | + gint64 id = -1; |
1095 | GtkTreeIter iter; |
1096 | |
1097 | g_return_val_if_fail (GTK_IS_COMBO_BOX (combo), 0); |
1098 | @@ -1902,6 +1930,8 @@ |
1099 | KatzeItem* item = midori_view_get_proxy_item (MIDORI_VIEW (view)); |
1100 | guint n; |
1101 | |
1102 | + g_object_set (view, "dnd-targets", browser->bookmarkbar_dnd_control.source_targets, NULL); |
1103 | + |
1104 | midori_browser_connect_tab (browser, view); |
1105 | |
1106 | if (!katze_item_get_meta_boolean (item, "append") && |
1107 | @@ -3107,29 +3137,17 @@ |
1108 | KatzeArray* folder, |
1109 | MidoriBrowser* browser) |
1110 | { |
1111 | - KatzeArray* bookmarks; |
1112 | - const gchar* id = katze_item_get_meta_string (KATZE_ITEM (folder), "id"); |
1113 | - gchar* condition; |
1114 | - |
1115 | if (browser->bookmarks == NULL) |
1116 | return FALSE; |
1117 | |
1118 | - if (id == NULL) |
1119 | - condition = "parentid is NULL"; |
1120 | - else |
1121 | - condition = "parentid = %q"; |
1122 | - |
1123 | - bookmarks = midori_bookmarks_db_query_recursive (browser->bookmarks, |
1124 | - "id, title, parentid, uri, app, pos_panel, pos_bar", condition, id, FALSE); |
1125 | - if (!bookmarks) |
1126 | - return FALSE; |
1127 | + midori_bookmarks_db_populate_folder (browser->bookmarks, folder); |
1128 | |
1129 | /* Clear items from dummy array here */ |
1130 | gtk_container_foreach (GTK_CONTAINER (menu), |
1131 | (GtkCallback)(gtk_widget_destroy), NULL); |
1132 | |
1133 | /* "Import Bookmarks" and "Export Bookmarks" at the top */ |
1134 | - if (id == NULL) |
1135 | + if (folder == KATZE_ARRAY (browser->bookmarks)) |
1136 | { |
1137 | GtkWidget* menuitem; |
1138 | menuitem = gtk_action_create_menu_item (_action_by_name (browser, "BookmarksImport")); |
1139 | @@ -3143,7 +3161,7 @@ |
1140 | gtk_widget_show (menuitem); |
1141 | } |
1142 | |
1143 | - if (katze_array_is_empty (bookmarks)) |
1144 | + if (katze_array_is_empty (folder)) |
1145 | { |
1146 | GtkWidget* menuitem = gtk_image_menu_item_new_with_label (_("Empty")); |
1147 | gtk_widget_set_sensitive (menuitem, FALSE); |
1148 | @@ -3152,7 +3170,7 @@ |
1149 | return TRUE; |
1150 | } |
1151 | |
1152 | - katze_array_action_generate_menu (KATZE_ARRAY_ACTION (action), bookmarks, |
1153 | + katze_array_action_generate_menu (KATZE_ARRAY_ACTION (action), folder, |
1154 | menu, GTK_WIDGET (browser)); |
1155 | return TRUE; |
1156 | } |
1157 | @@ -4502,7 +4520,7 @@ |
1158 | |
1159 | error = NULL; |
1160 | bookmarks = midori_bookmarks_db_query_recursive (browser->bookmarks, |
1161 | - "*", "parentid IS NULL", NULL, TRUE); |
1162 | + "*", "parentid IS NULL", NULL, NULL, TRUE); |
1163 | if (!midori_array_to_file (bookmarks, path, format, &error)) |
1164 | { |
1165 | sokoke_message_dialog (GTK_MESSAGE_ERROR, |
1166 | @@ -4903,6 +4921,8 @@ |
1167 | uri = midori_view_get_display_uri (new_view); |
1168 | midori_browser_set_title (browser, midori_view_get_display_title (new_view)); |
1169 | action = _action_by_name (browser, "Location"); |
1170 | + midori_location_action_set_icon (MIDORI_LOCATION_ACTION (action), midori_view_get_icon_uri (new_view)); |
1171 | + midori_location_action_set_title (MIDORI_LOCATION_ACTION (action), midori_view_get_display_title (new_view)); |
1172 | midori_location_action_set_text (MIDORI_LOCATION_ACTION (action), uri); |
1173 | if (midori_paths_get_runtime_mode () == MIDORI_RUNTIME_MODE_APP) |
1174 | gtk_window_set_icon (GTK_WINDOW (browser), midori_view_get_icon (new_view)); |
1175 | @@ -5876,8 +5896,6 @@ |
1176 | g_object_connect (action, |
1177 | "signal::populate-popup", |
1178 | _action_tools_populate_popup, browser, |
1179 | - "signal::activate-item-alt", |
1180 | - midori_bookmarkbar_activate_item_alt, browser, |
1181 | NULL); |
1182 | gtk_action_group_add_action (browser->action_group, action); |
1183 | g_object_unref (action); |
1184 | @@ -6003,7 +6021,11 @@ |
1185 | g_signal_connect (browser->bookmarkbar, "popup-context-menu", |
1186 | G_CALLBACK (midori_browser_toolbar_popup_context_menu_cb), browser); |
1187 | |
1188 | - /* Create the panel */ |
1189 | + bookmarkbar_dnd_control_init (&browser->bookmarkbar_dnd_control, browser); |
1190 | + bookmarkbar_dnd_control_install (&browser->bookmarkbar_dnd_control, |
1191 | + GTK_TOOLBAR (browser->bookmarkbar)); |
1192 | + |
1193 | + /* Create the panel */ |
1194 | hpaned = gtk_hpaned_new (); |
1195 | g_signal_connect (hpaned, "notify::position", |
1196 | G_CALLBACK (midori_panel_notify_position_cb), |
1197 | @@ -6101,6 +6123,8 @@ |
1198 | { |
1199 | MidoriBrowser* browser = MIDORI_BROWSER (object); |
1200 | |
1201 | + bookmarkbar_dnd_control_finalize (&browser->bookmarkbar_dnd_control); |
1202 | + |
1203 | katze_assign (browser->statusbar_text, NULL); |
1204 | |
1205 | katze_object_assign (browser->settings, NULL); |
1206 | @@ -6624,7 +6648,8 @@ |
1207 | |
1208 | static void |
1209 | midori_bookmarkbar_insert_item (GtkWidget* toolbar, |
1210 | - KatzeItem* item) |
1211 | + KatzeItem* item, |
1212 | + gint pos) |
1213 | { |
1214 | MidoriBrowser* browser = midori_browser_get_for_widget (toolbar); |
1215 | GtkAction* action = _action_by_name (browser, "Bookmarks"); |
1216 | @@ -6643,19 +6668,19 @@ |
1217 | else /* Separator */ |
1218 | gtk_tool_item_set_use_drag_window (toolitem, TRUE); |
1219 | |
1220 | + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, pos); |
1221 | gtk_widget_show (GTK_WIDGET (toolitem)); |
1222 | - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); |
1223 | } |
1224 | |
1225 | static void |
1226 | midori_bookmarkbar_add_item_cb (KatzeArray* bookmarks, |
1227 | - KatzeItem* item, |
1228 | - MidoriBrowser* browser) |
1229 | + KatzeItem* item, |
1230 | + MidoriBrowser* browser) |
1231 | { |
1232 | if (gtk_widget_get_visible (browser->bookmarkbar)) |
1233 | midori_bookmarkbar_populate (browser); |
1234 | else if (katze_item_get_meta_boolean (item, "toolbar")) |
1235 | - _action_set_active (browser, "Bookmarkbar", TRUE); |
1236 | + _action_set_active (browser, "Bookmarkbar", TRUE); |
1237 | midori_browser_update_history (item, "bookmark", "created"); |
1238 | } |
1239 | |
1240 | @@ -6702,7 +6727,7 @@ |
1241 | gtk_separator_tool_item_new (), -1); |
1242 | |
1243 | array = midori_bookmarks_db_query_recursive (browser->bookmarks, |
1244 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL, FALSE); |
1245 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL, "pos_bar ASC", FALSE); |
1246 | if (!array) |
1247 | { |
1248 | _action_set_sensitive (browser, "BookmarkAdd", FALSE); |
1249 | @@ -6712,10 +6737,12 @@ |
1250 | |
1251 | KATZE_ARRAY_FOREACH_ITEM (item, array) |
1252 | { |
1253 | - midori_bookmarkbar_insert_item (browser->bookmarkbar, item); |
1254 | + midori_bookmarkbar_insert_item (browser->bookmarkbar, item, -1); |
1255 | } |
1256 | _action_set_sensitive (browser, "BookmarkAdd", TRUE); |
1257 | _action_set_sensitive (browser, "BookmarkFolderAdd", TRUE); |
1258 | + |
1259 | + midori_bookmarkbar_position_items (browser->bookmarkbar); |
1260 | } |
1261 | |
1262 | static void |
1263 | @@ -6756,6 +6783,10 @@ |
1264 | midori_bookmarkbar_remove_item_cb, browser); |
1265 | } |
1266 | |
1267 | + g_object_set (G_OBJECT (_action_by_name (browser, "Bookmarks")), |
1268 | + "array", KATZE_ARRAY (bookmarks), |
1269 | + NULL); |
1270 | + |
1271 | settings = midori_browser_get_settings (browser); |
1272 | g_signal_handlers_disconnect_by_func (settings, |
1273 | midori_browser_show_bookmarkbar_notify_value_cb, browser); |
1274 | @@ -7481,3 +7512,331 @@ |
1275 | |
1276 | g_signal_emit (browser, signals[QUIT], 0); |
1277 | } |
1278 | + |
1279 | +static void |
1280 | +bookmarkbar_drag_dest_control_init (BookmarkbarDragDestControl* control) |
1281 | +{ |
1282 | + control->highligth_item = NULL; |
1283 | + control->hovering = FALSE; |
1284 | +} |
1285 | + |
1286 | +static GtkTargetEntry bookmarkbar_dnd_target_entries[]= |
1287 | +{ |
1288 | + {"KATZE_ARRAY", GTK_TARGET_SAME_APP, 0}, |
1289 | +}; |
1290 | + |
1291 | +#define BOOKMARKBAR_DND_NB_TARGET_ENTRIES \ |
1292 | + G_N_ELEMENTS (bookmarkbar_dnd_target_entries) |
1293 | + |
1294 | +static void |
1295 | +bookmarkbar_dnd_control_init (BookmarkbarDNDControl* control, MidoriBrowser* browser) |
1296 | +{ |
1297 | + bookmarkbar_drag_dest_control_init (&control->drag_dest_control); |
1298 | + |
1299 | + control->source_targets = gtk_target_list_new ( |
1300 | + bookmarkbar_dnd_target_entries, BOOKMARKBAR_DND_NB_TARGET_ENTRIES); |
1301 | + gtk_target_list_add_uri_targets (control->source_targets, 0); |
1302 | + gtk_target_list_add_text_targets (control->source_targets, 0); |
1303 | + |
1304 | + control->dest_targets = gtk_target_list_new ( |
1305 | + bookmarkbar_dnd_target_entries, BOOKMARKBAR_DND_NB_TARGET_ENTRIES); |
1306 | + |
1307 | + g_object_set (_action_by_name (browser, "Bookmarks"), "dnd-targets", control->source_targets, NULL); |
1308 | + g_object_set (_action_by_name (browser, "Location"), "dnd-targets", control->source_targets, NULL); |
1309 | +} |
1310 | + |
1311 | +static void |
1312 | +bookmarkbar_dnd_control_finalize (BookmarkbarDNDControl* control) |
1313 | +{ |
1314 | + gtk_target_list_unref (control->source_targets); |
1315 | + gtk_target_list_unref (control->dest_targets); |
1316 | + control->source_targets = NULL; |
1317 | + control->dest_targets = NULL; |
1318 | +} |
1319 | + |
1320 | + |
1321 | +static GtkToolItem* |
1322 | +bookmarkbar_drag_highlight_item (GdkDragContext *context) |
1323 | +{ |
1324 | + |
1325 | + GtkToolItem* highlight_item = NULL; |
1326 | + GtkWidget* source = gtk_drag_get_source_widget (context); |
1327 | + |
1328 | + if (source) |
1329 | + { |
1330 | + KatzeItem* item = (KatzeItem*)g_object_get_data (G_OBJECT (source), "KatzeItem"); |
1331 | + |
1332 | + if (!item && GTK_IS_TOOL_ITEM (gtk_widget_get_parent (source))) |
1333 | + item = (KatzeItem*)g_object_get_data (G_OBJECT (gtk_widget_get_parent (source)), "KatzeItem"); |
1334 | + |
1335 | + if (KATZE_ITEM_IS_BOOKMARK (item)) |
1336 | + highlight_item = gtk_tool_button_new (NULL, ""); |
1337 | + else if (KATZE_ITEM_IS_FOLDER (item)) |
1338 | + highlight_item = gtk_toggle_tool_button_new (); |
1339 | + |
1340 | + if (highlight_item) |
1341 | + { |
1342 | + GtkToolButton* toolbutton = GTK_TOOL_BUTTON (highlight_item); |
1343 | + GtkWidget* image = katze_item_get_image (item, GTK_WIDGET (highlight_item)); |
1344 | + const gchar* title = katze_item_get_name (item); |
1345 | + GtkWidget* label = gtk_label_new (NULL); |
1346 | + |
1347 | + gtk_widget_show (image); |
1348 | + |
1349 | + if (!title || !*title) |
1350 | + title = katze_item_get_uri (item); |
1351 | + |
1352 | + /* FIXME: Should text direction be respected here? */ |
1353 | + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
1354 | + gtk_label_set_max_width_chars (GTK_LABEL (label), 25); |
1355 | + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE); |
1356 | + gtk_label_set_text (GTK_LABEL (label), title); |
1357 | + gtk_widget_show (label); |
1358 | + |
1359 | + gtk_tool_button_set_icon_widget (toolbutton, image); |
1360 | + gtk_tool_button_set_label_widget (toolbutton, label); |
1361 | + |
1362 | + gtk_tool_item_set_visible_horizontal (highlight_item, TRUE); |
1363 | + gtk_tool_item_set_visible_vertical (highlight_item, TRUE); |
1364 | + gtk_tool_item_set_is_important (highlight_item, TRUE); |
1365 | + } |
1366 | + } |
1367 | + |
1368 | + if (!highlight_item) |
1369 | + highlight_item = gtk_separator_tool_item_new (); |
1370 | + |
1371 | + gtk_widget_show (GTK_WIDGET (highlight_item)); |
1372 | + return highlight_item; |
1373 | +} |
1374 | + |
1375 | +static gboolean |
1376 | +bookmarkbar_drag_dest_drag_motion_cb (GtkWidget *widget, |
1377 | + GdkDragContext *context, |
1378 | + gint x, gint y, guint t, |
1379 | + BookmarkbarDragDestControl* control) |
1380 | +{ |
1381 | + GtkToolbar* toolbar = GTK_TOOLBAR (widget); |
1382 | + gint n = gtk_toolbar_get_drop_index (toolbar, x, y); |
1383 | + |
1384 | + if (!control->highligth_item) |
1385 | + { |
1386 | + GtkToolItem* highlight_item = bookmarkbar_drag_highlight_item (context); |
1387 | + g_object_ref (highlight_item); |
1388 | + |
1389 | + gtk_toolbar_set_drop_highlight_item (toolbar, |
1390 | + highlight_item, |
1391 | + n); |
1392 | + control->highligth_item = highlight_item; |
1393 | + control->n = n; |
1394 | + } |
1395 | + else if (n != control->n) |
1396 | + { |
1397 | + gtk_toolbar_set_drop_highlight_item (toolbar, |
1398 | + control->highligth_item, |
1399 | + n); |
1400 | + control->n = n; |
1401 | + } |
1402 | + return FALSE; |
1403 | +} |
1404 | + |
1405 | +static void |
1406 | +bookmarkbar_drag_dest_drag_leave_cb (GtkWidget *widget, |
1407 | + GdkDragContext *context, |
1408 | + guint time, |
1409 | + BookmarkbarDragDestControl* control) |
1410 | +{ |
1411 | + GtkToolbar* toolbar = GTK_TOOLBAR (widget); |
1412 | + |
1413 | + if (control->highligth_item) |
1414 | + { |
1415 | + gtk_toolbar_set_drop_highlight_item (toolbar, NULL, -1); |
1416 | + g_object_unref (control->highligth_item); |
1417 | + control->highligth_item = NULL; |
1418 | + } |
1419 | +} |
1420 | + |
1421 | +void |
1422 | +midori_bookmarkbar_position_items (GtkWidget *widget) |
1423 | +{ |
1424 | + GtkToolbar* toolbar = GTK_TOOLBAR (widget); |
1425 | + MidoriBrowser* browser = midori_browser_get_for_widget (widget); |
1426 | + gint n = gtk_toolbar_get_n_items (toolbar); |
1427 | + gint i; |
1428 | + gint pos; |
1429 | + |
1430 | + pos = 0; |
1431 | + for (i = 0; i < n ; i++ ) |
1432 | + { |
1433 | + GtkWidget* toolitem = GTK_WIDGET (gtk_toolbar_get_nth_item (toolbar, i)); |
1434 | + KatzeItem* local_item = (KatzeItem*)g_object_get_data (G_OBJECT (toolitem), "KatzeItem"); |
1435 | + |
1436 | + if (!KATZE_IS_ITEM (local_item)) |
1437 | + continue; |
1438 | + |
1439 | + if (pos != katze_item_get_meta_integer (local_item, "pos_bar")) |
1440 | + katze_item_set_meta_integer (local_item, "pos_bar", pos); |
1441 | + |
1442 | + midori_bookmarks_db_update_item (browser->bookmarks, local_item); |
1443 | + |
1444 | + pos++; |
1445 | + } |
1446 | +} |
1447 | + |
1448 | +static void |
1449 | +bookmarkbar_drag_dest_drag_data_received_cb (GtkWidget *widget, |
1450 | + GdkDragContext *drag_context, |
1451 | + gint x, |
1452 | + gint y, |
1453 | + GtkSelectionData *data, |
1454 | + guint info, |
1455 | + guint time, |
1456 | + BookmarkbarDragDestControl* control) |
1457 | +{ |
1458 | + GtkToolbar* toolbar = GTK_TOOLBAR (widget); |
1459 | + MidoriBrowser* browser = midori_browser_get_for_widget (widget); |
1460 | + gboolean success = FALSE; |
1461 | + gboolean delete = FALSE; |
1462 | + |
1463 | + g_assert (browser); |
1464 | + |
1465 | + g_signal_handlers_block_by_func (browser->bookmarks, |
1466 | + midori_bookmarkbar_add_item_cb, browser); |
1467 | + g_signal_handlers_block_by_func (browser->bookmarks, |
1468 | + midori_bookmarkbar_update_item_cb, browser); |
1469 | + g_signal_handlers_block_by_func (browser->bookmarks, |
1470 | + midori_bookmarkbar_remove_item_cb, browser); |
1471 | + |
1472 | + if (gtk_selection_data_get_length (data) >= 0) |
1473 | + { |
1474 | + switch (gdk_drag_context_get_selected_action (drag_context)) |
1475 | + { |
1476 | + case GDK_ACTION_MOVE: |
1477 | + delete = TRUE; |
1478 | + case GDK_ACTION_COPY: |
1479 | + if (gtk_selection_data_get_format (data) == 8) |
1480 | + { |
1481 | + KatzeArray *array = katze_array_from_selection_data (data); |
1482 | + |
1483 | + if (array) |
1484 | + { |
1485 | + KatzeItem *item; |
1486 | + KATZE_ARRAY_FOREACH_ITEM (item, array) |
1487 | + { |
1488 | + gint old_pos = gtk_toolbar_get_n_items(toolbar); |
1489 | + gint dest_pos = gtk_toolbar_get_drop_index (toolbar, x, y); |
1490 | + gboolean is_bookmark = katze_item_get_meta_string (item, "id") ? TRUE : FALSE ; |
1491 | + gboolean from_toolbar = is_bookmark && katze_item_get_meta_boolean (item, "toolbar"); |
1492 | + |
1493 | + if (midori_debug("bookmarks")) |
1494 | + { |
1495 | + g_print ("bookmarkbar received KATZE_ITEM(bookmark:%d, toolbar:%d, title:%s) \n", |
1496 | + is_bookmark, from_toolbar, katze_item_get_name (item)); |
1497 | + } |
1498 | + |
1499 | + if (from_toolbar) |
1500 | + { |
1501 | + GtkToolItem* toolitem = NULL; |
1502 | + KatzeItem* local_item = NULL; |
1503 | + |
1504 | + old_pos = katze_item_get_meta_integer (item, "pos_bar"); |
1505 | + |
1506 | + if ((dest_pos != old_pos) |
1507 | + && (toolitem = gtk_toolbar_get_nth_item (toolbar, |
1508 | + old_pos)) |
1509 | + && (local_item = (KatzeItem*)g_object_get_data ( |
1510 | + G_OBJECT (toolitem), "KatzeItem"))) |
1511 | + { |
1512 | + midori_bookmarkbar_insert_item (widget, |
1513 | + local_item, dest_pos); |
1514 | + |
1515 | + if (old_pos < dest_pos) |
1516 | + old_pos++; |
1517 | + |
1518 | + /* FIXME: force a move */ |
1519 | + delete = TRUE; |
1520 | + } |
1521 | + else |
1522 | + delete = FALSE; |
1523 | + } |
1524 | + else if (!is_bookmark) |
1525 | + { |
1526 | + item = katze_item_copy (item); |
1527 | + |
1528 | + katze_item_set_meta_integer (item, "toolbar", TRUE); |
1529 | + |
1530 | + midori_bookmarkbar_insert_item (widget, |
1531 | + item, dest_pos); |
1532 | + |
1533 | + midori_bookmarks_db_add_item (browser->bookmarks, item); |
1534 | + |
1535 | + if (old_pos > dest_pos) |
1536 | + old_pos++; |
1537 | + |
1538 | + delete = FALSE; |
1539 | + } |
1540 | + else |
1541 | + { |
1542 | + katze_item_set_meta_integer (item, "toolbar", TRUE); |
1543 | + |
1544 | + midori_bookmarkbar_insert_item (widget, |
1545 | + item, dest_pos); |
1546 | + |
1547 | + if (old_pos > dest_pos) |
1548 | + old_pos++; |
1549 | + |
1550 | + delete = FALSE; |
1551 | + } |
1552 | + } |
1553 | + |
1554 | + g_object_unref (array); |
1555 | + success = TRUE; |
1556 | + break; |
1557 | + } |
1558 | + } |
1559 | + default: |
1560 | + break; |
1561 | + } |
1562 | + } |
1563 | + |
1564 | + if (!success) |
1565 | + delete = FALSE; |
1566 | + |
1567 | + gtk_drag_finish (drag_context, success, delete, time); |
1568 | + |
1569 | + if (success && !delete) |
1570 | + { |
1571 | + midori_bookmarkbar_position_items (GTK_WIDGET (toolbar)); |
1572 | + } |
1573 | + |
1574 | + g_signal_handlers_unblock_by_func (browser->bookmarks, |
1575 | + midori_bookmarkbar_add_item_cb, browser); |
1576 | + g_signal_handlers_unblock_by_func (browser->bookmarks, |
1577 | + midori_bookmarkbar_update_item_cb, browser); |
1578 | + g_signal_handlers_unblock_by_func (browser->bookmarks, |
1579 | + midori_bookmarkbar_remove_item_cb, browser); |
1580 | +} |
1581 | + |
1582 | +static void |
1583 | +bookmarkbar_drag_dest_control_install (BookmarkbarDNDControl* control, |
1584 | + GtkToolbar* bookmarkbar) |
1585 | +{ |
1586 | + GtkWidget* widget = GTK_WIDGET (bookmarkbar); |
1587 | + gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, NULL, 0, |
1588 | + GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_LINK); |
1589 | + gtk_drag_dest_set_target_list (widget, control->dest_targets); |
1590 | + g_signal_connect (bookmarkbar, "drag-motion", |
1591 | + G_CALLBACK (bookmarkbar_drag_dest_drag_motion_cb), |
1592 | + &control->drag_dest_control); |
1593 | + g_signal_connect (bookmarkbar, "drag-leave", |
1594 | + G_CALLBACK (bookmarkbar_drag_dest_drag_leave_cb), |
1595 | + &control->drag_dest_control); |
1596 | + g_signal_connect (bookmarkbar, "drag-data-received", |
1597 | + G_CALLBACK (bookmarkbar_drag_dest_drag_data_received_cb), |
1598 | + &control->drag_dest_control); |
1599 | +} |
1600 | + |
1601 | +static void |
1602 | +bookmarkbar_dnd_control_install (BookmarkbarDNDControl* control, GtkToolbar* bookmarkbar) |
1603 | +{ |
1604 | + bookmarkbar_drag_dest_control_install (control, bookmarkbar); |
1605 | +} |
1606 | |
1607 | === modified file 'midori/midori-locationaction.c' |
1608 | --- midori/midori-locationaction.c 2013-11-05 14:51:49 +0000 |
1609 | +++ midori/midori-locationaction.c 2014-01-26 19:44:25 +0000 |
1610 | @@ -43,6 +43,8 @@ |
1611 | gint completion_index; |
1612 | GtkWidget* entry; |
1613 | KatzeArray* history; |
1614 | + KatzeItem* item; |
1615 | + GtkTargetList* dnd_targets; |
1616 | }; |
1617 | |
1618 | struct _MidoriLocationActionClass |
1619 | @@ -58,7 +60,8 @@ |
1620 | |
1621 | PROP_PROGRESS, |
1622 | PROP_SECONDARY_ICON, |
1623 | - PROP_HISTORY |
1624 | + PROP_HISTORY, |
1625 | + PROP_DND_TARGETS |
1626 | }; |
1627 | |
1628 | enum |
1629 | @@ -222,6 +225,22 @@ |
1630 | "The list of history items", |
1631 | KATZE_TYPE_ARRAY, |
1632 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
1633 | + |
1634 | + /** |
1635 | + * MidoriLocationAction:dnd-targets: |
1636 | + * |
1637 | + * GtkTargetList* the location action supports. |
1638 | + * |
1639 | + * Since: 0.5.2 |
1640 | + **/ |
1641 | + g_object_class_install_property (gobject_class, |
1642 | + PROP_DND_TARGETS, |
1643 | + g_param_spec_pointer ( |
1644 | + "dnd-targets", |
1645 | + "DNDTargets", |
1646 | + "GtkTargetList* the location action supports", |
1647 | + G_PARAM_READABLE|G_PARAM_WRITABLE)); |
1648 | + |
1649 | } |
1650 | |
1651 | gchar* |
1652 | @@ -813,6 +832,8 @@ |
1653 | { |
1654 | location_action->progress = 0.0; |
1655 | location_action->completion_index = -1; |
1656 | + location_action->item = katze_item_new (); |
1657 | + location_action->dnd_targets = NULL; |
1658 | } |
1659 | |
1660 | static void |
1661 | @@ -832,6 +853,8 @@ |
1662 | } |
1663 | katze_object_assign (location_action->history, NULL); |
1664 | |
1665 | + g_object_unref (location_action->item); |
1666 | + |
1667 | G_OBJECT_CLASS (midori_location_action_parent_class)->finalize (object); |
1668 | } |
1669 | |
1670 | @@ -858,6 +881,9 @@ |
1671 | katze_assign (location_action->history, g_value_dup_object (value)); |
1672 | break; |
1673 | } |
1674 | + case PROP_DND_TARGETS: |
1675 | + location_action->dnd_targets = (GtkTargetList*)g_value_get_pointer (value); |
1676 | + break; |
1677 | default: |
1678 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1679 | break; |
1680 | @@ -883,6 +909,9 @@ |
1681 | case PROP_HISTORY: |
1682 | g_value_set_object (value, location_action->history); |
1683 | break; |
1684 | + case PROP_DND_TARGETS: |
1685 | + g_value_set_pointer (value, location_action->dnd_targets); |
1686 | + break; |
1687 | default: |
1688 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1689 | break; |
1690 | @@ -917,20 +946,19 @@ |
1691 | GtkSelectionData* data, |
1692 | guint info, |
1693 | guint32 time, |
1694 | - GtkAction* action) |
1695 | + MidoriLocationAction* action) |
1696 | { |
1697 | if (gtk_entry_get_current_icon_drag_source (GTK_ENTRY (entry)) == GTK_ENTRY_ICON_PRIMARY) |
1698 | { |
1699 | - const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry)); |
1700 | - gchar** uris = g_strsplit (uri, uri, 1); |
1701 | - gtk_selection_data_set_uris (data, uris); |
1702 | - g_strfreev (uris); |
1703 | + katze_item_set_uri (action->item, gtk_entry_get_text (GTK_ENTRY (entry))); |
1704 | + selection_data_from_katze_item (data, action->item); |
1705 | } |
1706 | } |
1707 | |
1708 | static GtkWidget* |
1709 | midori_location_action_create_tool_item (GtkAction* action) |
1710 | { |
1711 | + MidoriLocationAction* location_action = MIDORI_LOCATION_ACTION (action); |
1712 | GtkWidget* toolitem; |
1713 | GtkWidget* alignment; |
1714 | GtkWidget* entry; |
1715 | @@ -953,10 +981,18 @@ |
1716 | gtk_entry_set_icon_activatable (GTK_ENTRY (entry), |
1717 | GTK_ENTRY_ICON_SECONDARY, TRUE); |
1718 | |
1719 | - targetlist = gtk_target_list_new (NULL, 0); |
1720 | - gtk_target_list_add_uri_targets (targetlist, 0); |
1721 | - gtk_entry_set_icon_drag_source (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, targetlist, GDK_ACTION_ASK | GDK_ACTION_COPY | GDK_ACTION_LINK); |
1722 | - gtk_target_list_unref (targetlist); |
1723 | + g_object_set_data (G_OBJECT (entry), "KatzeItem", MIDORI_LOCATION_ACTION (action)->item); |
1724 | + |
1725 | + if (location_action->dnd_targets) |
1726 | + gtk_entry_set_icon_drag_source (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, |
1727 | + location_action->dnd_targets, GDK_ACTION_ASK | GDK_ACTION_COPY | GDK_ACTION_LINK); |
1728 | + else |
1729 | + { |
1730 | + targetlist = gtk_target_list_new (NULL, 0); |
1731 | + gtk_target_list_add_uri_targets (targetlist, 0); |
1732 | + gtk_entry_set_icon_drag_source (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, targetlist, GDK_ACTION_ASK | GDK_ACTION_COPY | GDK_ACTION_LINK); |
1733 | + gtk_target_list_unref (targetlist); |
1734 | + } |
1735 | g_signal_connect (entry, "drag-data-get", |
1736 | G_CALLBACK (midori_location_action_entry_drag_data_get_cb), action); |
1737 | gtk_widget_show (entry); |
1738 | @@ -1630,6 +1666,38 @@ |
1739 | } |
1740 | |
1741 | /** |
1742 | + * midori_location_action_set_icon: |
1743 | + * @location_action: a #MidoriLocationAction |
1744 | + * @icon: an icon |
1745 | + * |
1746 | + * Sets the entry icon to @icon. |
1747 | + * |
1748 | + * Since: 0.5.2 |
1749 | + **/ |
1750 | +void |
1751 | +midori_location_action_set_icon (MidoriLocationAction* location_action, |
1752 | + const gchar* icon) |
1753 | +{ |
1754 | + katze_item_set_icon (location_action->item, icon); |
1755 | +} |
1756 | + |
1757 | +/** |
1758 | + * midori_location_action_set_title: |
1759 | + * @location_action: a #MidoriLocationAction |
1760 | + * @text: a string |
1761 | + * |
1762 | + * Sets the entry name to @text. |
1763 | + * |
1764 | + * Since: 0.5.2 |
1765 | + **/ |
1766 | +void |
1767 | +midori_location_action_set_title (MidoriLocationAction* location_action, |
1768 | + const gchar* title) |
1769 | +{ |
1770 | + katze_item_set_name (location_action->item, title); |
1771 | +} |
1772 | + |
1773 | +/** |
1774 | * midori_location_action_set_text: |
1775 | * @location_action: a #MidoriLocationAction |
1776 | * @text: a string |
1777 | |
1778 | === modified file 'midori/midori-locationaction.h' |
1779 | --- midori/midori-locationaction.h 2013-04-16 23:10:10 +0000 |
1780 | +++ midori/midori-locationaction.h 2014-01-26 19:44:25 +0000 |
1781 | @@ -40,6 +40,14 @@ |
1782 | midori_location_action_get_text (MidoriLocationAction* location_action); |
1783 | |
1784 | void |
1785 | +midori_location_action_set_icon (MidoriLocationAction* location_action, |
1786 | + const gchar* icon); |
1787 | + |
1788 | +void |
1789 | +midori_location_action_set_title (MidoriLocationAction* location_action, |
1790 | + const gchar* title); |
1791 | + |
1792 | +void |
1793 | midori_location_action_set_text (MidoriLocationAction* location_action, |
1794 | const gchar* text); |
1795 | |
1796 | |
1797 | === modified file 'midori/midori-view.c' |
1798 | --- midori/midori-view.c 2013-12-09 20:23:03 +0000 |
1799 | +++ midori/midori-view.c 2014-01-26 19:44:25 +0000 |
1800 | @@ -121,6 +121,8 @@ |
1801 | GtkWidget* overlay_label; |
1802 | GtkWidget* overlay_find; |
1803 | #endif |
1804 | + |
1805 | + GtkTargetList* dnd_targets; |
1806 | }; |
1807 | |
1808 | struct _MidoriViewClass |
1809 | @@ -139,7 +141,8 @@ |
1810 | PROP_MINIMIZED, |
1811 | PROP_ZOOM_LEVEL, |
1812 | PROP_NEWS_FEEDS, |
1813 | - PROP_SETTINGS |
1814 | + PROP_SETTINGS, |
1815 | + PROP_DND_TARGETS |
1816 | }; |
1817 | |
1818 | enum { |
1819 | @@ -379,6 +382,21 @@ |
1820 | MIDORI_TYPE_WEB_SETTINGS, |
1821 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
1822 | |
1823 | + /** |
1824 | + * MidoriView:dnd-targets: |
1825 | + * |
1826 | + * GtkTargetList* the view supports. |
1827 | + * |
1828 | + * Since: 0.5.2 |
1829 | + **/ |
1830 | + g_object_class_install_property (gobject_class, |
1831 | + PROP_DND_TARGETS, |
1832 | + g_param_spec_pointer ( |
1833 | + "dnd-targets", |
1834 | + "DNDTargets", |
1835 | + "GtkTargetList* the view supports", |
1836 | + G_PARAM_READABLE|G_PARAM_WRITABLE)); |
1837 | + |
1838 | #ifdef HAVE_WEBKIT2 |
1839 | WebKitWebContext* context = webkit_web_context_get_default (); |
1840 | webkit_web_context_register_uri_scheme (context, |
1841 | @@ -2983,6 +3001,8 @@ |
1842 | view->news_feeds = NULL; |
1843 | view->find_links = -1; |
1844 | view->alerts = 0; |
1845 | + view->dnd_targets = NULL; |
1846 | + |
1847 | |
1848 | view->item = katze_item_new (); |
1849 | |
1850 | @@ -3056,6 +3076,9 @@ |
1851 | case PROP_SETTINGS: |
1852 | _midori_view_set_settings (view, g_value_get_object (value)); |
1853 | break; |
1854 | + case PROP_DND_TARGETS: |
1855 | + view->dnd_targets = (GtkTargetList*)g_value_get_pointer (value); |
1856 | + break; |
1857 | default: |
1858 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1859 | break; |
1860 | @@ -3087,6 +3110,9 @@ |
1861 | case PROP_SETTINGS: |
1862 | g_value_set_object (value, view->settings); |
1863 | break; |
1864 | + case PROP_DND_TARGETS: |
1865 | + g_value_set_pointer (value, view->dnd_targets); |
1866 | + break; |
1867 | default: |
1868 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1869 | break; |
1870 | @@ -4296,6 +4322,89 @@ |
1871 | return new_view; |
1872 | } |
1873 | |
1874 | +#if 0 |
1875 | +static void |
1876 | +midori_view_tab_label_data_received (GtkWidget* widget, |
1877 | + GdkDragContext* context, |
1878 | + gint x, |
1879 | + gint y, |
1880 | + GtkSelectionData* data, |
1881 | + guint ttype, |
1882 | + guint timestamp, |
1883 | + MidoriView* view) |
1884 | +{ |
1885 | + KatzeArray *array; |
1886 | + gchar** uri; |
1887 | + |
1888 | + array = katze_array_from_selection_data (data); |
1889 | + if (array) |
1890 | + { |
1891 | + if (katze_array_get_length (array)) |
1892 | + { |
1893 | + KatzeItem* item = katze_array_get_nth_item (array, 0); |
1894 | + if (KATZE_ITEM_IS_BOOKMARK (item)) |
1895 | + { |
1896 | + midori_view_set_title (view, katze_item_get_name (item)); |
1897 | + midori_view_set_uri (view, katze_item_get_uri (item)); |
1898 | + } |
1899 | + } |
1900 | + |
1901 | + g_object_unref (array); |
1902 | + return; |
1903 | + } |
1904 | + |
1905 | + uri = gtk_selection_data_get_uris (data); |
1906 | + if (uri != NULL) |
1907 | + { |
1908 | + midori_view_set_uri (view, uri[0]); |
1909 | + g_strfreev (uri); |
1910 | + } |
1911 | + else |
1912 | + { |
1913 | + gchar* text = (gchar*) gtk_selection_data_get_text (data); |
1914 | + midori_view_set_uri (view, text); |
1915 | + g_free (text); |
1916 | + } |
1917 | +} |
1918 | + |
1919 | +static void |
1920 | +midori_view_tab_label_data_get (GtkWidget *widget, |
1921 | + GdkDragContext *drag_context, |
1922 | + GtkSelectionData *data, |
1923 | + guint info, |
1924 | + guint time, |
1925 | + MidoriView* view) |
1926 | +{ |
1927 | + selection_data_from_katze_item (data, view->item); |
1928 | +} |
1929 | + |
1930 | +static void |
1931 | +midori_view_install_tab_dnd (MidoriView* view, GtkWidget* widget) |
1932 | +{ |
1933 | + g_object_set_data (G_OBJECT (widget), "KatzeItem", view->item) |
1934 | +; |
1935 | + gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, NULL, |
1936 | + 0, GDK_ACTION_COPY); |
1937 | + if (view->dnd_targets) |
1938 | + gtk_drag_dest_set_target_list (widget, view->dnd_targets); |
1939 | + gtk_drag_dest_add_text_targets (widget); |
1940 | + gtk_drag_dest_add_uri_targets (widget); |
1941 | + g_signal_connect (widget, "drag-data-received", |
1942 | + G_CALLBACK (midori_view_tab_label_data_received), |
1943 | + view); |
1944 | + if (view->dnd_targets) |
1945 | + { |
1946 | + g_print ("midori_view_get_tab: install source widget\n"); |
1947 | + gtk_drag_source_set (widget, GDK_BUTTON1_MASK, NULL, 0, |
1948 | + GDK_ACTION_COPY|GDK_ACTION_LINK); |
1949 | + gtk_drag_source_set_target_list (widget, view->dnd_targets); |
1950 | + g_signal_connect (widget, "drag-data-get", |
1951 | + G_CALLBACK (midori_view_tab_label_data_get), |
1952 | + view); |
1953 | + } |
1954 | +} |
1955 | +#endif |
1956 | + |
1957 | /** |
1958 | * midori_view_get_tab_menu: |
1959 | * @view: a #MidoriView |
1960 | |
1961 | === modified file 'panels/midori-bookmarks.c' |
1962 | --- panels/midori-bookmarks.c 2014-01-24 23:04:05 +0000 |
1963 | +++ panels/midori-bookmarks.c 2014-01-26 19:44:25 +0000 |
1964 | @@ -26,6 +26,151 @@ |
1965 | |
1966 | #define COMPLETION_DELAY 200 |
1967 | |
1968 | +#define MIDORI_BOOKMARKS_TREE_MODEL_TARGET "GTK_TREE_MODEL_ROW" |
1969 | + |
1970 | +G_BEGIN_DECLS |
1971 | + |
1972 | +#define MIDORI_BOOKMARKS_TREE_STORE_TYPE \ |
1973 | + (midori_bookmarks_tree_store_get_type ()) |
1974 | +#define MIDORI_BOOKMARKS_TREE_STORE(obj) \ |
1975 | + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_BOOKMARKS_TREE_STORE_TYPE, MidoriBookmarksTreeStore)) |
1976 | +#define MIDORI_BOOKMARKS_TREE_STORE_CLASS(klass) \ |
1977 | + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_BOOKMARKS_TREE_STORE_TYPE, MidoriBookmarksTreeStoreClass)) |
1978 | + |
1979 | +static gboolean |
1980 | +midori_bookmarks_tree_store_drag_data_get (GtkTreeDragSource* drag_source, |
1981 | + GtkTreePath* source_path, |
1982 | + GtkSelectionData* selection_data); |
1983 | +static gboolean |
1984 | +midori_bookmarks_tree_store_drag_data_delete (GtkTreeDragSource* drag_source, |
1985 | + GtkTreePath* source_path); |
1986 | +static gboolean |
1987 | +midori_bookmarks_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest, |
1988 | + GtkTreePath *dest_path, |
1989 | + GtkSelectionData *selection_data); |
1990 | +static gboolean |
1991 | +midori_bookmarks_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, |
1992 | + GtkTreePath *dest_path, |
1993 | + GtkSelectionData *selection_data); |
1994 | + |
1995 | +typedef struct _MidoriBookmarksTreeStore MidoriBookmarksTreeStore; |
1996 | +typedef struct _MidoriBookmarksTreeStoreClass MidoriBookmarksTreeStoreClass; |
1997 | +typedef struct _TreeRowData TreeRowData; |
1998 | + |
1999 | +struct _MidoriBookmarksTreeStore |
2000 | +{ |
2001 | + GtkTreeStore parent_instance; |
2002 | + |
2003 | + GList* stock_got_rows; |
2004 | + GtkTreeView *_view; |
2005 | +}; |
2006 | + |
2007 | +struct _MidoriBookmarksTreeStoreClass |
2008 | +{ |
2009 | + GtkTreeStoreClass parent_class; |
2010 | +}; |
2011 | + |
2012 | +struct _TreeRowData |
2013 | +{ |
2014 | + GtkTreeModel *model; |
2015 | + gchar path[4]; |
2016 | +}; |
2017 | + |
2018 | +static GtkTreeDragSourceIface * |
2019 | +gtk_tree_store_gtk_tree_drag_source_iface = NULL; |
2020 | +static GtkTreeDragDestIface * |
2021 | +gtk_tree_store_gtk_tree_drag_dest_iface = NULL; |
2022 | + |
2023 | +static void |
2024 | +midori_bookmarks_tree_store_drag_source_init (GtkTreeDragSourceIface *iface) |
2025 | +{ |
2026 | + gtk_tree_store_gtk_tree_drag_source_iface = g_type_interface_peek_parent (iface); |
2027 | + |
2028 | + iface->drag_data_get = midori_bookmarks_tree_store_drag_data_get; |
2029 | + iface->drag_data_delete = midori_bookmarks_tree_store_drag_data_delete; |
2030 | +} |
2031 | + |
2032 | +static void |
2033 | +midori_bookmarks_tree_store_drag_dest_init (GtkTreeDragDestIface *iface) |
2034 | +{ |
2035 | + gtk_tree_store_gtk_tree_drag_dest_iface = g_type_interface_peek_parent (iface); |
2036 | + |
2037 | + iface->row_drop_possible = midori_bookmarks_tree_store_row_drop_possible; |
2038 | + iface->drag_data_received = midori_bookmarks_tree_store_drag_data_received; |
2039 | +} |
2040 | + |
2041 | +static void |
2042 | +midori_bookmarks_tree_store_init (MidoriBookmarksTreeStore* item) |
2043 | +{ |
2044 | + item->stock_got_rows = NULL; |
2045 | + item->_view = NULL; |
2046 | +} |
2047 | + |
2048 | +static void |
2049 | +midori_bookmarks_tree_store_class_init (MidoriBookmarksTreeStoreClass *class) |
2050 | +{ |
2051 | +} |
2052 | + |
2053 | +G_DEFINE_TYPE_WITH_CODE (MidoriBookmarksTreeStore, |
2054 | + midori_bookmarks_tree_store, |
2055 | + GTK_TYPE_TREE_STORE, |
2056 | + G_IMPLEMENT_INTERFACE ( |
2057 | + GTK_TYPE_TREE_DRAG_SOURCE, |
2058 | + midori_bookmarks_tree_store_drag_source_init) |
2059 | + G_IMPLEMENT_INTERFACE ( |
2060 | + GTK_TYPE_TREE_DRAG_DEST, |
2061 | + midori_bookmarks_tree_store_drag_dest_init)); |
2062 | + |
2063 | + |
2064 | +GtkTreeStore* |
2065 | +midori_bookmarks_tree_store_new (gint n_columns, ...) |
2066 | +{ |
2067 | + GtkTreeStore* tree_store = GTK_TREE_STORE (g_object_new (MIDORI_BOOKMARKS_TREE_STORE_TYPE, NULL)); |
2068 | + va_list ap; |
2069 | + GType* types; |
2070 | + gint n; |
2071 | + |
2072 | + if (!tree_store) |
2073 | + return NULL; |
2074 | + |
2075 | + types = g_new (GType, n_columns); |
2076 | + |
2077 | + if (!types) |
2078 | + { |
2079 | + g_object_unref(tree_store); |
2080 | + return NULL; |
2081 | + } |
2082 | + |
2083 | + va_start(ap, n_columns); |
2084 | + for (n = 0; n < n_columns; n++) |
2085 | + { |
2086 | + types[n] = va_arg(ap, GType); |
2087 | + } |
2088 | + va_end(ap); |
2089 | + |
2090 | + gtk_tree_store_set_column_types (tree_store, |
2091 | + n_columns, |
2092 | + types); |
2093 | + |
2094 | + g_free (types); |
2095 | + return tree_store; |
2096 | +} |
2097 | + |
2098 | +GtkTreeStore* |
2099 | +midori_bookmarks_tree_store_newv (gint n_columns, GType *types) |
2100 | +{ |
2101 | + GtkTreeStore* tree_store = GTK_TREE_STORE (g_object_new (MIDORI_BOOKMARKS_TREE_STORE_TYPE, NULL)); |
2102 | + |
2103 | + if (!tree_store) |
2104 | + return NULL; |
2105 | + |
2106 | + gtk_tree_store_set_column_types (tree_store, |
2107 | + n_columns, |
2108 | + types); |
2109 | + |
2110 | + return tree_store; |
2111 | +} |
2112 | + |
2113 | gboolean |
2114 | midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, |
2115 | KatzeItem* bookmark_or_parent, |
2116 | @@ -37,6 +182,12 @@ |
2117 | midori_browser_open_bookmark (MidoriBrowser* browser, |
2118 | KatzeItem* item); |
2119 | |
2120 | +static void |
2121 | +midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
2122 | + GtkTreePath* path, |
2123 | + GtkTreeIter* iter, |
2124 | + MidoriBookmarks* bookmarks); |
2125 | + |
2126 | struct _MidoriBookmarks |
2127 | { |
2128 | GtkVBox parent_instance; |
2129 | @@ -50,7 +201,19 @@ |
2130 | gint filter_timeout; |
2131 | gchar* filter; |
2132 | |
2133 | + GList* pending_inserts; |
2134 | KatzeItem* hovering_item; |
2135 | + |
2136 | + struct _stock_pending_event |
2137 | + { |
2138 | + gint x; |
2139 | + gint y; |
2140 | + } *pending_event, |
2141 | + stock_pending_event; |
2142 | + |
2143 | + GHashTable* updated_items; |
2144 | + GList* added_paths; |
2145 | + GList* reordered_paths; |
2146 | }; |
2147 | |
2148 | struct _MidoriBookmarksClass |
2149 | @@ -88,36 +251,47 @@ |
2150 | GParamSpec* pspec); |
2151 | |
2152 | static void |
2153 | -midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
2154 | - GtkTreePath* path, |
2155 | - GtkTreeIter* iter, |
2156 | - MidoriBookmarks* bookmarks); |
2157 | - |
2158 | +midori_bookmarks_update_cb (KatzeArray* array, |
2159 | + MidoriBookmarks* bookmarks); |
2160 | static void |
2161 | midori_bookmarks_add_item_cb (KatzeArray* array, |
2162 | KatzeItem* item, |
2163 | MidoriBookmarks* bookmarks); |
2164 | - |
2165 | static void |
2166 | midori_bookmarks_update_item_cb (KatzeArray* array, |
2167 | - KatzeItem* item, |
2168 | - MidoriBookmarks* bookmarks); |
2169 | - |
2170 | + KatzeItem* item, |
2171 | + MidoriBookmarks* bookmarks); |
2172 | static void |
2173 | midori_bookmarks_remove_item_cb (KatzeArray* array, |
2174 | KatzeItem* item, |
2175 | MidoriBookmarks* bookmarks); |
2176 | |
2177 | static void |
2178 | -midori_bookmarks_update_cb (KatzeArray* array, |
2179 | - MidoriBookmarks* bookmarks); |
2180 | +midori_bookmarks_row_inserted_cb (GtkTreeModel* model, |
2181 | + GtkTreePath* path, |
2182 | + GtkTreeIter* iter, |
2183 | + MidoriBookmarks* bookmarks); |
2184 | +static void |
2185 | +midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
2186 | + GtkTreePath* path, |
2187 | + GtkTreeIter* iter, |
2188 | + MidoriBookmarks* bookmarks); |
2189 | +static void |
2190 | +midori_bookmarks_row_deleted_cb (GtkTreeModel* model, |
2191 | + GtkTreePath* path, |
2192 | + MidoriBookmarks* bookmarks); |
2193 | + |
2194 | +static void |
2195 | +midori_bookmarks_update_item (MidoriBookmarks* bookmarks, KatzeItem *item); |
2196 | |
2197 | static void |
2198 | midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks); |
2199 | |
2200 | static void |
2201 | -midori_bookmarks_add_item (KatzeItem* item, |
2202 | - MidoriBookmarks* bookmarks); |
2203 | +midori_bookmarks_idle_remove_item (MidoriBookmarks* bookmarks, KatzeItem *item); |
2204 | + |
2205 | +static gboolean |
2206 | +midori_bookmarks_idle_func (gpointer data); |
2207 | |
2208 | static void |
2209 | midori_bookmarks_class_init (MidoriBookmarksClass* class) |
2210 | @@ -133,13 +307,13 @@ |
2211 | flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; |
2212 | |
2213 | g_object_class_install_property (gobject_class, |
2214 | - PROP_APP, |
2215 | - g_param_spec_object ( |
2216 | - "app", |
2217 | - "App", |
2218 | - "The app", |
2219 | - MIDORI_TYPE_APP, |
2220 | - flags)); |
2221 | + PROP_APP, |
2222 | + g_param_spec_object ( |
2223 | + "app", |
2224 | + "App", |
2225 | + "The app", |
2226 | + MIDORI_TYPE_APP, |
2227 | + flags)); |
2228 | } |
2229 | |
2230 | static const gchar* |
2231 | @@ -168,7 +342,7 @@ |
2232 | gchar* parent_id; |
2233 | |
2234 | parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid); |
2235 | - if (!(root_array = midori_bookmarks_db_query_recursive (array, "*", "parentid = %q", parent_id, FALSE))) |
2236 | + if (!(root_array = midori_bookmarks_db_query_recursive (array, "*", "parentid = %q", parent_id, "(uri='') ASC, pos_panel DESC", FALSE))) |
2237 | { |
2238 | g_free (parent_id); |
2239 | return; |
2240 | @@ -180,7 +354,7 @@ |
2241 | subarray = katze_array_new (KATZE_TYPE_ARRAY); |
2242 | katze_item_set_name (KATZE_ITEM (subarray), katze_item_get_name (item)); |
2243 | midori_bookmarks_export_array_db (db, subarray, |
2244 | - katze_item_get_meta_integer (item, "parentid")); |
2245 | + katze_item_get_meta_integer (item, "parentid")); |
2246 | katze_array_add_item (array, subarray); |
2247 | } |
2248 | else |
2249 | @@ -201,20 +375,20 @@ |
2250 | |
2251 | if (keyword && *keyword) |
2252 | array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db, |
2253 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword, FALSE); |
2254 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword, NULL, FALSE); |
2255 | else |
2256 | { |
2257 | if (parentid > 0) |
2258 | { |
2259 | gchar* parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid); |
2260 | array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db, |
2261 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id, FALSE); |
2262 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id, "(uri='') ASC, pos_panel DESC", FALSE); |
2263 | |
2264 | g_free (parent_id); |
2265 | } |
2266 | else |
2267 | array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db, |
2268 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL, FALSE); |
2269 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL, "(uri='') ASC, pos_panel DESC", FALSE); |
2270 | } |
2271 | return array ? array : katze_array_new (KATZE_TYPE_ITEM); |
2272 | } |
2273 | @@ -231,24 +405,52 @@ |
2274 | KatzeItem* item; |
2275 | GtkTreeIter child; |
2276 | |
2277 | + g_signal_handlers_block_by_func (model, |
2278 | + midori_bookmarks_row_changed_cb, |
2279 | + bookmarks); |
2280 | + |
2281 | array = midori_bookmarks_read_from_db (bookmarks, parentid, keyword); |
2282 | katze_bookmark_populate_tree_view (array, model, parent); |
2283 | + |
2284 | + g_signal_handlers_unblock_by_func (model, |
2285 | + midori_bookmarks_row_changed_cb, |
2286 | + bookmarks); |
2287 | + |
2288 | /* Remove invisible dummy row */ |
2289 | last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent); |
2290 | if (!last) |
2291 | return; |
2292 | + |
2293 | + g_signal_handlers_block_by_func (model, |
2294 | + midori_bookmarks_row_deleted_cb, |
2295 | + bookmarks); |
2296 | + |
2297 | gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model), &child, parent, last - 1); |
2298 | gtk_tree_model_get (GTK_TREE_MODEL (model), &child, 0, &item, -1); |
2299 | if (KATZE_ITEM_IS_SEPARATOR (item)) |
2300 | gtk_tree_store_remove (model, &child); |
2301 | else |
2302 | g_object_unref (item); |
2303 | + |
2304 | + g_signal_handlers_unblock_by_func (model, |
2305 | + midori_bookmarks_row_deleted_cb, |
2306 | + bookmarks); |
2307 | + |
2308 | } |
2309 | |
2310 | +static void |
2311 | +midori_bookmarks_add_item (KatzeItem* item, |
2312 | + MidoriBookmarks* bookmarks); |
2313 | + |
2314 | +static void |
2315 | +add_parent_to_reorder (GtkTreeModel* model, |
2316 | + GtkTreePath* path, |
2317 | + MidoriBookmarks* bookmarks); |
2318 | + |
2319 | static gboolean |
2320 | midori_bookmarks_reach_item_recurse (GtkTreeModel* model, |
2321 | - GtkTreeIter* iter, |
2322 | - gint64 id) |
2323 | + GtkTreeIter* iter, |
2324 | + gint64 id) |
2325 | { |
2326 | do |
2327 | { |
2328 | @@ -258,7 +460,7 @@ |
2329 | |
2330 | gtk_tree_model_get (model, iter, 0, &item, -1); |
2331 | |
2332 | - if (!KATZE_ITEM_IS_SEPARATOR(item)) |
2333 | + if (item) |
2334 | { |
2335 | itemid = katze_item_get_meta_integer (item, "id"); |
2336 | g_object_unref (item); |
2337 | @@ -267,13 +469,11 @@ |
2338 | if (id == itemid) |
2339 | return TRUE; |
2340 | |
2341 | - if (gtk_tree_model_iter_children (model, &child, iter)) |
2342 | + if (gtk_tree_model_iter_children (model, &child, iter) |
2343 | + && midori_bookmarks_reach_item_recurse (model, &child, id)) |
2344 | { |
2345 | - if (midori_bookmarks_reach_item_recurse (model, &child, id)) |
2346 | - { |
2347 | - *iter = child; |
2348 | - return TRUE; |
2349 | - } |
2350 | + *iter = child; |
2351 | + return TRUE; |
2352 | } |
2353 | } |
2354 | while (gtk_tree_model_iter_next(model, iter)); |
2355 | @@ -283,8 +483,8 @@ |
2356 | |
2357 | static gboolean |
2358 | midori_bookmarks_reach_item (GtkTreeModel* model, |
2359 | - GtkTreeIter* iter, |
2360 | - gint64 id) |
2361 | + GtkTreeIter* iter, |
2362 | + gint64 id) |
2363 | { |
2364 | if (!gtk_tree_model_get_iter_first(model, iter)) |
2365 | return FALSE; |
2366 | @@ -293,38 +493,73 @@ |
2367 | } |
2368 | |
2369 | static void |
2370 | -midori_bookmarks_add_item_to_model(GtkTreeStore* model, |
2371 | - GtkTreeIter* parent, |
2372 | - KatzeItem* item) |
2373 | +midori_bookmarks_add_item_to_model(MidoriBookmarks* bookmarks, |
2374 | + GtkTreeModel* model, |
2375 | + GtkTreeIter* parent, |
2376 | + KatzeItem* item) |
2377 | { |
2378 | + GtkTreeStore* tree_store = GTK_TREE_STORE (model); |
2379 | + gint last; |
2380 | + GtkTreeIter child; |
2381 | + |
2382 | if (KATZE_ITEM_IS_BOOKMARK (item)) |
2383 | { |
2384 | + gint position = 0; |
2385 | + |
2386 | + /* skip the folders to be consistent with the db query order */ |
2387 | + if (gtk_tree_model_iter_children (model, &child, parent)) |
2388 | + while (gtk_tree_model_iter_has_child (model, &child)) |
2389 | + { |
2390 | + position++; |
2391 | + if (!gtk_tree_model_iter_next (model, &child)) |
2392 | + break; |
2393 | + } |
2394 | + |
2395 | gchar* tooltip = g_markup_escape_text (katze_item_get_uri (item), -1); |
2396 | |
2397 | - gtk_tree_store_insert_with_values (model, NULL, parent, |
2398 | - 0, |
2399 | + gtk_tree_store_insert_with_values (tree_store, NULL, parent, |
2400 | + position, |
2401 | 0, item, 1, tooltip, -1); |
2402 | g_free (tooltip); |
2403 | } |
2404 | - else |
2405 | + else if (KATZE_ITEM_IS_FOLDER (item)) |
2406 | { |
2407 | GtkTreeIter root_iter; |
2408 | |
2409 | - gtk_tree_store_insert_with_values (model, &root_iter, parent, |
2410 | + gtk_tree_store_insert_with_values (tree_store, &root_iter, parent, |
2411 | 0, 0, item, -1); |
2412 | |
2413 | /* That's an invisible dummy, so we always have an expander */ |
2414 | - gtk_tree_store_insert_with_values (model, NULL, &root_iter, |
2415 | - 0, |
2416 | - 0, NULL, -1); |
2417 | + gtk_tree_store_insert_with_values (tree_store, NULL, &root_iter, |
2418 | + 0, 0, NULL, -1); |
2419 | } |
2420 | + |
2421 | + /* Remove invisible dummy row */ |
2422 | + last = gtk_tree_model_iter_n_children (model, parent); |
2423 | + if (!last) |
2424 | + return; |
2425 | + |
2426 | + g_signal_handlers_block_by_func (model, |
2427 | + midori_bookmarks_row_deleted_cb, |
2428 | + bookmarks); |
2429 | + |
2430 | + gtk_tree_model_iter_nth_child (model, &child, parent, last - 1); |
2431 | + gtk_tree_model_get (model, &child, 0, &item, -1); |
2432 | + if (KATZE_ITEM_IS_SEPARATOR (item)) |
2433 | + gtk_tree_store_remove (tree_store, &child); |
2434 | + else |
2435 | + g_object_unref (item); |
2436 | + |
2437 | + g_signal_handlers_unblock_by_func (model, |
2438 | + midori_bookmarks_row_deleted_cb, |
2439 | + bookmarks); |
2440 | } |
2441 | |
2442 | static void |
2443 | midori_bookmarks_update_item_in_model(MidoriBookmarks* bookmarks, |
2444 | - GtkTreeStore* model, |
2445 | - GtkTreeIter* iter, |
2446 | - KatzeItem* item) |
2447 | + GtkTreeStore* model, |
2448 | + GtkTreeIter* iter, |
2449 | + KatzeItem* item) |
2450 | { |
2451 | g_signal_handlers_block_by_func (model, |
2452 | midori_bookmarks_row_changed_cb, |
2453 | @@ -350,18 +585,48 @@ |
2454 | bookmarks); |
2455 | } |
2456 | |
2457 | +static gboolean |
2458 | +midori_bookmarks_idle_pending (MidoriBookmarks* bookmarks) |
2459 | +{ |
2460 | + if (bookmarks->pending_inserts |
2461 | + || bookmarks->added_paths |
2462 | + || bookmarks->reordered_paths |
2463 | + || g_hash_table_size (bookmarks->updated_items)) |
2464 | + return TRUE; |
2465 | + return FALSE; |
2466 | +} |
2467 | + |
2468 | +/** |
2469 | + * midori_bookmarks_idle_start: |
2470 | + * @bookmarks: the bookmarks panel |
2471 | + * |
2472 | + * Internal function that checks whether idle processing is pending, |
2473 | + * if not, add a new one. |
2474 | + **/ |
2475 | +static void |
2476 | +midori_bookmarks_idle_start (MidoriBookmarks* bookmarks) |
2477 | +{ |
2478 | + if (midori_bookmarks_idle_pending (bookmarks)) |
2479 | + return; |
2480 | + |
2481 | + g_idle_add (midori_bookmarks_idle_func, bookmarks); |
2482 | +} |
2483 | + |
2484 | static void |
2485 | midori_bookmarks_add_item (KatzeItem* item, |
2486 | MidoriBookmarks* bookmarks); |
2487 | + |
2488 | static void |
2489 | midori_bookmarks_add_item_cb (KatzeArray* array, |
2490 | KatzeItem* item, |
2491 | MidoriBookmarks* bookmarks) |
2492 | { |
2493 | - midori_bookmarks_add_item (item, bookmarks); |
2494 | + midori_bookmarks_idle_start (bookmarks); |
2495 | + |
2496 | + g_object_ref (item); |
2497 | + bookmarks->pending_inserts = g_list_append (bookmarks->pending_inserts, item); |
2498 | } |
2499 | |
2500 | - |
2501 | static void |
2502 | midori_bookmarks_add_item (KatzeItem* item, |
2503 | MidoriBookmarks* bookmarks) |
2504 | @@ -370,18 +635,16 @@ |
2505 | GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
2506 | GtkTreeIter iter; |
2507 | |
2508 | - if (!parentid) |
2509 | - { |
2510 | - midori_bookmarks_add_item_to_model (GTK_TREE_STORE (model), NULL, item); |
2511 | - } |
2512 | + if (parentid == katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id")) |
2513 | + midori_bookmarks_add_item_to_model (bookmarks, model, NULL, item); |
2514 | else if (midori_bookmarks_reach_item (model, &iter, parentid)) |
2515 | { |
2516 | GtkTreePath* path = gtk_tree_model_get_path(model, &iter); |
2517 | + gint n_children = gtk_tree_model_iter_n_children (model, &iter); |
2518 | |
2519 | - if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path)) |
2520 | - { |
2521 | - midori_bookmarks_add_item_to_model (GTK_TREE_STORE (model), &iter, item); |
2522 | - } |
2523 | + if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path) |
2524 | + || !n_children) |
2525 | + midori_bookmarks_add_item_to_model (bookmarks, model, &iter, item); |
2526 | |
2527 | gtk_tree_path_free (path); |
2528 | } |
2529 | @@ -389,8 +652,8 @@ |
2530 | |
2531 | static void |
2532 | midori_bookmarks_update_item_cb (KatzeArray* array, |
2533 | - KatzeItem* item, |
2534 | - MidoriBookmarks* bookmarks) |
2535 | + KatzeItem* item, |
2536 | + MidoriBookmarks* bookmarks) |
2537 | { |
2538 | gint64 id = katze_item_get_meta_integer (item, "id"); |
2539 | gint64 parentid = katze_item_get_meta_integer (item, "parentid"); |
2540 | @@ -433,7 +696,7 @@ |
2541 | midori_bookmarks_add_item (item, bookmarks); |
2542 | } |
2543 | } |
2544 | - else if (parentid == 0) |
2545 | + else if (parentid == katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id")) |
2546 | { |
2547 | midori_bookmarks_update_item_in_model (bookmarks, GTK_TREE_STORE (model), &iter, item); |
2548 | } |
2549 | @@ -457,6 +720,10 @@ |
2550 | GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
2551 | GtkTreeIter iter; |
2552 | |
2553 | + g_assert (KATZE_IS_ITEM (item)); |
2554 | + |
2555 | + midori_bookmarks_idle_remove_item (bookmarks, item); |
2556 | + |
2557 | if (midori_bookmarks_reach_item (model, &iter, id)) |
2558 | { |
2559 | GtkTreeIter parent; |
2560 | @@ -486,12 +753,869 @@ |
2561 | midori_bookmarks_update_cb (KatzeArray* array, |
2562 | MidoriBookmarks* bookmarks) |
2563 | { |
2564 | +#if 1 |
2565 | + g_print ("midori_bookmarks_update_cb: ignored ********\n"); |
2566 | +#else |
2567 | GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
2568 | + |
2569 | gtk_tree_store_clear (GTK_TREE_STORE (model)); |
2570 | midori_bookmarks_read_from_db_to_model (bookmarks, |
2571 | GTK_TREE_STORE (model), NULL, 0, bookmarks->filter); |
2572 | -} |
2573 | - |
2574 | +#endif |
2575 | +} |
2576 | + |
2577 | +gboolean |
2578 | +midori_bookmarks_tree_set_row_drag_data (GtkSelectionData *selection_data, |
2579 | + GtkTreeModel *tree_model, |
2580 | + GList* rows) |
2581 | +{ |
2582 | + TreeRowData *trd; |
2583 | + gint len; |
2584 | + gint struct_size; |
2585 | + gint length; |
2586 | + gint i; |
2587 | + GString *data; |
2588 | + |
2589 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
2590 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE); |
2591 | + g_return_val_if_fail (rows != NULL, FALSE); |
2592 | + |
2593 | + data = g_string_new(""); |
2594 | + |
2595 | + length = g_list_length (rows); |
2596 | + for (i = 0; i < length; i++) |
2597 | + { |
2598 | + GtkTreePath *path = (GtkTreePath *)g_list_nth_data (rows, i); |
2599 | + gchar *path_str = gtk_tree_path_to_string (path); |
2600 | + |
2601 | + g_string_append (data, path_str); |
2602 | + if (i < length-1) |
2603 | + g_string_append_c (data, '\n'); |
2604 | + } |
2605 | + |
2606 | + len = data->len; |
2607 | + |
2608 | + /* the old allocate-end-of-struct-to-hold-string trick */ |
2609 | + struct_size = sizeof (TreeRowData) + len + 1 - |
2610 | + (sizeof (TreeRowData) - G_STRUCT_OFFSET (TreeRowData, path)); |
2611 | + |
2612 | + trd = g_malloc (struct_size); |
2613 | + |
2614 | + strcpy (trd->path, data->str); |
2615 | + |
2616 | + g_string_free (data, TRUE); |
2617 | + |
2618 | + trd->model = tree_model; |
2619 | + |
2620 | + gtk_selection_data_set (selection_data, |
2621 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET), |
2622 | + 8, /* bytes */ |
2623 | + (void*)trd, |
2624 | + struct_size); |
2625 | + |
2626 | + g_free (trd); |
2627 | + |
2628 | + return TRUE; |
2629 | +} |
2630 | + |
2631 | +static gboolean |
2632 | +midori_bookmarks_tree_store_drag_data_get (GtkTreeDragSource* drag_source, |
2633 | + GtkTreePath* source_path, |
2634 | + GtkSelectionData* selection_data) |
2635 | +{ |
2636 | + MidoriBookmarksTreeStore *tree_store; |
2637 | + gboolean status = FALSE; |
2638 | + |
2639 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
2640 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (drag_source), FALSE); |
2641 | + g_return_val_if_fail (source_path != NULL, FALSE); |
2642 | + |
2643 | + tree_store = MIDORI_BOOKMARKS_TREE_STORE(drag_source); |
2644 | + |
2645 | + if (tree_store->stock_got_rows) |
2646 | + { |
2647 | + g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free); |
2648 | + tree_store->stock_got_rows = NULL; |
2649 | + } |
2650 | + |
2651 | + if (gtk_selection_data_get_target (selection_data) == |
2652 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET)) |
2653 | + { |
2654 | + GtkTreeModel *model; |
2655 | + GList* rows; |
2656 | + if (katze_tree_view_get_selected_rows ( |
2657 | + tree_store->_view, &model, &rows)) |
2658 | + { |
2659 | + status = midori_bookmarks_tree_set_row_drag_data (selection_data, model, rows); |
2660 | + |
2661 | + tree_store->stock_got_rows = rows; |
2662 | + } |
2663 | + } |
2664 | + |
2665 | + return status; |
2666 | +} |
2667 | + |
2668 | +static void |
2669 | +update_path_list_for_insert (GList * rows, GtkTreePath* path) |
2670 | +{ |
2671 | + gint length = g_list_length (rows); |
2672 | + gint i; |
2673 | + |
2674 | + for (i = 0; i < length; i++ ) |
2675 | + { |
2676 | + GtkTreePath *src_path_r = (GtkTreePath *)g_list_nth_data (rows, i); |
2677 | + gint la = gtk_tree_path_get_depth (path); |
2678 | + gint lb = gtk_tree_path_get_depth (src_path_r); |
2679 | + gint *ia = gtk_tree_path_get_indices (path); |
2680 | + gint *ib = gtk_tree_path_get_indices (src_path_r); |
2681 | + gint j; |
2682 | + |
2683 | + if (la > lb) /* insert was donne in a deeper branch than source */ |
2684 | + continue; |
2685 | + |
2686 | + if (ia[la-1] > ib[la-1]) /* insert was donne after source */ |
2687 | + continue; |
2688 | + |
2689 | + for (j = 0; j < la; j++) |
2690 | + { |
2691 | + if (ia[j] != ib[j]) break; |
2692 | + } |
2693 | + |
2694 | + if (j < la-1) /* insert and source are not in the same branch */ |
2695 | + continue; |
2696 | + |
2697 | + /* source at depth level of insert must be incremented due to the insert */ |
2698 | + ib[la-1] += 1; |
2699 | + } |
2700 | +} |
2701 | + |
2702 | +static gint |
2703 | +midori_tree_path_compare (const GtkTreePath *a, |
2704 | + const GtkTreePath *b) |
2705 | +{ |
2706 | + if (!gtk_tree_path_get_depth ((GtkTreePath *)a)) |
2707 | + { |
2708 | + if (!gtk_tree_path_get_depth ((GtkTreePath *)b)) |
2709 | + return 0; |
2710 | + |
2711 | + return -1; |
2712 | + } |
2713 | + |
2714 | + if (!gtk_tree_path_get_depth ((GtkTreePath *)b)) |
2715 | + return 1; |
2716 | + |
2717 | + return gtk_tree_path_compare (a, b); |
2718 | +} |
2719 | + |
2720 | +static GList* |
2721 | +update_path_list_for_delete (GList* rows, GtkTreePath* removed_path) |
2722 | +{ |
2723 | + GList* new_rows = rows; |
2724 | + |
2725 | + while (rows) |
2726 | + { |
2727 | + GtkTreePath *source_path = (GtkTreePath *)rows->data; |
2728 | + gint la = gtk_tree_path_get_depth (removed_path); |
2729 | + gint lb = gtk_tree_path_get_depth (source_path); |
2730 | + gint *ia = gtk_tree_path_get_indices (removed_path); |
2731 | + gint *ib = gtk_tree_path_get_indices (source_path); |
2732 | + gint cmp = midori_tree_path_compare (removed_path, source_path); |
2733 | + gint j; |
2734 | + |
2735 | + if (cmp == 1) /* removal was done after source => kip source as it is */ |
2736 | + goto keep_source; |
2737 | + |
2738 | + if (cmp == 0) /* source is removed => remove source */ |
2739 | + goto remove_source; |
2740 | + |
2741 | + /* if removal is an ancestor of the source => remove source */ |
2742 | + if (gtk_tree_path_is_ancestor (removed_path, source_path)) |
2743 | + goto remove_source; |
2744 | + |
2745 | + if (la > lb) /* removal was donne in a deeper branch than source */ |
2746 | + goto keep_source; |
2747 | + |
2748 | + for (j = 0; j < la; j++) |
2749 | + { |
2750 | + if (ia[j] != ib[j]) break; |
2751 | + } |
2752 | + |
2753 | + if (j < la-1) /* removal and source are not in the same branch */ |
2754 | + goto keep_source; |
2755 | + |
2756 | + /* source at depth level of removal must be decremented due to the removal */ |
2757 | + ib[la-1] -= 1; |
2758 | + |
2759 | + if (ib[la-1] >= 0) |
2760 | + goto keep_source; |
2761 | + |
2762 | + remove_source: |
2763 | + /* remove source entry */ |
2764 | + gtk_tree_path_free (source_path); |
2765 | + { |
2766 | + GList *next_rows = g_list_next (rows); |
2767 | + new_rows = g_list_delete_link (new_rows, rows); |
2768 | + rows = next_rows; |
2769 | + } |
2770 | + continue; |
2771 | + |
2772 | + keep_source: |
2773 | + rows = g_list_next (rows); |
2774 | + } |
2775 | + |
2776 | + return new_rows; |
2777 | +} |
2778 | + |
2779 | +static gboolean |
2780 | +midori_bookmarks_tree_store_drag_data_delete (GtkTreeDragSource* drag_source, |
2781 | + GtkTreePath* source_path) |
2782 | +{ |
2783 | + gboolean status = TRUE; |
2784 | + MidoriBookmarksTreeStore *tree_store = MIDORI_BOOKMARKS_TREE_STORE(drag_source); |
2785 | + GtkTreeModel* model = GTK_TREE_MODEL(drag_source); |
2786 | + |
2787 | + if (!tree_store->stock_got_rows) |
2788 | + return TRUE; |
2789 | + |
2790 | + while (tree_store->stock_got_rows) |
2791 | + { |
2792 | + GtkTreePath *prev = (GtkTreePath *)tree_store->stock_got_rows->data; |
2793 | + GtkTreeIter iter; |
2794 | + |
2795 | + tree_store->stock_got_rows = g_list_delete_link (tree_store->stock_got_rows, |
2796 | + tree_store->stock_got_rows); |
2797 | + |
2798 | + if (gtk_tree_model_get_iter (model, &iter, prev)) |
2799 | + { |
2800 | + /* remove item updating source paths */ |
2801 | + gtk_tree_store_remove (GTK_TREE_STORE (drag_source), &iter); |
2802 | + |
2803 | + tree_store->stock_got_rows = update_path_list_for_delete (tree_store->stock_got_rows, prev); |
2804 | + } |
2805 | + else |
2806 | + status = FALSE; |
2807 | + |
2808 | + gtk_tree_path_free (prev); |
2809 | + } |
2810 | + |
2811 | + return status; |
2812 | +} |
2813 | + |
2814 | +static gboolean |
2815 | +midori_bookmarks_tree_store_get_rows_drag_data (GtkSelectionData *selection_data, |
2816 | + GtkTreeModel **tree_model, |
2817 | + GList **rows) |
2818 | +{ |
2819 | + TreeRowData *trd; |
2820 | + |
2821 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
2822 | + |
2823 | + if (tree_model) |
2824 | + *tree_model = NULL; |
2825 | + |
2826 | + if (rows) |
2827 | + *rows = NULL; |
2828 | + |
2829 | + if (gtk_selection_data_get_target (selection_data) != |
2830 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET)) |
2831 | + return FALSE; |
2832 | + |
2833 | + if (gtk_selection_data_get_length (selection_data) < 0) |
2834 | + return FALSE; |
2835 | + |
2836 | + trd = (void*) gtk_selection_data_get_data (selection_data); |
2837 | + |
2838 | + if (tree_model) |
2839 | + *tree_model = trd->model; |
2840 | + |
2841 | + if (rows) |
2842 | + { |
2843 | + GList *list = NULL; |
2844 | + gchar *trd_path = g_strdup (trd->path); |
2845 | + gchar *path_str; |
2846 | + |
2847 | + path_str = strtok(trd_path, "\n"); |
2848 | + while (path_str && *path_str) |
2849 | + { |
2850 | + list = g_list_append (list, gtk_tree_path_new_from_string (path_str)); |
2851 | + path_str = strtok (NULL, "\n"); |
2852 | + } |
2853 | + |
2854 | + *rows = list; |
2855 | + g_free (trd_path); |
2856 | + } |
2857 | + |
2858 | + return TRUE; |
2859 | +} |
2860 | + |
2861 | +#if !GTK_CHECK_VERSION (3,0,0) |
2862 | +gboolean |
2863 | +gtk_tree_model_iter_previous (GtkTreeModel *tree_model, |
2864 | + GtkTreeIter *iter) |
2865 | +{ |
2866 | + GtkTreePath* path = gtk_tree_model_get_path (tree_model, iter); |
2867 | + gboolean result = gtk_tree_path_prev (path); |
2868 | + |
2869 | + if (result) |
2870 | + result = gtk_tree_model_get_iter (tree_model, iter, path); |
2871 | + else |
2872 | + { |
2873 | + GtkTreeIter invalid = {0}; |
2874 | + *iter = invalid; |
2875 | + } |
2876 | + |
2877 | + gtk_tree_path_free (path); |
2878 | + return result; |
2879 | +} |
2880 | +#endif |
2881 | + |
2882 | +static gboolean |
2883 | +midori_bookmarks_tree_store_row_drop_possible (GtkTreeDragDest* drag_dest, |
2884 | + GtkTreePath* dest_path, |
2885 | + GtkSelectionData* selection_data) |
2886 | +{ |
2887 | + GtkTreeModel* dest_model = GTK_TREE_MODEL(drag_dest); |
2888 | + GtkTreePath *parent; |
2889 | + GtkTreeIter dest_parent; |
2890 | + GtkTreeIter *dest_parent_p = NULL; |
2891 | + gboolean row_drop_possible = TRUE; |
2892 | + GtkTreeViewDropPosition drop_position; |
2893 | + |
2894 | + gtk_tree_view_get_drag_dest_row (MIDORI_BOOKMARKS_TREE_STORE (dest_model)->_view, |
2895 | + NULL, &drop_position); |
2896 | + |
2897 | + parent = gtk_tree_path_copy (dest_path); |
2898 | + if ((gtk_tree_path_get_depth (parent) > 1) |
2899 | + && gtk_tree_path_up (parent) |
2900 | + && gtk_tree_model_get_iter (dest_model, &dest_parent, parent)) |
2901 | + dest_parent_p = &dest_parent; |
2902 | + |
2903 | + gtk_tree_path_free (parent); |
2904 | + |
2905 | + if (dest_parent_p) |
2906 | + { |
2907 | + KatzeItem* item; |
2908 | + |
2909 | + gtk_tree_model_get (dest_model, dest_parent_p, 0, &item, -1); |
2910 | + |
2911 | + if (!KATZE_ITEM_IS_FOLDER (item)) |
2912 | + { |
2913 | +#ifdef DEBUG_DROP |
2914 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
2915 | + |
2916 | + g_print ("%s: can only drop into folders\n", dest_path_str); |
2917 | + g_free (dest_path_str); |
2918 | +#endif /* DEBUG_DROP */ |
2919 | + row_drop_possible = FALSE; |
2920 | + } |
2921 | + |
2922 | + if (item) |
2923 | + g_object_unref (item); |
2924 | + } |
2925 | + |
2926 | + if (row_drop_possible |
2927 | + && (gtk_selection_data_get_target (selection_data) == |
2928 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET))) |
2929 | + { |
2930 | + GtkTreeModel *src_model; |
2931 | + GList* rows; |
2932 | + |
2933 | + if (midori_bookmarks_tree_store_get_rows_drag_data (selection_data, |
2934 | + &src_model, &rows)) |
2935 | + { |
2936 | + GtkTreeIter dest_iter; |
2937 | + GList* src_row; |
2938 | + gboolean dest_is_folder = FALSE; |
2939 | + /* gboolean dest_is_bookmark = FALSE; */ |
2940 | + gboolean src_has_folders = FALSE; |
2941 | + gboolean src_has_bookmarks = FALSE; |
2942 | + |
2943 | + if (gtk_tree_model_get_iter (dest_model, &dest_iter, dest_path)) |
2944 | + { |
2945 | + if (gtk_tree_model_iter_has_child (dest_model, &dest_iter)) |
2946 | + dest_is_folder = TRUE; |
2947 | +/* |
2948 | + else |
2949 | + { |
2950 | + KatzeItem* item; |
2951 | + gtk_tree_model_get (dest_model, &dest_iter, 0, &item, -1); |
2952 | + if (item) |
2953 | + { |
2954 | + dest_is_bookmark = TRUE; |
2955 | + g_object_unref (item); |
2956 | + } |
2957 | + } |
2958 | +*/ |
2959 | + } |
2960 | + |
2961 | + for (src_row = rows ; src_row ; src_row = g_list_next (src_row)) |
2962 | + { |
2963 | + GtkTreePath* src_path = (GtkTreePath*)src_row->data; |
2964 | + GtkTreeIter src_iter; |
2965 | + KatzeItem* item; |
2966 | + |
2967 | + if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path)) |
2968 | + continue; |
2969 | + |
2970 | + gtk_tree_model_get (src_model, &src_iter, 0, &item, -1); |
2971 | + if (item) |
2972 | + { |
2973 | + if (!src_has_folders && KATZE_ITEM_IS_FOLDER (item)) |
2974 | + src_has_folders = TRUE; |
2975 | + else if (!src_has_bookmarks && KATZE_ITEM_IS_BOOKMARK (item)) |
2976 | + src_has_bookmarks = TRUE; |
2977 | + |
2978 | + g_object_unref (item); |
2979 | + } |
2980 | + if (src_has_bookmarks && src_has_folders) |
2981 | + break; |
2982 | + } |
2983 | + |
2984 | + if (src_has_bookmarks) |
2985 | + { |
2986 | + switch (drop_position) |
2987 | + { |
2988 | + case GTK_TREE_VIEW_DROP_BEFORE: |
2989 | + case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: |
2990 | + if (dest_is_folder) |
2991 | + { |
2992 | +#ifdef DEBUG_DROP |
2993 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
2994 | + |
2995 | + g_print ("%s: cannot drop bookmarks in folders group\n", dest_path_str); |
2996 | + g_free (dest_path_str); |
2997 | +#endif /* DEBUG_DROP */ |
2998 | + row_drop_possible = FALSE; |
2999 | + goto done; |
3000 | + } |
3001 | + break; |
3002 | + case GTK_TREE_VIEW_DROP_AFTER: |
3003 | + case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: |
3004 | + if (dest_is_folder) |
3005 | + { |
3006 | + gboolean next_dest_is_folder = FALSE; |
3007 | + |
3008 | + if (gtk_tree_model_iter_next (dest_model, &dest_iter)) |
3009 | + if (gtk_tree_model_iter_has_child (dest_model, &dest_iter)) |
3010 | + next_dest_is_folder = TRUE; |
3011 | + |
3012 | + if (next_dest_is_folder) |
3013 | + { |
3014 | +#ifdef DEBUG_DROP |
3015 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
3016 | + |
3017 | + g_print ("%s: cannot drop bookmarks in folders group\n", dest_path_str); |
3018 | + g_free (dest_path_str); |
3019 | +#endif /* DEBUG_DROP */ |
3020 | + row_drop_possible = FALSE; |
3021 | + goto done; |
3022 | + } |
3023 | + } |
3024 | + break; |
3025 | + default: |
3026 | + break; |
3027 | + } |
3028 | + } |
3029 | + else if (src_has_folders) |
3030 | + { |
3031 | + gboolean prev_dest_is_folder = TRUE; |
3032 | + |
3033 | + if (gtk_tree_model_iter_previous (dest_model, &dest_iter)) |
3034 | + if (!gtk_tree_model_iter_has_child (dest_model, &dest_iter)) |
3035 | + prev_dest_is_folder = FALSE; |
3036 | + |
3037 | + if (!prev_dest_is_folder) |
3038 | + { |
3039 | +#ifdef DEBUG_DROP |
3040 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
3041 | + |
3042 | + g_print ("%s: cannot drop folders in bookmarks group\n", dest_path_str); |
3043 | + g_free (dest_path_str); |
3044 | +#endif /* DEBUG_DROP */ |
3045 | + row_drop_possible = FALSE; |
3046 | + goto done; |
3047 | + } |
3048 | + } |
3049 | + |
3050 | + if (src_model == dest_model) |
3051 | + { |
3052 | + for (src_row = rows ; src_row ; src_row = g_list_next (src_row)) |
3053 | + { |
3054 | + GtkTreePath* src_path = (GtkTreePath*)src_row->data; |
3055 | + |
3056 | + /* Can't drop into ourself. */ |
3057 | + if (gtk_tree_path_is_ancestor (src_path, dest_path)) |
3058 | + { |
3059 | +#ifdef DEBUG_DROP |
3060 | + g_print ("cannot drop into source folders\n"); |
3061 | +#endif /* DEBUG_DROP */ |
3062 | + row_drop_possible = FALSE; |
3063 | + goto done; |
3064 | + } |
3065 | + update_path_list_for_insert (rows, dest_path); |
3066 | + } |
3067 | + } |
3068 | + done: |
3069 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3070 | + } |
3071 | + else |
3072 | + row_drop_possible = FALSE; |
3073 | + } |
3074 | + else |
3075 | + row_drop_possible = FALSE; |
3076 | + |
3077 | +#ifdef DEBUG_DROP |
3078 | + if (row_drop_possible) |
3079 | + { |
3080 | + gchar *dest_path_str = gtk_tree_path_to_string (dest_path); |
3081 | + gchar *drop_position_str = "unknown"; |
3082 | + switch (drop_position) |
3083 | + { |
3084 | + case GTK_TREE_VIEW_DROP_BEFORE: |
3085 | + drop_position_str = "before"; |
3086 | + break; |
3087 | + case GTK_TREE_VIEW_DROP_AFTER: |
3088 | + drop_position_str = "after"; |
3089 | + break; |
3090 | + case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: |
3091 | + drop_position_str = "into or before"; |
3092 | + break; |
3093 | + case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: |
3094 | + drop_position_str = "into or after"; |
3095 | + break; |
3096 | + } |
3097 | + |
3098 | + g_print ("%s: row drop possible (%s)\n", dest_path_str, drop_position_str); |
3099 | + g_free (dest_path_str); |
3100 | + } |
3101 | +#endif /* DEBUG_DROP */ |
3102 | + |
3103 | + return row_drop_possible; |
3104 | +} |
3105 | + |
3106 | +static void |
3107 | +copy_node_data (GtkTreeStore *src_store, |
3108 | + GtkTreeIter *src_iter, |
3109 | + GtkTreeStore *dest_store, |
3110 | + GtkTreeIter *dest_iter) |
3111 | +{ |
3112 | + gint i; |
3113 | + gint n_columns; |
3114 | + GtkTreeModel* src_model = GTK_TREE_MODEL (src_store); |
3115 | + |
3116 | + n_columns = gtk_tree_model_get_n_columns (src_model); |
3117 | + |
3118 | + for (i = 0; i < n_columns; i++) |
3119 | + { |
3120 | + void *item; |
3121 | + |
3122 | + gtk_tree_model_get (src_model, src_iter, i, &item, -1); |
3123 | + gtk_tree_store_set (dest_store, dest_iter, i, item, -1); |
3124 | + } |
3125 | +} |
3126 | + |
3127 | +static void |
3128 | +recursive_node_copy (GtkTreeStore *src_store, |
3129 | + GtkTreeIter *src_iter, |
3130 | + GtkTreeStore *dest_store, |
3131 | + GtkTreeIter *dest_iter) |
3132 | +{ |
3133 | + GtkTreeIter child; |
3134 | + GtkTreeModel *src_model = GTK_TREE_MODEL (src_store); |
3135 | + |
3136 | + copy_node_data (src_store, src_iter, dest_store, dest_iter); |
3137 | + |
3138 | + if (gtk_tree_model_iter_children (src_model, &child, src_iter)) |
3139 | + { |
3140 | + /* Need to create children and recurse. Note our |
3141 | + * dependence on persistent iterators here. |
3142 | + */ |
3143 | + do |
3144 | + { |
3145 | + GtkTreeIter copy; |
3146 | + |
3147 | + /* Gee, a really slow algorithm... ;-) FIXME */ |
3148 | + gtk_tree_store_append (dest_store, |
3149 | + ©, |
3150 | + dest_iter); |
3151 | + |
3152 | + recursive_node_copy (src_store, &child, dest_store, ©); |
3153 | + } |
3154 | + while (gtk_tree_model_iter_next (src_model, &child)); |
3155 | + } |
3156 | +} |
3157 | + |
3158 | +static gboolean |
3159 | +midori_bookmarks_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, |
3160 | + GtkTreePath *dest_path, |
3161 | + GtkSelectionData *selection_data) |
3162 | +{ |
3163 | + gboolean status = TRUE; |
3164 | + |
3165 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
3166 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (drag_dest), FALSE); |
3167 | + g_return_val_if_fail (dest_path != NULL, FALSE); |
3168 | + |
3169 | + if (gtk_selection_data_get_target (selection_data) == |
3170 | + gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET)) |
3171 | + { |
3172 | + GtkTreeStore *dest_store = GTK_TREE_STORE (drag_dest); |
3173 | + GtkTreeModel *dest_model = GTK_TREE_MODEL (drag_dest); |
3174 | + GtkTreeModel *src_model; |
3175 | + GList* rows; |
3176 | + |
3177 | + if (midori_bookmarks_tree_store_get_rows_drag_data (selection_data, |
3178 | + &src_model, &rows)) |
3179 | + { |
3180 | + GtkTreeStore *src_store = GTK_TREE_STORE (src_model); |
3181 | + GtkTreePath *prev = gtk_tree_path_copy (dest_path); |
3182 | + |
3183 | + gint count = 0; |
3184 | + gint length = g_list_length (rows); |
3185 | + gint i; |
3186 | + |
3187 | + for (i = 0; i < length; i++) |
3188 | + { |
3189 | + GtkTreeIter dest_iter; |
3190 | + GtkTreeIter src_iter; |
3191 | + GtkTreePath *src_path = (GtkTreePath *)g_list_nth_data (rows, i); |
3192 | + |
3193 | + if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path)) |
3194 | + continue; |
3195 | + |
3196 | + /* Get the path to insert _after_ (dest is the path to insert _before_) */ |
3197 | + if (i == 0) |
3198 | + { |
3199 | + if (!gtk_tree_path_prev (prev)) |
3200 | + { /* Get the parent, NULL if parent is the root */ |
3201 | + GtkTreeIter dest_parent; |
3202 | + GtkTreePath *parent = gtk_tree_path_copy (dest_path); |
3203 | + GtkTreeIter *dest_parent_p = NULL; |
3204 | + |
3205 | + if (gtk_tree_path_up (parent) && |
3206 | + gtk_tree_path_get_depth (parent) > 0) |
3207 | + { |
3208 | + gtk_tree_model_get_iter (dest_model, |
3209 | + &dest_parent, parent); |
3210 | + dest_parent_p = &dest_parent; |
3211 | + } |
3212 | + gtk_tree_path_free (parent); |
3213 | + |
3214 | + gtk_tree_store_prepend (dest_store, &dest_iter, dest_parent_p); |
3215 | + } |
3216 | + else if (gtk_tree_model_get_iter (dest_model, &dest_iter, prev)) |
3217 | + { |
3218 | + GtkTreeIter tmp_iter = dest_iter; |
3219 | + |
3220 | + gtk_tree_store_insert_after (dest_store, &dest_iter, NULL, |
3221 | + &tmp_iter); |
3222 | + } |
3223 | + } |
3224 | + else if (gtk_tree_model_get_iter (dest_model, &dest_iter, prev)) |
3225 | + { |
3226 | + GtkTreeIter tmp_iter = dest_iter; |
3227 | + |
3228 | + gtk_tree_store_insert_after (dest_store, &dest_iter, NULL, |
3229 | + &tmp_iter); |
3230 | + } |
3231 | + |
3232 | + gtk_tree_path_free (prev); |
3233 | + |
3234 | + recursive_node_copy (src_store, &src_iter, dest_store, &dest_iter); |
3235 | + count++; |
3236 | + |
3237 | + prev = gtk_tree_model_get_path (dest_model, &dest_iter); |
3238 | + |
3239 | + if (src_store != dest_store) |
3240 | + continue; |
3241 | + |
3242 | + update_path_list_for_insert (rows, prev); |
3243 | + } |
3244 | + |
3245 | + gtk_tree_path_free (prev); |
3246 | + |
3247 | + g_assert (count == length); |
3248 | + |
3249 | + if (src_store == dest_store) |
3250 | + { |
3251 | + MidoriBookmarksTreeStore *tree_store = MIDORI_BOOKMARKS_TREE_STORE(src_store); |
3252 | + |
3253 | + g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free); |
3254 | + tree_store->stock_got_rows = rows; |
3255 | + } |
3256 | + else |
3257 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3258 | + } |
3259 | + } |
3260 | + |
3261 | + return status; |
3262 | +} |
3263 | + |
3264 | +static void |
3265 | +midori_bookmarks_set_item_positon (GtkTreeModel* model, |
3266 | + GtkTreeIter* iter, |
3267 | + gint64 parentid, |
3268 | + MidoriBookmarks* bookmarks) |
3269 | +{ |
3270 | + KatzeItem* item; |
3271 | + gint position = 0; |
3272 | + GtkTreeIter next = *iter; |
3273 | + |
3274 | + do { |
3275 | + gboolean update = FALSE; |
3276 | + gtk_tree_model_get (model, &next, 0, &item, -1); |
3277 | + |
3278 | + if (!KATZE_IS_ITEM (item)) |
3279 | + continue; |
3280 | + |
3281 | + if (position != katze_item_get_meta_integer (item, "pos_panel")) |
3282 | + { |
3283 | + katze_item_set_meta_integer (item, "pos_panel", position); |
3284 | + update = TRUE; |
3285 | + } |
3286 | + if (parentid != katze_item_get_meta_integer (item, "parentid")) |
3287 | + { |
3288 | + katze_item_set_meta_integer (item, "parentid", parentid); |
3289 | + update = TRUE; |
3290 | + } |
3291 | + |
3292 | + if (update) |
3293 | + midori_bookmarks_update_item (bookmarks, item); |
3294 | + |
3295 | + position++; |
3296 | + |
3297 | + g_object_unref (item); |
3298 | + } |
3299 | + while (gtk_tree_model_iter_next (model, &next)); |
3300 | +} |
3301 | + |
3302 | +static void |
3303 | +assert_reorder_are_folders (GtkTreeModel* model, |
3304 | + MidoriBookmarks* bookmarks) |
3305 | +{ |
3306 | + GList* iter; |
3307 | + for (iter = bookmarks->reordered_paths; iter ; iter = g_list_next (iter)) |
3308 | + { |
3309 | + GtkTreePath* path = (GtkTreePath*)iter->data; |
3310 | + GtkTreeIter tree_iter; |
3311 | + |
3312 | + if (!gtk_tree_path_get_depth (path)) |
3313 | + continue; |
3314 | + |
3315 | + if (gtk_tree_model_get_iter (model, &tree_iter, path)) |
3316 | + { |
3317 | + KatzeItem *item; |
3318 | + |
3319 | + gtk_tree_model_get (model, &tree_iter, 0, &item, -1); |
3320 | + |
3321 | + g_assert (KATZE_ITEM_IS_FOLDER (item)); |
3322 | + } |
3323 | + } |
3324 | +} |
3325 | + |
3326 | +static void |
3327 | +add_parent_to_reorder (GtkTreeModel* model, |
3328 | + GtkTreePath* path, |
3329 | + MidoriBookmarks* bookmarks) |
3330 | +{ |
3331 | + GtkTreePath* path_copy = gtk_tree_path_copy (path); |
3332 | + GList* found; |
3333 | + |
3334 | + midori_bookmarks_idle_start (bookmarks); |
3335 | + |
3336 | + if (gtk_tree_path_get_depth (path_copy) > 1 |
3337 | + && gtk_tree_path_up (path_copy)) |
3338 | + { |
3339 | + GtkTreeIter iter; |
3340 | + if (gtk_tree_model_get_iter (model, &iter, path_copy)) |
3341 | + { |
3342 | + KatzeItem* item; |
3343 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
3344 | + if (item) |
3345 | + { |
3346 | + g_assert (KATZE_ITEM_IS_FOLDER (item)); |
3347 | + g_object_unref (item); |
3348 | + } |
3349 | + else |
3350 | + g_assert_not_reached (); |
3351 | + } |
3352 | + else |
3353 | + g_assert_not_reached (); |
3354 | + } |
3355 | + else |
3356 | + { |
3357 | + gtk_tree_path_free (path_copy); |
3358 | + path_copy = gtk_tree_path_new (); |
3359 | + } |
3360 | + |
3361 | + if ((found = g_list_find_custom (bookmarks->reordered_paths, |
3362 | + path_copy, (GCompareFunc)midori_tree_path_compare)) != NULL) |
3363 | + { |
3364 | + gtk_tree_path_free (path_copy); |
3365 | + return; |
3366 | + } |
3367 | + |
3368 | + bookmarks->reordered_paths = g_list_append (bookmarks->reordered_paths, path_copy); |
3369 | +} |
3370 | + |
3371 | +static void |
3372 | +midori_bookmarks_row_inserted_cb (GtkTreeModel* model, |
3373 | + GtkTreePath* path, |
3374 | + GtkTreeIter* iter, |
3375 | + MidoriBookmarks* bookmarks) |
3376 | +{ |
3377 | + midori_bookmarks_idle_start (bookmarks); |
3378 | + |
3379 | + update_path_list_for_insert (bookmarks->added_paths, path); |
3380 | + update_path_list_for_insert (bookmarks->reordered_paths, path); |
3381 | + assert_reorder_are_folders (model, bookmarks); |
3382 | + |
3383 | + if (g_list_find_custom (bookmarks->added_paths, |
3384 | + path, (GCompareFunc)midori_tree_path_compare)) |
3385 | + return; |
3386 | + |
3387 | + bookmarks->added_paths = g_list_append (bookmarks->added_paths, gtk_tree_path_copy (path)); |
3388 | +} |
3389 | + |
3390 | +#ifdef DEBUG_LIST |
3391 | +static void |
3392 | +print_path_list (GList* iter) |
3393 | +{ |
3394 | + for ( ; iter ; iter = g_list_next (iter)) |
3395 | + { |
3396 | + gchar* str = gtk_tree_path_to_string ((GtkTreePath*)iter->data); |
3397 | + g_print ("%s ", str); |
3398 | + g_free (str); |
3399 | + } |
3400 | + g_print ("\n"); |
3401 | +} |
3402 | +#endif /* DEBUG_LIST */ |
3403 | + |
3404 | +static void |
3405 | +midori_bookmarks_row_deleted_cb (GtkTreeModel* model, |
3406 | + GtkTreePath* path, |
3407 | + MidoriBookmarks* bookmarks) |
3408 | +{ |
3409 | +#ifdef DEBUG_LIST |
3410 | + gchar* str = gtk_tree_path_to_string (path); |
3411 | + g_print ("midori_bookmarks_row_deleted_cb: path: %s\n", str); |
3412 | + g_free (str); |
3413 | +#endif /* DEBUG_LIST */ |
3414 | + |
3415 | + midori_bookmarks_idle_start (bookmarks); |
3416 | + |
3417 | + bookmarks->added_paths = update_path_list_for_delete (bookmarks->added_paths, path); |
3418 | +#ifdef DEBUG_LIST |
3419 | + print_path_list (bookmarks->reordered_paths); |
3420 | +#endif /* DEBUG_LIST */ |
3421 | + bookmarks->reordered_paths = update_path_list_for_delete (bookmarks->reordered_paths, path); |
3422 | +#ifdef DEBUG_LIST |
3423 | + print_path_list (bookmarks->reordered_paths); |
3424 | +#endif /* DEBUG_LIST */ |
3425 | + assert_reorder_are_folders (model, bookmarks); |
3426 | + add_parent_to_reorder (model, path, bookmarks); |
3427 | + assert_reorder_are_folders (model, bookmarks); |
3428 | +} |
3429 | |
3430 | static void |
3431 | midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
3432 | @@ -499,41 +1623,8 @@ |
3433 | GtkTreeIter* iter, |
3434 | MidoriBookmarks* bookmarks) |
3435 | { |
3436 | - KatzeItem* item; |
3437 | - GtkTreeIter parent; |
3438 | - KatzeItem* new_parent = NULL; |
3439 | - gint64 parentid; |
3440 | - |
3441 | - gtk_tree_model_get (model, iter, 0, &item, -1); |
3442 | - |
3443 | - if (gtk_tree_model_iter_parent (model, &parent, iter)) |
3444 | - { |
3445 | - gtk_tree_model_get (model, &parent, 0, &new_parent, -1); |
3446 | - |
3447 | - /* Bookmarks must not be moved into non-folder items */ |
3448 | - if (!KATZE_ITEM_IS_FOLDER (new_parent)) |
3449 | - parentid = 0; |
3450 | - else |
3451 | - parentid = katze_item_get_meta_integer (new_parent, "id"); |
3452 | - } |
3453 | - else |
3454 | - parentid = 0; |
3455 | - |
3456 | - katze_item_set_meta_integer (item, "parentid", parentid); |
3457 | - |
3458 | - g_signal_handlers_block_by_func (bookmarks->bookmarks_db, |
3459 | - midori_bookmarks_update_item_cb, |
3460 | - bookmarks); |
3461 | - |
3462 | - midori_bookmarks_db_update_item (bookmarks->bookmarks_db, item); |
3463 | - |
3464 | - g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db, |
3465 | - midori_bookmarks_update_item_cb, |
3466 | - bookmarks); |
3467 | - |
3468 | - g_object_unref (item); |
3469 | - if (new_parent) |
3470 | - g_object_unref (new_parent); |
3471 | + add_parent_to_reorder (model, path, bookmarks); |
3472 | + assert_reorder_are_folders (model, bookmarks); |
3473 | } |
3474 | |
3475 | static void |
3476 | @@ -596,7 +1687,7 @@ |
3477 | GtkTreeIter iter; |
3478 | |
3479 | if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview), |
3480 | - &model, &iter)) |
3481 | + &model, &iter)) |
3482 | { |
3483 | KatzeItem* item; |
3484 | MidoriBrowser* browser; |
3485 | @@ -616,15 +1707,17 @@ |
3486 | static void |
3487 | midori_bookmarks_toolbar_update (MidoriBookmarks *bookmarks) |
3488 | { |
3489 | - gboolean selected; |
3490 | + gint selected; |
3491 | |
3492 | - selected = katze_tree_view_get_selected_iter ( |
3493 | + selected = katze_tree_view_get_selected_rows ( |
3494 | GTK_TREE_VIEW (bookmarks->treeview), NULL, NULL); |
3495 | - gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->delete), selected); |
3496 | - gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->edit), selected); |
3497 | + gtk_widget_set_sensitive ( |
3498 | + GTK_WIDGET (bookmarks->delete), (selected > 0 ? TRUE : FALSE)); |
3499 | + gtk_widget_set_sensitive ( |
3500 | + GTK_WIDGET (bookmarks->edit), (selected == 1 ? TRUE : FALSE)); |
3501 | } |
3502 | |
3503 | -static gchar* |
3504 | +static gchar* |
3505 | midori_bookmarks_statusbar_bookmarks_str (gint count) |
3506 | { |
3507 | if (!count) |
3508 | @@ -634,7 +1727,7 @@ |
3509 | return g_strdup_printf (ngettext ("%d bookmark", "%d bookmarks", count), count); |
3510 | } |
3511 | |
3512 | -static gchar* |
3513 | +static gchar* |
3514 | midori_bookmarks_statusbar_subfolders_str (gint count) |
3515 | { |
3516 | if (!count) |
3517 | @@ -648,78 +1741,141 @@ |
3518 | midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks) |
3519 | { |
3520 | gchar* text = NULL; |
3521 | - |
3522 | - if (bookmarks->hovering_item) |
3523 | - { |
3524 | - KatzeItem* item = bookmarks->hovering_item; |
3525 | - |
3526 | - g_assert (!KATZE_ITEM_IS_SEPARATOR (item)); |
3527 | - |
3528 | - if (KATZE_ITEM_IS_FOLDER (item)) |
3529 | + GtkTreeModel* model; |
3530 | + GList *rows; |
3531 | + gint selected; |
3532 | + |
3533 | + selected = katze_tree_view_get_selected_rows ( |
3534 | + GTK_TREE_VIEW (bookmarks->treeview), &model, &rows); |
3535 | + |
3536 | + if (selected > 1) |
3537 | + { |
3538 | + gint i; |
3539 | + gint selected_folders_count = 0; |
3540 | + gint selected_bookmarks_count = 0; |
3541 | + gchar* selected_folders_str = midori_bookmarks_statusbar_subfolders_str (selected_folders_count); |
3542 | + gchar* selected_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (selected_bookmarks_count); |
3543 | + |
3544 | + for (i = 0 ; i < selected ; i++) |
3545 | + { |
3546 | + GtkTreeIter iter; |
3547 | + KatzeItem* item; |
3548 | + |
3549 | + if (!gtk_tree_model_get_iter ( |
3550 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, i))) |
3551 | + continue; |
3552 | + |
3553 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
3554 | + |
3555 | + g_assert (!KATZE_ITEM_IS_SEPARATOR (item)); |
3556 | + |
3557 | + if (KATZE_ITEM_IS_FOLDER (item)) |
3558 | + { |
3559 | + selected_folders_count++; |
3560 | + } |
3561 | + else |
3562 | + { |
3563 | + selected_bookmarks_count++; |
3564 | + } |
3565 | + } |
3566 | + |
3567 | + selected_folders_str = midori_bookmarks_statusbar_subfolders_str (selected_folders_count); |
3568 | + selected_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (selected_bookmarks_count); |
3569 | + |
3570 | + if (!selected_bookmarks_count && !selected_folders_count) |
3571 | + g_assert_not_reached (); |
3572 | + else if (!selected_bookmarks_count && (selected_folders_count >= 1)) |
3573 | + /* i18n: Selection containing [[n] folder(s)] and no bookmark */ |
3574 | + text = g_strdup_printf (_("Selection containing %s and no bookmark"), |
3575 | + selected_folders_str); |
3576 | + else if ((selected_bookmarks_count >= 1) && !selected_folders_count) |
3577 | + /* i18n: Selection containing [[n] bookmark(s)] */ |
3578 | + text = g_strdup_printf (_("Selection containing %s"), selected_bookmarks_str); |
3579 | + else if ((selected_bookmarks_count >= 1) && (selected_folders_count >= 1)) |
3580 | + /* i18n: Selection containing [[n] bookmark(s)] and [[n] folder(s)] */ |
3581 | + text = g_strdup_printf (_("Selection containing %s and %s"), |
3582 | + selected_bookmarks_str, selected_folders_str); |
3583 | + |
3584 | + g_free (selected_folders_str); |
3585 | + g_free (selected_bookmarks_str); |
3586 | + |
3587 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3588 | + } |
3589 | + else |
3590 | + { |
3591 | + if (selected) |
3592 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3593 | + |
3594 | + if (bookmarks->hovering_item) |
3595 | + { |
3596 | + KatzeItem* item = bookmarks->hovering_item; |
3597 | + |
3598 | + if (KATZE_ITEM_IS_FOLDER (item)) |
3599 | + { |
3600 | + gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
3601 | + "uri = ''", NULL, item, FALSE); |
3602 | + gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
3603 | + "uri <> ''", NULL, item, FALSE); |
3604 | + gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count); |
3605 | + gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count); |
3606 | + |
3607 | + if (!child_bookmarks_count && !child_folders_count) |
3608 | + /* i18n: Empty folder */ |
3609 | + text = g_strdup_printf (_("Empty folder")); |
3610 | + else if (!child_bookmarks_count && (child_folders_count >= 1)) |
3611 | + /* i18n: Folder containing [[n] folder(s)] and no bookmark */ |
3612 | + text = g_strdup_printf (_("Folder containing %s and no bookmark"), |
3613 | + child_folders_str); |
3614 | + else if ((child_bookmarks_count >= 1) && !child_folders_count) |
3615 | + /* i18n: Folder containing [[n] bookmark(s)] */ |
3616 | + text = g_strdup_printf (_("Folder containing %s"), child_bookmarks_str); |
3617 | + else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1)) |
3618 | + /* i18n: Folder containing [[n] bookmark(s)] and [[n] folder(s)] */ |
3619 | + text = g_strdup_printf (_("Folder containing %s and %s"), |
3620 | + child_bookmarks_str, child_folders_str); |
3621 | + |
3622 | + g_free (child_folders_str); |
3623 | + g_free (child_bookmarks_str); |
3624 | + } |
3625 | + else if (KATZE_ITEM_IS_BOOKMARK (item)) |
3626 | + { |
3627 | + const gchar* uri = katze_item_get_uri (item); |
3628 | + |
3629 | + /* i18n: Bookmark leading to: [bookmark uri] */ |
3630 | + text = g_strdup_printf (_("Bookmark leading to: %s"), uri); |
3631 | + } |
3632 | + } |
3633 | + else |
3634 | { |
3635 | gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
3636 | - "uri = ''", NULL, item, FALSE); |
3637 | + "uri = ''", NULL, NULL, FALSE); |
3638 | gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
3639 | - "uri <> ''", NULL, item, FALSE); |
3640 | + "uri <> ''", NULL, NULL, FALSE); |
3641 | gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count); |
3642 | gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count); |
3643 | |
3644 | - if (!child_bookmarks_count && !child_folders_count) |
3645 | - /* i18n: Empty folder */ |
3646 | - text = g_strdup_printf (_("Empty folder")); |
3647 | - else if (!child_bookmarks_count && (child_folders_count >= 1)) |
3648 | - /* i18n: Folder containing [[n] folder(s)] and no bookmark */ |
3649 | - text = g_strdup_printf (_("Folder containing %s and no bookmark"), |
3650 | + if (!child_bookmarks_count && (child_folders_count >= 1)) |
3651 | + /* i18n: [[n] folder(s)] and no bookmark */ |
3652 | + text = g_strdup_printf (_("%s and no bookmark"), |
3653 | child_folders_str); |
3654 | else if ((child_bookmarks_count >= 1) && !child_folders_count) |
3655 | - /* i18n: Folder containing [[n] bookmark(s)] */ |
3656 | - text = g_strdup_printf (_("Folder containing %s"), child_bookmarks_str); |
3657 | + text = g_strdup (child_bookmarks_str); |
3658 | else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1)) |
3659 | - /* i18n: Folder containing [[n] bookmark(s)] and [[n] folder(s)] */ |
3660 | - text = g_strdup_printf (_("Folder containing %s and %s"), |
3661 | + /* i18n: [[n] bookmark(s)] and [[n] folder(s)] */ |
3662 | + text = g_strdup_printf (_("%s and %s"), |
3663 | child_bookmarks_str, child_folders_str); |
3664 | |
3665 | g_free (child_folders_str); |
3666 | g_free (child_bookmarks_str); |
3667 | } |
3668 | - else if (KATZE_ITEM_IS_BOOKMARK (item)) |
3669 | - { |
3670 | - const gchar* uri = katze_item_get_uri (item); |
3671 | - |
3672 | - /* i18n: Bookmark leading to: [bookmark uri] */ |
3673 | - text = g_strdup_printf (_("Bookmark leading to: %s"), uri); |
3674 | - } |
3675 | - } |
3676 | - else |
3677 | - { |
3678 | - gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
3679 | - "uri = ''", NULL, NULL, FALSE); |
3680 | - gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
3681 | - "uri <> ''", NULL, NULL, FALSE); |
3682 | - gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count); |
3683 | - gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count); |
3684 | - |
3685 | - if (!child_bookmarks_count && (child_folders_count >= 1)) |
3686 | - /* i18n: [[n] folder(s)] and no bookmark */ |
3687 | - text = g_strdup_printf (_("%s and no bookmark"), |
3688 | - child_folders_str); |
3689 | - else if ((child_bookmarks_count >= 1) && !child_folders_count) |
3690 | - text = g_strdup (child_bookmarks_str); |
3691 | - else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1)) |
3692 | - /* i18n: [[n] bookmark(s)] and [[n] folder(s)] */ |
3693 | - text = g_strdup_printf (_("%s and %s"), |
3694 | - child_bookmarks_str, child_folders_str); |
3695 | - |
3696 | - g_free (child_folders_str); |
3697 | - g_free (child_bookmarks_str); |
3698 | } |
3699 | |
3700 | if (text) |
3701 | { |
3702 | MidoriBrowser* browser = midori_browser_get_for_widget (bookmarks->treeview); |
3703 | - |
3704 | + |
3705 | g_object_set (browser, "statusbar-text", text, NULL); |
3706 | - |
3707 | + |
3708 | g_free(text); |
3709 | } |
3710 | } |
3711 | @@ -729,19 +1885,33 @@ |
3712 | MidoriBookmarks* bookmarks) |
3713 | { |
3714 | GtkTreeModel* model; |
3715 | - GtkTreeIter iter; |
3716 | - |
3717 | - if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview), |
3718 | - &model, &iter)) |
3719 | + GList* rows; |
3720 | + GList* iter_row; |
3721 | + |
3722 | + if (!katze_tree_view_get_selected_rows(GTK_TREE_VIEW (bookmarks->treeview), |
3723 | + &model, &rows)) |
3724 | + return; |
3725 | + |
3726 | + for (iter_row = rows ; iter_row ; iter_row = g_list_next (iter_row)) |
3727 | { |
3728 | - KatzeItem* item; |
3729 | - |
3730 | - gtk_tree_model_get (model, &iter, 0, &item, -1); |
3731 | - |
3732 | - midori_bookmarks_db_remove_item (bookmarks->bookmarks_db, item); |
3733 | - |
3734 | - g_object_unref (item); |
3735 | + GtkTreeIter iter; |
3736 | + |
3737 | + if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *)iter_row->data)) |
3738 | + { |
3739 | + KatzeItem* item; |
3740 | + |
3741 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
3742 | + |
3743 | + if (item) |
3744 | + { |
3745 | + midori_bookmarks_db_remove_item (bookmarks->bookmarks_db, item); |
3746 | + |
3747 | + g_object_unref (item); |
3748 | + } |
3749 | + } |
3750 | } |
3751 | + |
3752 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3753 | } |
3754 | |
3755 | static GtkWidget* |
3756 | @@ -759,7 +1929,7 @@ |
3757 | toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK_ADD); |
3758 | gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkAdd"); |
3759 | gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), |
3760 | - _("Add a new bookmark")); |
3761 | + _("Add a new bookmark")); |
3762 | gtk_tool_item_set_is_important (toolitem, TRUE); |
3763 | g_signal_connect (toolitem, "clicked", |
3764 | G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks); |
3765 | @@ -767,7 +1937,7 @@ |
3766 | gtk_widget_show (GTK_WIDGET (toolitem)); |
3767 | toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_EDIT); |
3768 | gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), |
3769 | - _("Edit the selected bookmark")); |
3770 | + _("Edit the selected bookmark")); |
3771 | g_signal_connect (toolitem, "clicked", |
3772 | G_CALLBACK (midori_bookmarks_edit_clicked_cb), bookmarks); |
3773 | gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); |
3774 | @@ -775,7 +1945,7 @@ |
3775 | bookmarks->edit = GTK_WIDGET (toolitem); |
3776 | toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE); |
3777 | gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), |
3778 | - _("Delete the selected bookmark")); |
3779 | + _("Delete the selected bookmark")); |
3780 | g_signal_connect (toolitem, "clicked", |
3781 | G_CALLBACK (midori_bookmarks_delete_clicked_cb), bookmarks); |
3782 | gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); |
3783 | @@ -791,7 +1961,7 @@ |
3784 | toolitem = gtk_tool_button_new_from_stock (STOCK_FOLDER_NEW); |
3785 | gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkFolderAdd"); |
3786 | gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), |
3787 | - _("Add a new folder")); |
3788 | + _("Add a new folder")); |
3789 | g_signal_connect (toolitem, "clicked", |
3790 | G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks); |
3791 | gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1); |
3792 | @@ -841,6 +2011,12 @@ |
3793 | G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks); |
3794 | g_signal_connect (bookmarks->bookmarks_db, "update", |
3795 | G_CALLBACK (midori_bookmarks_update_cb), bookmarks); |
3796 | + g_signal_connect_after (model, "row-inserted", |
3797 | + G_CALLBACK (midori_bookmarks_row_inserted_cb), |
3798 | + bookmarks); |
3799 | + g_signal_connect_after (model, "row-deleted", |
3800 | + G_CALLBACK (midori_bookmarks_row_deleted_cb), |
3801 | + bookmarks); |
3802 | g_signal_connect_after (model, "row-changed", |
3803 | G_CALLBACK (midori_bookmarks_row_changed_cb), |
3804 | bookmarks); |
3805 | @@ -856,12 +2032,12 @@ |
3806 | |
3807 | switch (prop_id) |
3808 | { |
3809 | - case PROP_APP: |
3810 | - midori_bookmarks_set_app (bookmarks, g_value_get_object (value)); |
3811 | - break; |
3812 | - default: |
3813 | - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
3814 | - break; |
3815 | + case PROP_APP: |
3816 | + midori_bookmarks_set_app (bookmarks, g_value_get_object (value)); |
3817 | + break; |
3818 | + default: |
3819 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
3820 | + break; |
3821 | } |
3822 | } |
3823 | |
3824 | @@ -875,12 +2051,12 @@ |
3825 | |
3826 | switch (prop_id) |
3827 | { |
3828 | - case PROP_APP: |
3829 | - g_value_set_object (value, bookmarks->app); |
3830 | - break; |
3831 | - default: |
3832 | - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
3833 | - break; |
3834 | + case PROP_APP: |
3835 | + g_value_set_object (value, bookmarks->app); |
3836 | + break; |
3837 | + default: |
3838 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
3839 | + break; |
3840 | } |
3841 | } |
3842 | |
3843 | @@ -918,8 +2094,8 @@ |
3844 | if (item && katze_item_get_name (item)) |
3845 | { |
3846 | g_object_set (renderer, "markup", NULL, |
3847 | - "ellipsize", PANGO_ELLIPSIZE_END, |
3848 | - "text", katze_item_get_name (item), NULL); |
3849 | + "ellipsize", PANGO_ELLIPSIZE_END, |
3850 | + "text", katze_item_get_name (item), NULL); |
3851 | } |
3852 | else |
3853 | g_object_set (renderer, "markup", _("<i>Separator</i>"), NULL); |
3854 | @@ -976,7 +2152,7 @@ |
3855 | menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL); |
3856 | if (label) |
3857 | gtk_label_set_text_with_mnemonic (GTK_LABEL (gtk_bin_get_child ( |
3858 | - GTK_BIN (menuitem))), label); |
3859 | + GTK_BIN (menuitem))), label); |
3860 | if (!strcmp (stock_id, GTK_STOCK_EDIT)) |
3861 | gtk_widget_set_sensitive (menuitem, |
3862 | !KATZE_ITEM_IS_SEPARATOR (item)); |
3863 | @@ -1007,39 +2183,103 @@ |
3864 | } |
3865 | } |
3866 | |
3867 | -static void |
3868 | -midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem, |
3869 | - MidoriBookmarks* bookmarks) |
3870 | -{ |
3871 | - KatzeItem* item; |
3872 | - const gchar* uri; |
3873 | - |
3874 | - item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem"); |
3875 | - if (KATZE_ITEM_IS_FOLDER (item)) |
3876 | +static GtkWidget* |
3877 | +midori_bookmarks_open_bookmark_in_tab (KatzeItem *item, |
3878 | + MidoriBrowser* browser) |
3879 | +{ |
3880 | + const gchar* uri = katze_item_get_uri (item); |
3881 | + |
3882 | + if (!uri || !*uri) |
3883 | + return NULL; |
3884 | + |
3885 | + return midori_browser_add_item (browser, item); |
3886 | +} |
3887 | + |
3888 | +static GtkWidget* |
3889 | +midori_bookmarks_open_folder_in_tab (gint64 parentid, |
3890 | + MidoriBookmarks* bookmarks, |
3891 | + MidoriBrowser* browser) |
3892 | +{ |
3893 | + GtkWidget* last_view = NULL; |
3894 | + KatzeArray* array; |
3895 | + |
3896 | + array = midori_bookmarks_read_from_db (bookmarks, parentid, NULL); |
3897 | + |
3898 | + if (KATZE_IS_ARRAY (array)) |
3899 | { |
3900 | KatzeItem* child; |
3901 | - KatzeArray* array; |
3902 | - |
3903 | - array = midori_bookmarks_read_from_db (bookmarks, |
3904 | - katze_item_get_meta_integer (item, "parentid"), NULL); |
3905 | - |
3906 | - g_return_if_fail (KATZE_IS_ARRAY (array)); |
3907 | + |
3908 | KATZE_ARRAY_FOREACH_ITEM (child, array) |
3909 | { |
3910 | - if ((uri = katze_item_get_uri (child)) && *uri) |
3911 | + GtkWidget* view = midori_bookmarks_open_bookmark_in_tab (child, browser); |
3912 | + if (view) |
3913 | + last_view = view; |
3914 | + } |
3915 | + } |
3916 | + |
3917 | + return last_view; |
3918 | +} |
3919 | + |
3920 | +static void |
3921 | +midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem, |
3922 | + MidoriBookmarks* bookmarks) |
3923 | +{ |
3924 | + GtkWidget* last_view = NULL; |
3925 | + MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
3926 | + GtkTreeModel* model; |
3927 | + GList* rows; |
3928 | + gint length; |
3929 | + |
3930 | + length = katze_tree_view_get_selected_rows (GTK_TREE_VIEW (bookmarks->treeview), |
3931 | + &model, &rows); |
3932 | + |
3933 | + if (!length) |
3934 | + { |
3935 | + KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db); |
3936 | + KatzeItem* item = KATZE_ITEM (g_object_get_data (G_OBJECT (menuitem), "KatzeItem")); |
3937 | + |
3938 | + if (item != root) |
3939 | + return; |
3940 | + |
3941 | + last_view = midori_bookmarks_open_folder_in_tab (0, bookmarks, browser); |
3942 | + } |
3943 | + else |
3944 | + { |
3945 | + gint i; |
3946 | + |
3947 | + for (i = 0 ; i < length; i++) |
3948 | + { |
3949 | + GtkTreeIter iter; |
3950 | + |
3951 | + if (gtk_tree_model_get_iter ( |
3952 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, i))) |
3953 | { |
3954 | - MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
3955 | - GtkWidget* view = midori_browser_add_item (browser, child); |
3956 | - midori_browser_set_current_tab_smartly (browser, view); |
3957 | + GtkWidget* view = NULL; |
3958 | + KatzeItem* item; |
3959 | + |
3960 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
3961 | + |
3962 | + if (KATZE_ITEM_IS_SEPARATOR(item)) |
3963 | + continue; |
3964 | + |
3965 | + if (KATZE_ITEM_IS_FOLDER (item)) |
3966 | + view = midori_bookmarks_open_folder_in_tab ( |
3967 | + katze_item_get_meta_integer (item, "id"), bookmarks, browser); |
3968 | + else |
3969 | + view = midori_bookmarks_open_bookmark_in_tab (item, browser); |
3970 | + |
3971 | + g_object_unref (item); |
3972 | + |
3973 | + if (view) |
3974 | + last_view = view; |
3975 | } |
3976 | } |
3977 | - } |
3978 | - else if ((uri = katze_item_get_uri (item)) && *uri) |
3979 | - { |
3980 | - MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
3981 | - GtkWidget* view = midori_browser_add_item (browser, item); |
3982 | - midori_browser_set_current_tab_smartly (browser, view); |
3983 | - } |
3984 | + |
3985 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3986 | + } |
3987 | + |
3988 | + if (last_view) |
3989 | + midori_browser_set_current_tab_smartly (browser, last_view); |
3990 | } |
3991 | |
3992 | static void |
3993 | @@ -1067,18 +2307,20 @@ |
3994 | KatzeItem* item, |
3995 | MidoriBookmarks* bookmarks) |
3996 | { |
3997 | + KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db); |
3998 | GtkWidget* menu; |
3999 | GtkWidget* menuitem; |
4000 | |
4001 | menu = gtk_menu_new (); |
4002 | - if (KATZE_ITEM_IS_FOLDER (item)) |
4003 | + if ((item == root) |
4004 | + || KATZE_ITEM_IS_FOLDER (item)) |
4005 | { |
4006 | gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db, |
4007 | "uri <> ''", NULL, item, FALSE); |
4008 | |
4009 | midori_bookmarks_popup_item (menu, |
4010 | - STOCK_TAB_NEW, _("Open all in _Tabs"), item, |
4011 | - (!child_bookmarks_count ? NULL : midori_bookmarks_open_in_tab_activate_cb), |
4012 | + STOCK_TAB_NEW, _("Open all in _Tabs"), item, |
4013 | + (!child_bookmarks_count ? NULL : midori_bookmarks_open_in_tab_activate_cb), |
4014 | bookmarks); |
4015 | } |
4016 | else |
4017 | @@ -1094,11 +2336,59 @@ |
4018 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
4019 | gtk_widget_show (menuitem); |
4020 | midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL, |
4021 | - item, midori_bookmarks_edit_clicked_cb, bookmarks); |
4022 | - midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
4023 | - item, midori_bookmarks_delete_clicked_cb, bookmarks); |
4024 | - |
4025 | - katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
4026 | + item, (item == root) ? NULL : midori_bookmarks_edit_clicked_cb, bookmarks); |
4027 | + midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
4028 | + item, (item == root) ? NULL : midori_bookmarks_delete_clicked_cb, bookmarks); |
4029 | + |
4030 | + katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
4031 | +} |
4032 | + |
4033 | +static void |
4034 | +midori_bookmarks_multi_popup (GtkWidget* widget, |
4035 | + GdkEventButton* event, |
4036 | + MidoriBookmarks* bookmarks, |
4037 | + GtkTreeModel* model, |
4038 | + gint count, |
4039 | + GList* rows) |
4040 | +{ |
4041 | + GtkWidget* menu; |
4042 | + GtkWidget* menuitem; |
4043 | + |
4044 | + menu = gtk_menu_new (); |
4045 | + |
4046 | + midori_bookmarks_popup_item (menu, |
4047 | + STOCK_TAB_NEW, _("Open all in _Tabs"), |
4048 | + KATZE_ITEM(bookmarks->bookmarks_db), midori_bookmarks_open_in_tab_activate_cb, bookmarks); |
4049 | + menuitem = gtk_separator_menu_item_new (); |
4050 | + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
4051 | + gtk_widget_show (menuitem); |
4052 | + |
4053 | + midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL, |
4054 | + NULL, NULL, bookmarks); |
4055 | + midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
4056 | + KATZE_ITEM(bookmarks->bookmarks_db), midori_bookmarks_delete_clicked_cb, bookmarks); |
4057 | + |
4058 | + katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
4059 | +} |
4060 | + |
4061 | +static gboolean |
4062 | +midori_bookmarks_do_block_selection (GtkTreeSelection *selection, |
4063 | + GtkTreeModel *model, |
4064 | + GtkTreePath *path, |
4065 | + gboolean path_currently_selected, |
4066 | + gpointer data) |
4067 | +{ |
4068 | + return FALSE; |
4069 | +} |
4070 | + |
4071 | +static gboolean |
4072 | +midori_bookmarks_do_not_block_selection (GtkTreeSelection *selection, |
4073 | + GtkTreeModel *model, |
4074 | + GtkTreePath *path, |
4075 | + gboolean path_currently_selected, |
4076 | + gpointer data) |
4077 | +{ |
4078 | + return TRUE; |
4079 | } |
4080 | |
4081 | static gboolean |
4082 | @@ -1109,32 +2399,194 @@ |
4083 | GtkTreeModel* model; |
4084 | GtkTreeIter iter; |
4085 | |
4086 | - if (event->button != 2 && event->button != 3) |
4087 | + if (bookmarks->pending_event) |
4088 | + { |
4089 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
4090 | + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); |
4091 | + gint x = bookmarks->stock_pending_event.x; |
4092 | + gint y = bookmarks->stock_pending_event.y; |
4093 | + |
4094 | + bookmarks->pending_event = NULL; |
4095 | + gtk_tree_selection_set_select_function ( |
4096 | + selection, midori_bookmarks_do_not_block_selection, NULL, NULL); |
4097 | + |
4098 | + if (x != event->x || y != event->y) |
4099 | + return FALSE; |
4100 | + } |
4101 | + |
4102 | + if (event->button == 3) |
4103 | + return TRUE; |
4104 | + |
4105 | + if (event->button != 2) |
4106 | return FALSE; |
4107 | |
4108 | if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter)) |
4109 | { |
4110 | + gboolean done = FALSE; |
4111 | KatzeItem* item; |
4112 | |
4113 | gtk_tree_model_get (model, &iter, 0, &item, -1); |
4114 | |
4115 | - if (event->button == 2) |
4116 | + if (KATZE_ITEM_IS_BOOKMARK (item)) |
4117 | { |
4118 | - const gchar* uri; |
4119 | - if (KATZE_ITEM_IS_BOOKMARK (item) && (uri = katze_item_get_uri (item)) && *uri) |
4120 | + MidoriBrowser* browser = midori_browser_get_for_widget (widget); |
4121 | + GtkWidget* view = midori_bookmarks_open_bookmark_in_tab ( |
4122 | + item, browser); |
4123 | + |
4124 | + if (widget) |
4125 | { |
4126 | - MidoriBrowser* browser = midori_browser_get_for_widget (widget); |
4127 | - GtkWidget* view = midori_browser_add_uri (browser, uri); |
4128 | - midori_browser_set_current_tab (browser, view); |
4129 | + midori_browser_set_current_tab_smartly (browser, view); |
4130 | + done = TRUE; |
4131 | } |
4132 | } |
4133 | - else |
4134 | - midori_bookmarks_popup (widget, event, item, bookmarks); |
4135 | - |
4136 | - if (item != NULL) |
4137 | - g_object_unref (item); |
4138 | - return TRUE; |
4139 | - } |
4140 | + |
4141 | + g_object_unref (item); |
4142 | + |
4143 | + return done; |
4144 | + } |
4145 | + |
4146 | + return FALSE; |
4147 | +} |
4148 | + |
4149 | +static gboolean |
4150 | +midori_bookmarks_block_selection(GtkWidget* widget, |
4151 | + GdkEventButton* event, |
4152 | + MidoriBookmarks* bookmarks) |
4153 | +{ |
4154 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
4155 | + GtkTreePath* path; |
4156 | + GtkTreeSelection* selection; |
4157 | + gint cell_x; |
4158 | + gint cell_y; |
4159 | + |
4160 | + if (!gtk_tree_view_get_path_at_pos ( |
4161 | + treeview, event->x, event->y, |
4162 | + &path, NULL, &cell_x, &cell_y)) |
4163 | + return FALSE; |
4164 | + |
4165 | + gtk_widget_grab_focus (widget); |
4166 | + |
4167 | + selection = gtk_tree_view_get_selection (treeview); |
4168 | + |
4169 | + if (gtk_tree_selection_path_is_selected (selection, path) |
4170 | + && !(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK))) |
4171 | + { |
4172 | + bookmarks->pending_event = &bookmarks->stock_pending_event; |
4173 | + bookmarks->stock_pending_event.x = event->x; |
4174 | + bookmarks->stock_pending_event.y = event->y; |
4175 | + gtk_tree_selection_set_select_function ( |
4176 | + selection, midori_bookmarks_do_block_selection, NULL, NULL); |
4177 | + } |
4178 | + else |
4179 | + { |
4180 | + bookmarks->pending_event = NULL; |
4181 | + gtk_tree_selection_set_select_function ( |
4182 | + selection, midori_bookmarks_do_not_block_selection, NULL, NULL); |
4183 | + } |
4184 | + |
4185 | + return FALSE; |
4186 | +} |
4187 | + |
4188 | +static gboolean |
4189 | +midori_bookmarks_button_press_event_cb (GtkWidget* widget, |
4190 | + GdkEventButton* event, |
4191 | + MidoriBookmarks* bookmarks) |
4192 | +{ |
4193 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
4194 | + GtkTreePath* path; |
4195 | + GtkTreeSelection* selection; |
4196 | + GtkTreeModel* model; |
4197 | + gint selected; |
4198 | + GList* rows; |
4199 | + gint cell_x; |
4200 | + gint cell_y; |
4201 | + |
4202 | + if (event->button == 1) |
4203 | + return midori_bookmarks_block_selection (widget, event, bookmarks); |
4204 | + |
4205 | + if (event->button != 3) |
4206 | + return FALSE; |
4207 | + |
4208 | + selection = gtk_tree_view_get_selection (treeview); |
4209 | + |
4210 | + if (!gtk_tree_view_get_path_at_pos ( |
4211 | + treeview, event->x, event->y, |
4212 | + &path, NULL, &cell_x, &cell_y)) |
4213 | + { |
4214 | + /* FIXME: popup opening below treeview |
4215 | + * Rationale: the user is actually in ROOT folder |
4216 | + * we may need to have a non editable, non deletable, ROOT folder popup |
4217 | + * Open all in Tabs |
4218 | + * Separator |
4219 | + * Edit [inactive] |
4220 | + * Delete [inactive] |
4221 | + * Here we just mimic the Files behaviour: |
4222 | + * 1- unselect all |
4223 | + * 2- let popup based on selection process |
4224 | + */ |
4225 | + |
4226 | + gtk_tree_selection_unselect_all (selection); |
4227 | + } |
4228 | + else if (!gtk_tree_selection_path_is_selected (selection, path)) |
4229 | + { |
4230 | + /* Use case: popup opening on item not in selection |
4231 | + * Rationale: the user is addressing a single item not in selection |
4232 | + * we may need a single item popup with callbacks working on the item, |
4233 | + * not the selection. |
4234 | + * Here we just mimic the Files behaviour: |
4235 | + * 1- change the selection to the item the popup is opened on |
4236 | + * 2- let popup based on selection process |
4237 | + */ |
4238 | + |
4239 | + gtk_tree_selection_unselect_all (selection); |
4240 | + gtk_tree_selection_select_path (selection, path); |
4241 | + } |
4242 | + |
4243 | + selected = katze_tree_view_get_selected_rows(GTK_TREE_VIEW (widget), &model, &rows); |
4244 | + |
4245 | + if (!selected) |
4246 | + { |
4247 | + KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db); |
4248 | + |
4249 | + midori_bookmarks_popup (widget, event, root, bookmarks); |
4250 | + |
4251 | + return TRUE; |
4252 | + } |
4253 | + |
4254 | + if (selected == 1) |
4255 | + { |
4256 | + GtkTreeIter iter; |
4257 | + KatzeItem* item; |
4258 | + |
4259 | + if (!gtk_tree_model_get_iter ( |
4260 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, 0))) |
4261 | + { |
4262 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
4263 | + |
4264 | + return FALSE; |
4265 | + } |
4266 | + |
4267 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
4268 | + |
4269 | + midori_bookmarks_popup (widget, event, item, bookmarks); |
4270 | + |
4271 | + g_object_unref (item); |
4272 | + |
4273 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
4274 | + |
4275 | + return TRUE; |
4276 | + } |
4277 | + |
4278 | + if (selected > 1) |
4279 | + { |
4280 | + midori_bookmarks_multi_popup (widget, event, bookmarks, |
4281 | + model, selected, rows); |
4282 | + |
4283 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
4284 | + |
4285 | + return TRUE; |
4286 | + } |
4287 | + |
4288 | return FALSE; |
4289 | } |
4290 | |
4291 | @@ -1165,39 +2617,74 @@ |
4292 | } |
4293 | } |
4294 | |
4295 | -static void |
4296 | -midori_bookmarks_row_expanded_cb (GtkTreeView* treeview, |
4297 | - GtkTreeIter* iter, |
4298 | - GtkTreePath* path, |
4299 | - MidoriBookmarks* bookmarks) |
4300 | +static gboolean |
4301 | +midori_bookmarks_test_expand_row_cb (GtkTreeView* treeview, |
4302 | + GtkTreeIter* iter, |
4303 | + GtkTreePath* path, |
4304 | + MidoriBookmarks* bookmarks) |
4305 | { |
4306 | GtkTreeModel* model; |
4307 | + GtkTreeIter child; |
4308 | KatzeItem* item; |
4309 | + gint64 id; |
4310 | |
4311 | model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); |
4312 | + |
4313 | gtk_tree_model_get (model, iter, 0, &item, -1); |
4314 | + |
4315 | + g_return_val_if_fail (KATZE_IS_ITEM(item), TRUE); |
4316 | + |
4317 | + g_signal_handlers_block_by_func (model, |
4318 | + midori_bookmarks_row_deleted_cb, |
4319 | + bookmarks); |
4320 | + |
4321 | + id = katze_item_get_meta_integer (item, "id"); |
4322 | + |
4323 | + g_object_unref (item); |
4324 | + |
4325 | + while (gtk_tree_model_iter_children (model, &child, iter)) |
4326 | + gtk_tree_store_remove (GTK_TREE_STORE (model), &child); |
4327 | + /* That's an invisible dummy, so we always have an expander */ |
4328 | + gtk_tree_store_insert_with_values (GTK_TREE_STORE (model), &child, iter, |
4329 | + 0, 0, NULL, -1); |
4330 | + |
4331 | + g_signal_handlers_unblock_by_func (model, |
4332 | + midori_bookmarks_row_deleted_cb, |
4333 | + bookmarks); |
4334 | + |
4335 | midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), |
4336 | - iter, katze_item_get_meta_integer (item, "id"), NULL); |
4337 | - g_object_unref (item); |
4338 | + iter, id, NULL); |
4339 | + |
4340 | + return FALSE; |
4341 | } |
4342 | |
4343 | static void |
4344 | midori_bookmarks_row_collapsed_cb (GtkTreeView *treeview, |
4345 | GtkTreeIter *parent, |
4346 | GtkTreePath *path, |
4347 | - gpointer user_data) |
4348 | + MidoriBookmarks* bookmarks) |
4349 | { |
4350 | GtkTreeModel* model; |
4351 | GtkTreeStore* treestore; |
4352 | GtkTreeIter child; |
4353 | |
4354 | model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); |
4355 | + |
4356 | + g_signal_handlers_block_by_func (model, |
4357 | + midori_bookmarks_row_deleted_cb, |
4358 | + bookmarks); |
4359 | + |
4360 | treestore = GTK_TREE_STORE (model); |
4361 | while (gtk_tree_model_iter_nth_child (model, &child, parent, 0)) |
4362 | gtk_tree_store_remove (treestore, &child); |
4363 | /* That's an invisible dummy, so we always have an expander */ |
4364 | gtk_tree_store_insert_with_values (treestore, &child, parent, |
4365 | 0, 0, NULL, -1); |
4366 | + |
4367 | + g_signal_handlers_block_by_func (model, |
4368 | + midori_bookmarks_row_deleted_cb, |
4369 | + bookmarks); |
4370 | + |
4371 | } |
4372 | |
4373 | static void |
4374 | @@ -1205,26 +2692,27 @@ |
4375 | MidoriBookmarks *bookmarks) |
4376 | { |
4377 | midori_bookmarks_toolbar_update (bookmarks); |
4378 | + midori_bookmarks_statusbar_update (bookmarks); |
4379 | } |
4380 | |
4381 | static KatzeItem* |
4382 | midori_bookmarks_get_item_at_pos (GtkTreeView *treeview, |
4383 | gint x, gint y) |
4384 | -{ |
4385 | +{ |
4386 | GtkTreeModel* model = gtk_tree_view_get_model (treeview); |
4387 | GtkTreePath* path; |
4388 | GtkTreeIter iter; |
4389 | KatzeItem* item = NULL; |
4390 | |
4391 | gtk_tree_view_get_path_at_pos (treeview, x, y, |
4392 | - &path, NULL, NULL, NULL); |
4393 | - |
4394 | + &path, NULL, NULL, NULL); |
4395 | + |
4396 | if (!path) |
4397 | return NULL; |
4398 | - |
4399 | + |
4400 | if (gtk_tree_model_get_iter (model, &iter, path)) |
4401 | gtk_tree_model_get (model, &iter, 0, &item, -1); |
4402 | - |
4403 | + |
4404 | gtk_tree_path_free (path); |
4405 | |
4406 | return item; |
4407 | @@ -1296,7 +2784,7 @@ |
4408 | |
4409 | if (bookmarks->hovering_item) |
4410 | g_object_unref (bookmarks->hovering_item); |
4411 | - |
4412 | + |
4413 | bookmarks->hovering_item = NULL; |
4414 | |
4415 | g_object_set (browser, "statusbar-text", "", NULL); |
4416 | @@ -1337,6 +2825,186 @@ |
4417 | midori_bookmarks_filter_timeout_cb, bookmarks, NULL); |
4418 | } |
4419 | |
4420 | +static GtkTargetEntry midori_bookmarks_dnd_target_entries[]= |
4421 | +{ |
4422 | + {MIDORI_BOOKMARKS_TREE_MODEL_TARGET, GTK_TARGET_SAME_WIDGET, 0}, |
4423 | +}; |
4424 | + |
4425 | +#define MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES \ |
4426 | + G_N_ELEMENTS (midori_bookmarks_dnd_target_entries) |
4427 | + |
4428 | +static guint |
4429 | +item_hash (gconstpointer item) |
4430 | +{ |
4431 | + gint64 id = katze_item_get_meta_integer (KATZE_ITEM (item), "id"); |
4432 | + return g_int64_hash (&id); |
4433 | +} |
4434 | + |
4435 | +static gboolean |
4436 | +item_equal (gconstpointer item_a, gconstpointer item_b) |
4437 | +{ |
4438 | + gint64 id_a = katze_item_get_meta_integer (KATZE_ITEM (item_a), "id"); |
4439 | + gint64 id_b = katze_item_get_meta_integer (KATZE_ITEM (item_b), "id"); |
4440 | + return (id_a == id_b)? TRUE : FALSE; |
4441 | +} |
4442 | + |
4443 | +static gboolean |
4444 | +midori_bookmarks_idle_func (gpointer data) |
4445 | +{ |
4446 | + MidoriBookmarks* bookmarks = MIDORI_BOOKMARKS (data); |
4447 | + GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
4448 | + GHashTableIter hash_iter; |
4449 | + gpointer key, value; |
4450 | + GList* list_iter; |
4451 | + |
4452 | + /* update remaining additions */ |
4453 | + assert_reorder_are_folders (model, bookmarks); |
4454 | + for (list_iter = bookmarks->added_paths; list_iter ; list_iter = g_list_next (list_iter)) |
4455 | + { |
4456 | + GtkTreePath* path = (GtkTreePath*)list_iter->data; |
4457 | + |
4458 | + add_parent_to_reorder (model, path, bookmarks); |
4459 | + assert_reorder_are_folders (model, bookmarks); |
4460 | + } |
4461 | + |
4462 | + g_list_free_full (bookmarks->added_paths, (GDestroyNotify) gtk_tree_path_free); |
4463 | + bookmarks->added_paths = NULL; |
4464 | + |
4465 | + /* do actual reordering */ |
4466 | + for (list_iter = bookmarks->reordered_paths; list_iter ; list_iter = g_list_next (list_iter)) |
4467 | + { |
4468 | + GtkTreeIter local_iter; |
4469 | + GtkTreePath* path = (GtkTreePath*)list_iter->data; |
4470 | + |
4471 | + if (gtk_tree_path_get_depth (path)) |
4472 | + { |
4473 | + GtkTreeIter parent; |
4474 | + |
4475 | + if (gtk_tree_model_get_iter (model, &parent, path)) |
4476 | + { |
4477 | + KatzeItem *item; |
4478 | + gint64 id; |
4479 | + |
4480 | + gtk_tree_model_get (model, &parent, 0, &item, -1); |
4481 | + |
4482 | + g_assert (KATZE_ITEM_IS_FOLDER (item)); |
4483 | + |
4484 | + id = katze_item_get_meta_integer (item, "id"); |
4485 | + |
4486 | + if (gtk_tree_model_iter_children (model, &local_iter, &parent)) |
4487 | + midori_bookmarks_set_item_positon(model, &local_iter, id, bookmarks); |
4488 | + |
4489 | + /* update folder array for menu update */ |
4490 | + katze_array_update (KATZE_ARRAY (item)); |
4491 | + |
4492 | + g_object_unref (item); |
4493 | + } |
4494 | + } |
4495 | + else |
4496 | + { |
4497 | + if (gtk_tree_model_get_iter_first (model, &local_iter)) |
4498 | + midori_bookmarks_set_item_positon(model, &local_iter, |
4499 | + katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id"), |
4500 | + bookmarks); |
4501 | + |
4502 | + g_signal_handlers_block_by_func (bookmarks->bookmarks_db, |
4503 | + midori_bookmarks_update_cb, |
4504 | + bookmarks); |
4505 | + |
4506 | + /* update folder array for menu update */ |
4507 | + katze_array_update (KATZE_ARRAY (bookmarks->bookmarks_db)); |
4508 | + |
4509 | + g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db, |
4510 | + midori_bookmarks_update_cb, |
4511 | + bookmarks); |
4512 | + } |
4513 | + } |
4514 | + |
4515 | + g_list_free_full (bookmarks->reordered_paths, (GDestroyNotify) gtk_tree_path_free); |
4516 | + bookmarks->reordered_paths = NULL; |
4517 | + |
4518 | + /* then finalize updates */ |
4519 | + g_signal_handlers_block_by_func (bookmarks->bookmarks_db, |
4520 | + midori_bookmarks_update_item_cb, |
4521 | + bookmarks); |
4522 | + |
4523 | + g_hash_table_iter_init (&hash_iter, bookmarks->updated_items); |
4524 | + |
4525 | + while (g_hash_table_iter_next (&hash_iter, &key, &value)) |
4526 | + { |
4527 | + midori_bookmarks_db_update_item (bookmarks->bookmarks_db, KATZE_ITEM (value)); |
4528 | + g_object_unref (value); |
4529 | + } |
4530 | + |
4531 | + g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db, |
4532 | + midori_bookmarks_update_item_cb, |
4533 | + bookmarks); |
4534 | + |
4535 | + g_hash_table_remove_all (bookmarks->updated_items); |
4536 | + |
4537 | + /* process pending additions of inserted bookmarks */ |
4538 | + for (list_iter = bookmarks->pending_inserts; list_iter; list_iter = g_list_next (list_iter)) |
4539 | + { |
4540 | + KatzeItem *item = KATZE_ITEM (list_iter->data); |
4541 | + gint64 id = katze_item_get_meta_integer (item, "id"); |
4542 | + GtkTreeIter iter; |
4543 | + |
4544 | + if (!midori_bookmarks_reach_item (model, &iter, id)) |
4545 | + midori_bookmarks_add_item (item, bookmarks); |
4546 | + |
4547 | + g_object_unref (item); |
4548 | + } |
4549 | + |
4550 | + g_list_free (bookmarks->pending_inserts); |
4551 | + bookmarks->pending_inserts = NULL; |
4552 | + return midori_bookmarks_idle_pending (bookmarks); |
4553 | +} |
4554 | + |
4555 | +static void |
4556 | +midori_bookmarks_update_item (MidoriBookmarks* bookmarks, KatzeItem *item) |
4557 | +{ |
4558 | + midori_bookmarks_idle_start (bookmarks); |
4559 | + |
4560 | + if (g_hash_table_lookup (bookmarks->updated_items, item)) |
4561 | + return; |
4562 | + |
4563 | + g_object_ref (item); |
4564 | + g_hash_table_insert (bookmarks->updated_items, item, item); |
4565 | +} |
4566 | + |
4567 | +static void |
4568 | +midori_bookmarks_idle_remove_item (MidoriBookmarks* bookmarks, KatzeItem *item) |
4569 | +{ |
4570 | + gpointer found; |
4571 | + |
4572 | + if (KATZE_ITEM_IS_FOLDER (item)) |
4573 | + { |
4574 | + gint64 id = katze_item_get_meta_integer (item, "id"); |
4575 | + GHashTableIter iter; |
4576 | + gpointer key, value; |
4577 | + |
4578 | + g_hash_table_iter_init (&iter, bookmarks->updated_items); |
4579 | + |
4580 | + while (g_hash_table_iter_next (&iter, &key, &value)) |
4581 | + { |
4582 | + KatzeItem *hash_item = KATZE_ITEM(key); |
4583 | + |
4584 | + gint64 parentid = katze_item_get_meta_integer (hash_item, "parentid"); |
4585 | + if (parentid == id) |
4586 | + { |
4587 | + g_hash_table_iter_remove (&iter); |
4588 | + g_object_unref (hash_item); |
4589 | + } |
4590 | + } |
4591 | + } |
4592 | + |
4593 | + if ((found = g_hash_table_lookup (bookmarks->updated_items, item)) != NULL) |
4594 | + { |
4595 | + g_hash_table_remove (bookmarks->updated_items, found); |
4596 | + g_object_unref (found); |
4597 | + } |
4598 | +} |
4599 | + |
4600 | static void |
4601 | midori_bookmarks_init (MidoriBookmarks* bookmarks) |
4602 | { |
4603 | @@ -1349,6 +3017,8 @@ |
4604 | GtkCellRenderer* renderer_text; |
4605 | GtkTreeSelection* selection; |
4606 | |
4607 | + bookmarks->pending_event = NULL; |
4608 | + |
4609 | /* Create the filter entry */ |
4610 | entry = sokoke_search_entry_new (_("Search Bookmarks")); |
4611 | g_signal_connect_after (entry, "changed", |
4612 | @@ -1359,7 +3029,7 @@ |
4613 | gtk_box_pack_start (GTK_BOX (bookmarks), box, FALSE, FALSE, 5); |
4614 | |
4615 | /* Create the treeview */ |
4616 | - model = gtk_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING); |
4617 | + model = midori_bookmarks_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING); |
4618 | treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); |
4619 | gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); |
4620 | gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), 1); |
4621 | @@ -1376,19 +3046,32 @@ |
4622 | (GtkTreeCellDataFunc)midori_bookmarks_treeview_render_text_cb, |
4623 | treeview, NULL); |
4624 | gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); |
4625 | - gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE); |
4626 | + gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), FALSE); |
4627 | + gtk_tree_view_enable_model_drag_source ( |
4628 | + GTK_TREE_VIEW (treeview), |
4629 | + GDK_BUTTON1_MASK, |
4630 | + midori_bookmarks_dnd_target_entries, |
4631 | + MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES, |
4632 | + GDK_ACTION_MOVE|GDK_ACTION_LINK); |
4633 | + gtk_tree_view_enable_model_drag_dest ( |
4634 | + GTK_TREE_VIEW (treeview), |
4635 | + midori_bookmarks_dnd_target_entries, |
4636 | + MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES, |
4637 | + GDK_ACTION_MOVE|GDK_ACTION_LINK); |
4638 | g_object_unref (model); |
4639 | g_object_connect (treeview, |
4640 | "signal::row-activated", |
4641 | midori_bookmarks_row_activated_cb, bookmarks, |
4642 | + "signal::button-press-event", |
4643 | + midori_bookmarks_button_press_event_cb, bookmarks, |
4644 | "signal::button-release-event", |
4645 | midori_bookmarks_button_release_event_cb, bookmarks, |
4646 | "signal::key-release-event", |
4647 | midori_bookmarks_key_release_event_cb, bookmarks, |
4648 | "signal::popup-menu", |
4649 | midori_bookmarks_popup_menu_cb, bookmarks, |
4650 | - "signal::row-expanded", |
4651 | - midori_bookmarks_row_expanded_cb, bookmarks, |
4652 | + "signal::test-expand-row", |
4653 | + midori_bookmarks_test_expand_row_cb, bookmarks, |
4654 | "signal::row-collapsed", |
4655 | midori_bookmarks_row_collapsed_cb, bookmarks, |
4656 | "signal::enter-notify-event", |
4657 | @@ -1398,18 +3081,27 @@ |
4658 | "signal::leave-notify-event", |
4659 | midori_bookmarks_leave_notify_event_cb, bookmarks, |
4660 | NULL); |
4661 | - gtk_widget_add_events (GTK_WIDGET (treeview), |
4662 | - GDK_POINTER_MOTION_MASK |
4663 | - | GDK_POINTER_MOTION_HINT_MASK); |
4664 | + |
4665 | + MIDORI_BOOKMARKS_TREE_STORE (model)->_view = GTK_TREE_VIEW (treeview); |
4666 | + |
4667 | + gtk_widget_add_events (GTK_WIDGET (treeview), |
4668 | + GDK_POINTER_MOTION_MASK |
4669 | + | GDK_POINTER_MOTION_HINT_MASK); |
4670 | |
4671 | selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); |
4672 | + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); |
4673 | g_signal_connect_after (selection, "changed", |
4674 | - G_CALLBACK (midori_bookmarks_selection_changed_cb), |
4675 | - bookmarks); |
4676 | + G_CALLBACK (midori_bookmarks_selection_changed_cb), |
4677 | + bookmarks); |
4678 | gtk_widget_show (treeview); |
4679 | gtk_box_pack_start (GTK_BOX (bookmarks), treeview, TRUE, TRUE, 0); |
4680 | bookmarks->treeview = treeview; |
4681 | + bookmarks->pending_inserts = NULL; |
4682 | bookmarks->hovering_item = NULL; |
4683 | + bookmarks->pending_inserts = NULL; |
4684 | + bookmarks->updated_items = g_hash_table_new (item_hash, item_equal); |
4685 | + bookmarks->added_paths = NULL; |
4686 | + bookmarks->reordered_paths = NULL; |
4687 | } |
4688 | |
4689 | static void |
4690 | @@ -1420,5 +3112,16 @@ |
4691 | if (bookmarks->app) |
4692 | g_object_unref (bookmarks->app); |
4693 | if (bookmarks->hovering_item) |
4694 | - g_object_unref (bookmarks->hovering_item); |
4695 | + g_object_unref (bookmarks->hovering_item); |
4696 | + |
4697 | + if (g_idle_remove_by_data (bookmarks)) |
4698 | + { |
4699 | + g_list_free_full (bookmarks->pending_inserts, (GDestroyNotify) g_object_unref); |
4700 | + bookmarks->pending_inserts = NULL; |
4701 | + g_hash_table_unref (bookmarks->updated_items); |
4702 | + g_list_free_full (bookmarks->added_paths, (GDestroyNotify) gtk_tree_path_free); |
4703 | + bookmarks->added_paths = NULL; |
4704 | + g_list_free_full (bookmarks->reordered_paths, (GDestroyNotify) gtk_tree_path_free); |
4705 | + bookmarks->reordered_paths = NULL; |
4706 | + } |
4707 | } |
4708 | |
4709 | === modified file 'tests/bookmarks.c' |
4710 | --- tests/bookmarks.c 2013-08-05 19:52:52 +0000 |
4711 | +++ tests/bookmarks.c 2014-01-26 19:44:25 +0000 |
4712 | @@ -128,7 +128,7 @@ |
4713 | } |
4714 | |
4715 | db_items = midori_bookmarks_db_query_recursive (db_bookmarks, |
4716 | - "*", "title='%q'", katze_item_get_name (test_item), FALSE); |
4717 | + "*", "title='%q'", katze_item_get_name (test_item), NULL, FALSE); |
4718 | |
4719 | /* FIXME g_assert_cmpint (katze_array_get_length (db_items), ==, 1); */ |
4720 | db_item = katze_array_get_nth_item (db_items, 0); |