Merge lp:~aauzi/midori/bookmarks-work into lp:midori
- bookmarks-work
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Danielle Foré |
Proposed branch: | lp:~aauzi/midori/bookmarks-work |
Merge into: | lp:midori |
Diff against target: |
3717 lines (+2658/-233) 13 files modified
katze/katze-array.c (+40/-0) katze/katze-array.h (+4/-0) katze/katze-item.c (+15/-7) katze/katze-utils.c (+90/-3) katze/katze-utils.h (+5/-0) midori/midori-array.c (+139/-5) midori/midori-array.h (+10/-1) midori/midori-bookmarks.c (+156/-9) midori/midori-bookmarks.h (+0/-10) midori/midori-browser.c (+188/-40) midori/midori-view.c (+1/-1) panels/midori-bookmarks.c (+2009/-156) tests/bookmarks.c (+1/-1) |
To merge this branch: | bzr merge lp:~aauzi/midori/bookmarks-work |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Danielle Foré (community) | Disapprove | ||
Review via email: mp+164815@code.launchpad.net |
Commit message
Description of the change
All is in revision 6164 commit message.
Fix proposal for:
#894143 Unable to select multiple bookmarks for moving/deleting
#1116908 Bookmarkbar folder is not updated when bookmark is added to folder
#1177553 Bookmark folder tree not reflected in bookmark bar and edit dialog
#1179200 Bookmark folder tree collapsed on bookmarks update
#1179624 Lack of visual feedback in bookmarks panel
Implements:
* bookmarks panel multiple selection DND delete and moves
* katze items signals between bookmarks panel and bookmarks bar
* correct handling of panel position on database retrieval
* bookmarkbar folder trees
* bookmark folder path is bookmark edit combo box
* use of current selection for bookmark/folder creation parent folder
* status bar updates and popup menus cosmetics
* idle time database updates (speed feeling)
Does not implement (maybe future work):
* DND exchanges between bookmark bar and bookmark panel
* DND bookmark creation
Considering the amount of changes I thought merging the different bugs myself may help :)
André Auzi (aauzi) wrote : | # |
> Hey André, thanks for this huge work! I have a couple of problems to report
> however...
>
> It seems for some reason there is a bunch of .po files scattered around your
> branch :p
>
> Also, the build fails with:
>
> ../panels/
> ‘midori_
> ../panels/
> incomplete type
> ../panels/
> ‘midori_
> ../panels/
> incomplete type
> ../panels/
> incomplete type
> ../panels/
> incomplete type
> ../panels/
> ‘midori_
> ../panels/
> incomplete type
> ../panels/
> ‘midori_
> ../panels/
> incomplete type
Hi Dan, no problem.
I'm glad there are so few problems on a first shoot :D
For the .po files I'm clueless so far but if your show me directions I'll do my best.
I'm concerned by the compilation errors you have.
Apparently, the GtkSelectionData structure is not exposed in your environment.
I'm building with gtk+-2.0 version : 2.24.16 on Fedora 18, let me know what is your environment, I'll see if I can figure out what happens.
- 6164. By André Auzi
-
Fix proposal for:
#894143 Unable to select multiple bookmarks for moving/deleting
#1116908 Bookmarkbar folder is not updated when bookmark is added to folder
#1177553 Bookmark folder tree not reflected in bookmark bar and edit dialog
#1179200 Bookmark folder tree collapsed on bookmarks update
#1179624 Lack of visual feedback in bookmarks panelImplements:
* bookmarks panel multiple selection DND delete and moves
* katze items signals between bookmarks panel and bookmarks bar
* correct handling of panel position on database retrieval
* bookmarkbar folder trees
* bookmark folder path in bookmark edit combo box
* use of current selection for bookmark/folder creation parent folder
* status bar updates and popup menus cosmetics
* idle time database updates (speed feeling)Does not implement (maybe future work):
* DND exchanges between bookmark bar and bookmark panel
* DND bookmark creationNotes:
1-recommit with use of accessors for GtkSelectionData fields - 6165. By André Auzi
Danielle Foré (danrabbit) wrote : | # |
Hey André,
I think for the .po files, you can probably just delete any of them that aren't in the po directory and we'll know there's something really wrong if they regenerate :p
After your latest commit, the branch does build with Gtk 3.4 :) But I'm afraid there are issues >.<
I do have a problem that I can't access any bookmarks that are in a folder. Clicking the expander triangle does nothing. Double-clicking the folder expands, but as soon as I move the cursor it starts a drag operation.
Dragging any bookmarks in the sidepanel forces the Bookmarks Bar to open.
I think for the statusbar feature, it should probably only show on hover as is the behavior with links in the web view (but it is a cool feature!)
Danielle Foré (danrabbit) wrote : | # |
Hey André,
it looks like the .po file thing is actually our fault. Something went weird with LP translations.
But also I want to say if possible it would be great to split this up into separate feature branches that we could merge individually. This is quite a large diff and is very difficult to review. It would probably be a lot safer to merge one feature at a time.
If one branch relies on another, that's okay! LP has a feature where you can mark one branch as being a pre-requisite of another so we know what order to merge them in.
Thanks again for your hard work!
André Auzi (aauzi) wrote : | # |
Hi Dan,
> I think for the .po files, you can probably just delete any of them that
> aren't in the po directory and we'll know there's something really wrong if
> they regenerate :p
it's OK on my side, no more .po after deletion and clean build.
> After your latest commit, the branch does build with Gtk 3.4 :) But I'm afraid
> there are issues >.<
Great news! and issues were expected, it's all the point of testing and reviews, isn't it?
> I do have a problem that I can't access any bookmarks that are in a folder.
> Clicking the expander triangle does nothing. Double-clicking the folder
> expands, but as soon as I move the cursor it starts a drag operation.
OK, I believe the ugly trick used to keep the multi selection before dragging does not integrate well with Gtk 3. I'll work on that.
> Dragging any bookmarks in the sidepanel forces the Bookmarks Bar to open.
Oups! Now I have to see how we hide the bookmark bar. I'll work on that too.
> I think for the statusbar feature, it should probably only show on hover as is
> the behavior with links in the web view (but it is a cool feature!)
Sounds good, I will have a look on the web view and see how I can reproduce the behaviour.
Thanks for the valuable feedback.
André Auzi (aauzi) wrote : | # |
Hi Dan,
> But also I want to say if possible it would be great to split this up into
> separate feature branches that we could merge individually. This is quite a
> large diff and is very difficult to review. It would probably be a lot safer
> to merge one feature at a time.
No problem, I have the increments ready, it's just a matter of configuration management ;)
> Thanks again for your hard work!
you're welcome. Thank you for midori, it's cool to hack in.
Now it's time to go to the office :D
André Auzi (aauzi) wrote : | # |
OK, it's time for a follow up.
So far I've reworked the proposal in three independent branches (in increasing order of complexity):
1. lp:~aauzi/midori/fix-1177553: Bookmark folder tree not reflected in bookmark bar and edit dialog
2. lp:~aauzi/midori/fix-1179624: Lack of visual feedback in bookmarks panel
3. lp:~aauzi/midori/fix-1179200: Bookmark folder tree collapsed on bookmarks update
The reported issues/remarks taken into account are:
> Dragging any bookmarks in the sidepanel forces the Bookmarks Bar to open
=> fixed in lp:~aauzi/midori/fix-1179200
> I think for the statusbar feature, it should probably only show on hover as is
> the behavior with links in the web view (but it is a cool feature!)
=> reworked into lp:~aauzi/midori/fix-1179624
There's still an upcoming one:
> I do have a problem that I can't access any bookmarks that are in a folder.
> Clicking the expander triangle does nothing. Double-clicking the folder
> expands, but as soon as I move the cursor it starts a drag operation.
=> it's work in progress
it'll show up in a branch related to bug
#894143 Unable to select multiple bookmarks for moving/deleting, lp:~aauzi/midori/fix-894143
the merge of this branch will have to come after the merge of branches:
lp:~aauzi/midori/fix-1179200
lp:~aauzi/midori/fix-1179624
the remaining activities are:
* rework hovering to take multi selection into account (~1day)
* integrate with Gtk+3 to investigate the misbehaviour (hopefully no more than ~1day)
I will propose it for merge when it's ready.
I therefore propose to close this review and switch to the reviews of the fore mentioned branches.
Danielle Foré (danrabbit) wrote : | # |
Great! Thanks André! I'll go ahead and close this review then and we can get started on merging those smaller branches :)
Unmerged revisions
- 6165. By André Auzi
- 6164. By André Auzi
-
Fix proposal for:
#894143 Unable to select multiple bookmarks for moving/deleting
#1116908 Bookmarkbar folder is not updated when bookmark is added to folder
#1177553 Bookmark folder tree not reflected in bookmark bar and edit dialog
#1179200 Bookmark folder tree collapsed on bookmarks update
#1179624 Lack of visual feedback in bookmarks panelImplements:
* bookmarks panel multiple selection DND delete and moves
* katze items signals between bookmarks panel and bookmarks bar
* correct handling of panel position on database retrieval
* bookmarkbar folder trees
* bookmark folder path in bookmark edit combo box
* use of current selection for bookmark/folder creation parent folder
* status bar updates and popup menus cosmetics
* idle time database updates (speed feeling)Does not implement (maybe future work):
* DND exchanges between bookmark bar and bookmark panel
* DND bookmark creationNotes:
1-recommit with use of accessors for GtkSelectionData fields
Preview Diff
1 | === modified file 'katze/katze-array.c' |
2 | --- katze/katze-array.c 2012-08-08 23:02:56 +0000 |
3 | +++ katze/katze-array.c 2013-05-21 05:35:32 +0000 |
4 | @@ -42,6 +42,9 @@ |
5 | (*add_item) (KatzeArray* array, |
6 | gpointer item); |
7 | void |
8 | + (*update_item) (KatzeArray* array, |
9 | + gpointer item); |
10 | + void |
11 | (*remove_item) (KatzeArray* array, |
12 | gpointer item); |
13 | void |
14 | @@ -59,6 +62,7 @@ |
15 | |
16 | enum { |
17 | ADD_ITEM, |
18 | + UPDATE_ITEM, |
19 | REMOVE_ITEM, |
20 | MOVE_ITEM, |
21 | CLEAR, |
22 | @@ -95,6 +99,13 @@ |
23 | } |
24 | |
25 | static void |
26 | +_katze_array_update_item (KatzeArray* array, |
27 | + gpointer item) |
28 | +{ |
29 | + _katze_array_update (array); |
30 | +} |
31 | + |
32 | +static void |
33 | _katze_array_remove_item (KatzeArray* array, |
34 | gpointer item) |
35 | { |
36 | @@ -147,6 +158,17 @@ |
37 | G_TYPE_NONE, 1, |
38 | G_TYPE_POINTER); |
39 | |
40 | + signals[UPDATE_ITEM] = g_signal_new ( |
41 | + "update-item", |
42 | + G_TYPE_FROM_CLASS (class), |
43 | + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), |
44 | + G_STRUCT_OFFSET (KatzeArrayClass, add_item), |
45 | + 0, |
46 | + NULL, |
47 | + g_cclosure_marshal_VOID__POINTER, |
48 | + G_TYPE_NONE, 1, |
49 | + G_TYPE_POINTER); |
50 | + |
51 | signals[REMOVE_ITEM] = g_signal_new ( |
52 | "remove-item", |
53 | G_TYPE_FROM_CLASS (class), |
54 | @@ -213,6 +235,7 @@ |
55 | gobject_class->finalize = katze_array_finalize; |
56 | |
57 | class->add_item = _katze_array_add_item; |
58 | + class->update_item = _katze_array_update_item; |
59 | class->remove_item = _katze_array_remove_item; |
60 | class->move_item = _katze_array_move_item; |
61 | class->clear = _katze_array_clear; |
62 | @@ -301,6 +324,23 @@ |
63 | } |
64 | |
65 | /** |
66 | + * katze_array_update_item: |
67 | + * @array: a #KatzeArray |
68 | + * @item: an item |
69 | + * |
70 | + * Notify an update of the item of the array. |
71 | + * |
72 | + **/ |
73 | +void |
74 | +katze_array_update_item (KatzeArray* array, |
75 | + gpointer item) |
76 | +{ |
77 | + g_return_if_fail (KATZE_IS_ARRAY (array)); |
78 | + |
79 | + g_signal_emit (array, signals[UPDATE_ITEM], 0, item); |
80 | +} |
81 | + |
82 | +/** |
83 | * katze_array_remove_item: |
84 | * @array: a #KatzeArray |
85 | * @item: an item |
86 | |
87 | === modified file 'katze/katze-array.h' |
88 | --- katze/katze-array.h 2011-01-19 20:58:26 +0000 |
89 | +++ katze/katze-array.h 2013-05-21 05:35:32 +0000 |
90 | @@ -47,6 +47,10 @@ |
91 | gpointer item); |
92 | |
93 | void |
94 | +katze_array_update_item (KatzeArray* array, |
95 | + gpointer item); |
96 | + |
97 | +void |
98 | katze_array_remove_item (KatzeArray* array, |
99 | gpointer item); |
100 | |
101 | |
102 | === modified file 'katze/katze-item.c' |
103 | --- katze/katze-item.c 2013-02-21 21:36:30 +0000 |
104 | +++ katze/katze-item.c 2013-05-21 05:35:32 +0000 |
105 | @@ -314,11 +314,12 @@ |
106 | katze_item_set_name (KatzeItem* item, |
107 | const gchar* name) |
108 | { |
109 | + gchar* pname = item->name; |
110 | g_return_if_fail (KATZE_IS_ITEM (item)); |
111 | |
112 | katze_assign (item->name, g_strdup (name)); |
113 | - if (item->parent) |
114 | - katze_array_update ((KatzeArray*)item->parent); |
115 | + if (item->parent && g_strcmp0(name, pname)) |
116 | + katze_array_update((KatzeArray*)item->parent); |
117 | g_object_notify (G_OBJECT (item), "name"); |
118 | } |
119 | |
120 | @@ -418,11 +419,12 @@ |
121 | katze_item_set_icon (KatzeItem* item, |
122 | const gchar* icon) |
123 | { |
124 | + gchar *picon = katze_item_get_meta_string (item, "icon"); |
125 | g_return_if_fail (KATZE_IS_ITEM (item)); |
126 | |
127 | katze_item_set_meta_string (item, "icon", icon); |
128 | - if (item->parent) |
129 | - katze_array_update ((KatzeArray*)item->parent); |
130 | + if (item->parent && g_strcmp0(icon, picon)) |
131 | + katze_array_update_item ((KatzeArray*)item->parent, item); |
132 | g_object_notify (G_OBJECT (item), "icon"); |
133 | } |
134 | |
135 | @@ -445,8 +447,13 @@ |
136 | |
137 | g_return_val_if_fail (KATZE_IS_ITEM (item), NULL); |
138 | |
139 | - if (widget && KATZE_ITEM_IS_FOLDER (item)) |
140 | - return gtk_widget_render_icon (widget, GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL); |
141 | + if (widget) |
142 | + { |
143 | + if (KATZE_ITEM_IS_FOLDER (item)) |
144 | + return gtk_widget_render_icon (widget, GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL); |
145 | + if (KATZE_ITEM_IS_BOOKMARK (item) && katze_item_get_meta_boolean (item, "app")) |
146 | + return gtk_widget_render_icon (widget, GTK_STOCK_EXECUTE, GTK_ICON_SIZE_MENU, NULL); |
147 | + } |
148 | if ((pixbuf = midori_paths_get_icon (katze_item_get_icon (item), NULL))) |
149 | return pixbuf; |
150 | if ((pixbuf = midori_paths_get_icon (item->uri, widget))) |
151 | @@ -526,7 +533,8 @@ |
152 | gtk_widget_show (image); |
153 | if (pixbuf != NULL) |
154 | g_object_unref (pixbuf); |
155 | - if (KATZE_ITEM_IS_FOLDER (item)) |
156 | + if (KATZE_ITEM_IS_FOLDER (item) |
157 | + || (KATZE_ITEM_IS_BOOKMARK (item) && katze_item_get_meta_boolean (item, "app"))) |
158 | return image; |
159 | g_object_set_data (G_OBJECT (image), "KatzeItem", g_object_ref (item)); |
160 | g_signal_connect (image, "destroy", |
161 | |
162 | === modified file 'katze/katze-utils.c' |
163 | --- katze/katze-utils.c 2013-04-16 23:16:24 +0000 |
164 | +++ katze/katze-utils.c 2013-05-21 05:35:32 +0000 |
165 | @@ -984,12 +984,99 @@ |
166 | |
167 | g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE); |
168 | |
169 | - if ((selection = gtk_tree_view_get_selection (treeview))) |
170 | - if (gtk_tree_selection_get_selected (selection, model, iter)) |
171 | - return TRUE; |
172 | + selection = gtk_tree_view_get_selection(treeview); |
173 | + |
174 | + switch (gtk_tree_selection_get_mode (selection)) |
175 | + { |
176 | + default: |
177 | + break; |
178 | + |
179 | + case GTK_SELECTION_SINGLE: |
180 | + case GTK_SELECTION_BROWSE: |
181 | + if (gtk_tree_selection_get_selected (selection, model, iter)) |
182 | + return TRUE; |
183 | + break; |
184 | + |
185 | + case GTK_SELECTION_MULTIPLE: |
186 | + if (gtk_tree_selection_count_selected_rows (selection) == 1) |
187 | + { |
188 | + GtkTreeModel *stock_model; |
189 | + GList *list = gtk_tree_selection_get_selected_rows (selection, &stock_model); |
190 | + |
191 | + if (model) |
192 | + *model = stock_model; |
193 | + |
194 | + if (list) |
195 | + { |
196 | + GtkTreePath *path = (GtkTreePath *)g_list_nth_data (list, 0); |
197 | + |
198 | + if (path && (!iter || gtk_tree_model_get_iter (stock_model, iter, path))) |
199 | + { |
200 | + g_list_free_full(list, (GDestroyNotify) gtk_tree_path_free); |
201 | + return TRUE; |
202 | + } |
203 | + |
204 | + g_list_free_full(list, (GDestroyNotify) gtk_tree_path_free); |
205 | + } |
206 | + } |
207 | + } |
208 | + |
209 | return FALSE; |
210 | } |
211 | |
212 | +/** |
213 | + * katze_tree_view_get_selected_rows: |
214 | + * @treeview: a #GtkTreeView |
215 | + * @model: a pointer to store the #GtkTreeModel, or %NULL |
216 | + * @rows: a pointer to store the #GList of #GtkTreePath, or %NULL |
217 | + * |
218 | + * Determines whether there is a selection in @treeview |
219 | + * and sets the @rows to the current selection. |
220 | + * |
221 | + * If there is a selection and @model is not %NULL, it is |
222 | + * set to the model. If @model is %NULL, the @rows will be |
223 | + * set to %NULL. |
224 | + * |
225 | + * Either @model or @rows or both can be %NULL in which case |
226 | + * no value will be assigned in any case. |
227 | + * |
228 | + * When @rows is not %NULL it must be freed using: |
229 | + * g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); |
230 | + * |
231 | + * Return value: the count of selected rows |
232 | + * |
233 | + * Since: 0.4.7.aau.1 |
234 | + **/ |
235 | + |
236 | +gint |
237 | +katze_tree_view_get_selected_rows (GtkTreeView* treeview, |
238 | + GtkTreeModel** model, |
239 | + GList** rows) |
240 | +{ |
241 | + gint count; |
242 | + GtkTreeSelection* selection; |
243 | + |
244 | + if (model) |
245 | + *model = NULL; |
246 | + if (rows) |
247 | + *rows = NULL; |
248 | + |
249 | + g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), 0); |
250 | + |
251 | + selection = gtk_tree_view_get_selection(treeview); |
252 | + |
253 | + count = gtk_tree_selection_count_selected_rows (selection); |
254 | + if (count > 0) |
255 | + { |
256 | + if (model && rows) |
257 | + { |
258 | + *rows = gtk_tree_selection_get_selected_rows (selection, model); |
259 | + } |
260 | + } |
261 | + |
262 | + return count; |
263 | +} |
264 | + |
265 | void |
266 | katze_bookmark_populate_tree_view (KatzeArray* array, |
267 | GtkTreeStore* model, |
268 | |
269 | === modified file 'katze/katze-utils.h' |
270 | --- katze/katze-utils.h 2013-04-16 22:10:56 +0000 |
271 | +++ katze/katze-utils.h 2013-05-21 05:35:32 +0000 |
272 | @@ -88,6 +88,11 @@ |
273 | GtkTreeModel** model, |
274 | GtkTreeIter* iter); |
275 | |
276 | +gint |
277 | +katze_tree_view_get_selected_rows (GtkTreeView* treeview, |
278 | + GtkTreeModel** model, |
279 | + GList** rows); |
280 | + |
281 | void |
282 | katze_bookmark_populate_tree_view (KatzeArray* array, |
283 | GtkTreeStore* model, |
284 | |
285 | === modified file 'midori/midori-array.c' |
286 | --- midori/midori-array.c 2013-04-16 23:16:24 +0000 |
287 | +++ midori/midori-array.c 2013-05-21 05:35:32 +0000 |
288 | @@ -1109,6 +1109,12 @@ |
289 | * @fields: comma separated list of fields |
290 | * @condition: condition, like "folder = '%q'" |
291 | * @value: a value to be inserted if @condition contains %q |
292 | + * @order: a value to be inserted in "ORDER BY" |
293 | + * default order is : |
294 | + * (uri='') ASC, title DESC |
295 | + * @order is inserted before title. |
296 | + * order then becomes : |
297 | + * (uri='') ASC, @order title DESC |
298 | * @recursive: if %TRUE include children |
299 | * |
300 | * Stores the result in a #KatzeArray. |
301 | @@ -1122,6 +1128,7 @@ |
302 | const gchar* fields, |
303 | const gchar* condition, |
304 | const gchar* value, |
305 | + const gchar* order, |
306 | gboolean recursive) |
307 | { |
308 | sqlite3* db; |
309 | @@ -1138,7 +1145,8 @@ |
310 | g_return_val_if_fail (db != NULL, NULL); |
311 | |
312 | sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s " |
313 | - "ORDER BY (uri='') ASC, title DESC", fields, condition); |
314 | + "ORDER BY (uri='') ASC, %s title DESC", |
315 | + fields, condition, order ? order : ""); |
316 | if (strstr (condition, "%q")) |
317 | { |
318 | sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : ""); |
319 | @@ -1159,7 +1167,7 @@ |
320 | gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT, |
321 | katze_item_get_meta_integer (item, "id")); |
322 | KatzeArray* subarray = midori_array_query_recursive (bookmarks, |
323 | - fields, "parentid=%q", parentid, TRUE); |
324 | + fields, "parentid=%q", parentid, order, TRUE); |
325 | katze_item_set_name (KATZE_ITEM (subarray), katze_item_get_name (item)); |
326 | katze_array_add_item (array, subarray); |
327 | |
328 | @@ -1176,6 +1184,12 @@ |
329 | * @fields: comma separated list of fields |
330 | * @condition: condition, like "folder = '%q'" |
331 | * @value: a value to be inserted if @condition contains %q |
332 | + * @order: a value to be inserted in "ORDER BY" |
333 | + * default order is : |
334 | + * (uri='') ASC, title DESC |
335 | + * @order is inserted before title. |
336 | + * order then becomes : |
337 | + * (uri='') ASC, @order title DESC |
338 | * |
339 | * Stores the result in a #KatzeArray. |
340 | * |
341 | @@ -1189,8 +1203,128 @@ |
342 | midori_array_query (KatzeArray* bookmarks, |
343 | const gchar* fields, |
344 | const gchar* condition, |
345 | - const gchar* value) |
346 | -{ |
347 | - return midori_array_query_recursive (bookmarks, fields, condition, value, FALSE); |
348 | + const gchar* value, |
349 | + const gchar* order) |
350 | +{ |
351 | + return midori_array_query_recursive (bookmarks, fields, condition, value, order, FALSE); |
352 | +} |
353 | + |
354 | +static gint64 |
355 | +count_from_sqlite (sqlite3* db, |
356 | + const gchar* sqlcmd) |
357 | +{ |
358 | + gint64 count = -1; |
359 | + sqlite3_stmt* stmt; |
360 | + gint result; |
361 | + |
362 | + result = sqlite3_prepare_v2 (db, sqlcmd, -1, &stmt, NULL); |
363 | + if (result != SQLITE_OK) |
364 | + return -1; |
365 | + |
366 | + g_assert (sqlite3_column_count (stmt) == 1); |
367 | + |
368 | + if ((result = sqlite3_step (stmt)) == SQLITE_ROW) |
369 | + count = sqlite3_column_int64(stmt, 0); |
370 | + |
371 | + sqlite3_clear_bindings (stmt); |
372 | + sqlite3_reset (stmt); |
373 | + |
374 | + return count; |
375 | +} |
376 | + |
377 | +/** |
378 | + * midori_array_count_recursive: |
379 | + * @array: the main bookmark array |
380 | + * @condition: condition, like "folder = '%q'" |
381 | + * @value: a value to be inserted if @condition contains %q |
382 | + * @recursive: if %TRUE include children |
383 | + * |
384 | + * Return value: the number of elements on success, -1 otherwise |
385 | + * |
386 | + * Since: 0.5.1 |
387 | + **/ |
388 | +gint64 |
389 | +midori_array_count_recursive (KatzeArray* bookmarks, |
390 | + const gchar* condition, |
391 | + const gchar* value, |
392 | + KatzeItem* folder, |
393 | + gboolean recursive) |
394 | +{ |
395 | + gint64 count = -1; |
396 | + gint64 id = -1; |
397 | + sqlite3* db; |
398 | + gchar* sqlcmd; |
399 | + char* sqlcmd_value; |
400 | + KatzeArray* array; |
401 | + KatzeItem* item; |
402 | + GList* list; |
403 | + gchar* id_str; |
404 | + |
405 | + g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), -1); |
406 | + g_return_val_if_fail (!folder || KATZE_ITEM_IS_FOLDER (folder), -1); |
407 | + g_return_val_if_fail (condition, -1); |
408 | + db = g_object_get_data (G_OBJECT (bookmarks), "db"); |
409 | + g_return_val_if_fail (db != NULL, -1); |
410 | + |
411 | + g_assert(!strstr("parentid", condition)); |
412 | + |
413 | + id = folder ? katze_item_get_meta_integer (folder, "id") : 0; |
414 | + |
415 | + if (id > 0) |
416 | + sqlcmd = g_strdup_printf ("SELECT COUNT(*) FROM bookmarks " |
417 | + "WHERE parentid = %" G_GINT64_FORMAT " AND %s", |
418 | + id, |
419 | + condition); |
420 | + else |
421 | + sqlcmd = g_strdup_printf ("SELECT COUNT(*) FROM bookmarks " |
422 | + "WHERE parentid IS NULL AND %s ", |
423 | + condition); |
424 | + |
425 | + if (strstr (condition, "%q")) |
426 | + { |
427 | + sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : ""); |
428 | + count = count_from_sqlite (db, sqlcmd_value); |
429 | + sqlite3_free (sqlcmd_value); |
430 | + } |
431 | + else |
432 | + count = count_from_sqlite (db, sqlcmd); |
433 | + |
434 | + g_free (sqlcmd); |
435 | + |
436 | + if (!recursive || (count < 0)) |
437 | + return count; |
438 | + |
439 | + if (id > 0) |
440 | + sqlcmd = g_strdup_printf ("parentid = %" G_GINT64_FORMAT " AND uri = ''", |
441 | + id); |
442 | + else |
443 | + sqlcmd = g_strdup ("parentid IS NULL AND uri = '' "); |
444 | + |
445 | + array = midori_array_query_recursive (bookmarks, "id, uri", sqlcmd, NULL, NULL, FALSE); |
446 | + |
447 | + g_free (sqlcmd); |
448 | + |
449 | + KATZE_ARRAY_FOREACH_ITEM_L (item, array, list) |
450 | + { |
451 | + if (KATZE_ITEM_IS_FOLDER(item)) |
452 | + { |
453 | + gint64 sub_count = midori_array_count_recursive (bookmarks, |
454 | + condition, |
455 | + value, |
456 | + item, |
457 | + recursive); |
458 | + |
459 | + if (sub_count < 0) |
460 | + { |
461 | + g_object_unref (array); |
462 | + return -1; |
463 | + } |
464 | + |
465 | + count += sub_count; |
466 | + } |
467 | + } |
468 | + |
469 | + g_object_unref (array); |
470 | + return count; |
471 | } |
472 | |
473 | |
474 | === modified file 'midori/midori-array.h' |
475 | --- midori/midori-array.h 2012-01-03 20:15:19 +0000 |
476 | +++ midori/midori-array.h 2013-05-21 05:35:32 +0000 |
477 | @@ -34,17 +34,26 @@ |
478 | midori_array_query (KatzeArray* array, |
479 | const gchar* fields, |
480 | const gchar* condition, |
481 | - const gchar* value); |
482 | + const gchar* value, |
483 | + const gchar* order); |
484 | |
485 | KatzeArray* |
486 | midori_array_query_recursive (KatzeArray* array, |
487 | const gchar* fields, |
488 | const gchar* condition, |
489 | const gchar* value, |
490 | + const gchar* order, |
491 | gboolean recursive); |
492 | |
493 | KatzeArray* |
494 | katze_array_from_sqlite (sqlite3* db, |
495 | const gchar* sqlcmd); |
496 | |
497 | +gint64 |
498 | +midori_array_count_recursive (KatzeArray* bookmarks, |
499 | + const gchar* condition, |
500 | + const gchar* value, |
501 | + KatzeItem* folder, |
502 | + gboolean recursive); |
503 | + |
504 | #endif /* !__MIDORI_ARRAY_H__ */ |
505 | |
506 | === modified file 'midori/midori-bookmarks.c' |
507 | --- midori/midori-bookmarks.c 2012-11-25 15:37:41 +0000 |
508 | +++ midori/midori-bookmarks.c 2013-05-21 05:35:32 +0000 |
509 | @@ -25,6 +25,19 @@ |
510 | #include <unistd.h> |
511 | #endif |
512 | |
513 | +#define MIDORI_BOOKMARKS_DB_CONTROL(a) ((MidoriBookmarksDBControl*)(a)) |
514 | +typedef struct _MidoriBookmarksDBControl MidoriBookmarksDBControl; |
515 | +struct _MidoriBookmarksDBControl |
516 | +{ |
517 | + sqlite3* db; |
518 | + GHashTable* pending_updates; |
519 | +}; |
520 | + |
521 | +static void |
522 | +midori_bookmarks_recursive_remove_childs_db (KatzeArray* array, |
523 | + KatzeItem* item, |
524 | + sqlite3* db); |
525 | + |
526 | void |
527 | midori_bookmarks_dbtracer (void* dummy, |
528 | const char* query) |
529 | @@ -32,31 +45,155 @@ |
530 | g_printerr ("%s\n", query); |
531 | } |
532 | |
533 | -void |
534 | +static guint |
535 | +item_hash (gconstpointer item) |
536 | +{ |
537 | + gint64 id = katze_item_get_meta_integer (KATZE_ITEM (item), "id"); |
538 | + return g_int64_hash (&id); |
539 | +} |
540 | + |
541 | +static gboolean |
542 | +item_equal (gconstpointer item_a, gconstpointer item_b) |
543 | +{ |
544 | + gint64 id_a = katze_item_get_meta_integer (KATZE_ITEM (item_a), "id"); |
545 | + gint64 id_b = katze_item_get_meta_integer (KATZE_ITEM (item_b), "id"); |
546 | + return (id_a == id_b)? TRUE : FALSE; |
547 | +} |
548 | + |
549 | +static gboolean |
550 | +midori_bookmarks_idle (gpointer data) |
551 | +{ |
552 | + MidoriBookmarksDBControl* control = MIDORI_BOOKMARKS_DB_CONTROL (data); |
553 | + GHashTableIter hash_iter; |
554 | + gpointer key, value; |
555 | + |
556 | + g_hash_table_iter_init (&hash_iter, control->pending_updates); |
557 | + |
558 | + while (g_hash_table_iter_next (&hash_iter, &key, &value)) |
559 | + { |
560 | + KatzeItem *item = KATZE_ITEM(key); |
561 | + |
562 | + midori_bookmarks_update_item_db (control->db, item); |
563 | + g_object_unref (item); |
564 | + } |
565 | + |
566 | + g_hash_table_remove_all (control->pending_updates); |
567 | + |
568 | + return FALSE; |
569 | +} |
570 | + |
571 | +static void |
572 | midori_bookmarks_add_item_cb (KatzeArray* array, |
573 | KatzeItem* item, |
574 | - sqlite3* db) |
575 | + MidoriBookmarksDBControl* control) |
576 | { |
577 | - midori_bookmarks_insert_item_db (db, item, |
578 | + midori_bookmarks_insert_item_db (control->db, item, |
579 | katze_item_get_meta_integer (item, "parentid")); |
580 | } |
581 | |
582 | -void |
583 | +static void |
584 | +midori_bookmarks_update_item_cb (KatzeArray* array, |
585 | + KatzeItem* item, |
586 | + MidoriBookmarksDBControl* control) |
587 | +{ |
588 | + if (!g_hash_table_size (control->pending_updates)) |
589 | + g_idle_add (midori_bookmarks_idle, control); |
590 | + else if (g_hash_table_lookup (control->pending_updates, item)) |
591 | + return; |
592 | + |
593 | + g_object_ref (item); |
594 | + g_hash_table_insert (control->pending_updates, item, item); |
595 | +} |
596 | + |
597 | +static void |
598 | midori_bookmarks_remove_item_cb (KatzeArray* array, |
599 | KatzeItem* item, |
600 | - sqlite3* db) |
601 | + MidoriBookmarksDBControl* control) |
602 | { |
603 | gchar* sqlcmd; |
604 | char* errmsg = NULL; |
605 | - |
606 | + gpointer found; |
607 | + |
608 | + if (KATZE_ITEM_IS_FOLDER (item)) |
609 | + { |
610 | + gint64 id = katze_item_get_meta_integer (item, "id"); |
611 | + GHashTableIter iter; |
612 | + gpointer key, value; |
613 | + |
614 | + g_hash_table_iter_init (&iter, control->pending_updates); |
615 | + |
616 | + while (g_hash_table_iter_next (&iter, &key, &value)) |
617 | + { |
618 | + KatzeItem *hash_item = KATZE_ITEM(key); |
619 | + |
620 | + gint64 parentid = katze_item_get_meta_integer (hash_item, "parentid"); |
621 | + if (parentid == id) |
622 | + { |
623 | + g_hash_table_iter_remove (&iter); |
624 | + g_object_unref (hash_item); |
625 | + } |
626 | + } |
627 | + |
628 | + midori_bookmarks_recursive_remove_childs_db (array, item, control->db); |
629 | + } |
630 | + |
631 | + if (found = g_hash_table_lookup (control->pending_updates, item)) |
632 | + { |
633 | + g_hash_table_remove (control->pending_updates, found); |
634 | + g_object_unref (found); |
635 | + } |
636 | |
637 | sqlcmd = sqlite3_mprintf ( |
638 | "DELETE FROM bookmarks WHERE id = %" G_GINT64_FORMAT ";", |
639 | katze_item_get_meta_integer (item, "id")); |
640 | |
641 | + if (sqlite3_exec (control->db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK) |
642 | + { |
643 | + g_printerr (_("Failed to remove bookmark item: %s\n"), errmsg); |
644 | + sqlite3_free (errmsg); |
645 | + } |
646 | + |
647 | + sqlite3_free (sqlcmd); |
648 | +} |
649 | + |
650 | +static void |
651 | +midori_bookmarks_recursive_remove_childs_db (KatzeArray* array, |
652 | + KatzeItem* item, |
653 | + sqlite3* db) |
654 | +{ |
655 | + gint64 parentid = katze_item_get_meta_integer (item, "id"); |
656 | + char* errmsg = NULL; |
657 | + KatzeArray* childs_array; |
658 | + gchar* sqlcmd; |
659 | + |
660 | + sqlcmd = g_strdup_printf ("SELECT id FROM bookmarks" |
661 | + "WHERE uri = '' AND parentid = %"G_GINT64_FORMAT ";", |
662 | + parentid); |
663 | + |
664 | + childs_array = katze_array_from_sqlite (db, sqlcmd); |
665 | + g_free (sqlcmd); |
666 | + |
667 | + if (KATZE_IS_ARRAY (childs_array)) |
668 | + { |
669 | + KatzeItem* child; |
670 | + GList* list; |
671 | + |
672 | + KATZE_ARRAY_FOREACH_ITEM_L (child, childs_array, list) |
673 | + { |
674 | + katze_array_remove_item (array, child); |
675 | + } |
676 | + |
677 | + g_list_free (list); |
678 | + g_object_unref(array); |
679 | + } |
680 | + |
681 | + sqlcmd = sqlite3_mprintf ( |
682 | + "DELETE FROM bookmarks WHERE parentid = %" G_GINT64_FORMAT ";", |
683 | + parentid); |
684 | + |
685 | if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK) |
686 | { |
687 | - g_printerr (_("Failed to remove history item: %s\n"), errmsg); |
688 | + g_printerr (_("Failed to remove bookmarks folder child items: %s\n"), errmsg); |
689 | sqlite3_free (errmsg); |
690 | } |
691 | |
692 | @@ -141,6 +278,7 @@ |
693 | gchar* sql_errmsg = NULL; |
694 | gchar* import_errmsg = NULL; |
695 | KatzeArray* array; |
696 | + MidoriBookmarksDBControl* control; |
697 | |
698 | g_return_val_if_fail (errmsg != NULL, NULL); |
699 | |
700 | @@ -279,12 +417,18 @@ |
701 | init_success: |
702 | g_free (newfile); |
703 | g_free (oldfile); |
704 | + control = MIDORI_BOOKMARKS_DB_CONTROL (g_malloc (sizeof (*control))); |
705 | + control->db = db; |
706 | + control->pending_updates = g_hash_table_new (item_hash, item_equal); |
707 | array = katze_array_new (KATZE_TYPE_ARRAY); |
708 | g_signal_connect (array, "add-item", |
709 | - G_CALLBACK (midori_bookmarks_add_item_cb), db); |
710 | + G_CALLBACK (midori_bookmarks_add_item_cb), control); |
711 | + g_signal_connect (array, "update-item", |
712 | + G_CALLBACK (midori_bookmarks_update_item_cb), control); |
713 | g_signal_connect (array, "remove-item", |
714 | - G_CALLBACK (midori_bookmarks_remove_item_cb), db); |
715 | + G_CALLBACK (midori_bookmarks_remove_item_cb), control); |
716 | g_object_set_data (G_OBJECT (array), "db", db); |
717 | + g_object_set_data (G_OBJECT (array), "control", control); |
718 | return array; |
719 | |
720 | init_failed: |
721 | @@ -323,5 +467,8 @@ |
722 | sqlite3* db = g_object_get_data (G_OBJECT (array), "db"); |
723 | g_return_if_fail (db != NULL); |
724 | sqlite3_close (db); |
725 | + MidoriBookmarksDBControl* control = g_object_get_data (G_OBJECT (array), "control"); |
726 | + g_return_if_fail (control != NULL); |
727 | + g_hash_table_unref (control->pending_updates); |
728 | } |
729 | |
730 | |
731 | === modified file 'midori/midori-bookmarks.h' |
732 | --- midori/midori-bookmarks.h 2012-11-25 15:37:41 +0000 |
733 | +++ midori/midori-bookmarks.h 2013-05-21 05:35:32 +0000 |
734 | @@ -16,16 +16,6 @@ |
735 | #include <sqlite3.h> |
736 | #include <katze/katze.h> |
737 | |
738 | -void |
739 | -midori_bookmarks_add_item_cb (KatzeArray* array, |
740 | - KatzeItem* item, |
741 | - sqlite3* db); |
742 | - |
743 | -void |
744 | -midori_bookmarks_remove_item_cb (KatzeArray* array, |
745 | - KatzeItem* item, |
746 | - sqlite3* db); |
747 | - |
748 | KatzeArray* |
749 | midori_bookmarks_new (char** errmsg); |
750 | |
751 | |
752 | === modified file 'midori/midori-browser.c' |
753 | --- midori/midori-browser.c 2013-05-19 09:33:02 +0000 |
754 | +++ midori/midori-browser.c 2013-05-21 05:35:32 +0000 |
755 | @@ -96,6 +96,8 @@ |
756 | gboolean show_statusbar; |
757 | guint maximum_history_age; |
758 | guint last_web_search; |
759 | + |
760 | + gboolean bookmarkbar_populate; |
761 | }; |
762 | |
763 | G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW) |
764 | @@ -166,16 +168,14 @@ |
765 | KatzeArray* array, |
766 | gint64 parentid); |
767 | |
768 | -gboolean |
769 | -midori_bookmarks_update_item_db (sqlite3* db, |
770 | - KatzeItem* item); |
771 | - |
772 | void |
773 | midori_browser_open_bookmark (MidoriBrowser* browser, |
774 | KatzeItem* item); |
775 | |
776 | static void |
777 | midori_bookmarkbar_populate (MidoriBrowser* browser); |
778 | +static void |
779 | +midori_bookmarkbar_populate_idle (MidoriBrowser* browser); |
780 | |
781 | static void |
782 | midori_bookmarkbar_clear (GtkWidget* toolbar); |
783 | @@ -484,6 +484,9 @@ |
784 | inter = ZEITGEIST_ZG_DELETE_EVENT; |
785 | else |
786 | g_assert_not_reached (); |
787 | + g_assert (KATZE_IS_ITEM (item)); |
788 | + if (KATZE_ITEM_IS_FOLDER (item)) |
789 | + return; |
790 | zeitgeist_log_insert_events_no_reply (zeitgeist_log_get_default (), |
791 | zeitgeist_event_new_full (inter, ZEITGEIST_ZG_USER_ACTIVITY, |
792 | "application://midori.desktop", |
793 | @@ -818,9 +821,8 @@ |
794 | |
795 | static GtkWidget* |
796 | midori_bookmark_folder_button_new (KatzeArray* array, |
797 | - gboolean new_bookmark, |
798 | gint64 selected, |
799 | - gint64 parentid) |
800 | + gint64 new_parentid) |
801 | { |
802 | GtkListStore* model; |
803 | GtkWidget* combo; |
804 | @@ -829,8 +831,16 @@ |
805 | sqlite3* db; |
806 | sqlite3_stmt* statement; |
807 | gint result; |
808 | - const gchar* sqlcmd = "SELECT title, id FROM bookmarks WHERE uri='' ORDER BY title ASC"; |
809 | + const gchar* sqlcmd = "SELECT title, id, parentid FROM bookmarks WHERE uri='' ORDER BY parentid, title ASC"; |
810 | + guint selection; |
811 | + gchar *parent_path; |
812 | + gint64 parent_id; |
813 | |
814 | + /* folder combo box content: |
815 | + ** 0: path |
816 | + ** 1: path ellipsize mode |
817 | + ** 2: id |
818 | + */ |
819 | model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT64); |
820 | combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model)); |
821 | renderer = gtk_cell_renderer_text_new (); |
822 | @@ -838,31 +848,102 @@ |
823 | gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "text", 0); |
824 | gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "ellipsize", 1); |
825 | gtk_list_store_insert_with_values (model, NULL, G_MAXINT, |
826 | - 0, _("Bookmarks"), 1, PANGO_ELLIPSIZE_END, 2, (gint64)0, -1); |
827 | + 0, _("Bookmarks"), 1, PANGO_ELLIPSIZE_MIDDLE, 2, (gint64)0, -1); |
828 | gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); |
829 | |
830 | db = g_object_get_data (G_OBJECT (array), "db"); |
831 | g_return_val_if_fail (db != NULL, NULL); |
832 | + selection = 0; |
833 | + parent_id = -1; |
834 | + parent_path = NULL; |
835 | n = 1; |
836 | if ((result = sqlite3_prepare_v2 (db, sqlcmd, -1, &statement, NULL)) == SQLITE_OK) |
837 | while ((result = sqlite3_step (statement)) == SQLITE_ROW) |
838 | { |
839 | - const unsigned char* name = sqlite3_column_text (statement, 0); |
840 | + const unsigned char* title = sqlite3_column_text (statement, 0); |
841 | gint64 id = sqlite3_column_int64 (statement, 1); |
842 | + gint64 parentid = sqlite3_column_int64 (statement, 2); |
843 | |
844 | /* do not show the folder itself */ |
845 | if (id != selected) |
846 | - { |
847 | - gtk_list_store_insert_with_values (model, NULL, G_MAXINT, |
848 | - 0, name, 1, PANGO_ELLIPSIZE_END, 2, id, -1); |
849 | + { |
850 | + if (parentid != parent_id) |
851 | + { |
852 | + if (parent_path) |
853 | + { |
854 | + g_free(parent_path); |
855 | + parent_path = NULL; |
856 | + parent_id = -1; |
857 | + } |
858 | + |
859 | + if (!parentid) |
860 | + { |
861 | + parent_id = 0; |
862 | + parent_path = g_strdup(_("Bookmarks")); |
863 | + } |
864 | + else |
865 | + { |
866 | + GtkTreeIter iter; |
867 | + gboolean valid; |
868 | + |
869 | + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter); |
870 | + |
871 | + while (valid) |
872 | + { |
873 | + gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, |
874 | + 2, &parent_id, -1); |
875 | + |
876 | + if (parentid == parent_id) |
877 | + { |
878 | + gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, |
879 | + 0, &parent_path, -1); |
880 | + break; |
881 | + } |
882 | + |
883 | + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter); |
884 | + } |
885 | + } |
886 | + } |
887 | + |
888 | + /* If something went wrong, fallback to title presentation */ |
889 | + if (parent_path) |
890 | + { |
891 | + gchar *path = g_strdup_printf ("%s/%s", parent_path, title); |
892 | + |
893 | + gtk_list_store_insert_with_values (model, NULL, G_MAXINT, |
894 | + 0, path ? path : (gchar*)title, |
895 | + 1, PANGO_ELLIPSIZE_MIDDLE, |
896 | + 2, id, -1); |
897 | + |
898 | + if (path) |
899 | + g_free (path); |
900 | + } |
901 | + else |
902 | + { |
903 | + gtk_list_store_insert_with_values (model, NULL, G_MAXINT, |
904 | + 0, title, |
905 | + 1, PANGO_ELLIPSIZE_MIDDLE, |
906 | + 2, id, -1); |
907 | + parent_id = -1; |
908 | + } |
909 | + |
910 | + if (id == new_parentid) |
911 | + selection = n; |
912 | |
913 | - if (!new_bookmark && id == parentid) |
914 | - gtk_combo_box_set_active (GTK_COMBO_BOX (combo), n); |
915 | n++; |
916 | } |
917 | } |
918 | + |
919 | + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), selection); |
920 | + |
921 | if (n < 2) |
922 | gtk_widget_set_sensitive (combo, FALSE); |
923 | + |
924 | + if (parent_path) |
925 | + g_free (parent_path); |
926 | + |
927 | + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE (model), 0, GTK_SORT_ASCENDING); |
928 | + |
929 | return combo; |
930 | } |
931 | |
932 | @@ -876,14 +957,8 @@ |
933 | |
934 | if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) |
935 | { |
936 | - gchar* selected = NULL; |
937 | GtkTreeModel* model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); |
938 | - gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &selected, 2, &id, -1); |
939 | - |
940 | - if (g_str_equal (selected, _("Bookmarks"))) |
941 | - id = 0; |
942 | - |
943 | - g_free (selected); |
944 | + gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 2, &id, -1); |
945 | } |
946 | |
947 | return id; |
948 | @@ -910,11 +985,12 @@ |
949 | /* Private function, used by MidoriBookmarks and MidoriHistory */ |
950 | /* static */ gboolean |
951 | midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, |
952 | - KatzeItem* bookmark, |
953 | + KatzeItem* bookmark_or_parent, |
954 | gboolean new_bookmark, |
955 | gboolean is_folder, |
956 | GtkWidget* proxy) |
957 | { |
958 | + KatzeItem* bookmark = bookmark_or_parent; |
959 | const gchar* title; |
960 | GtkWidget* dialog; |
961 | GtkWidget* content_area; |
962 | @@ -980,7 +1056,7 @@ |
963 | gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); |
964 | gtk_container_set_border_width (GTK_CONTAINER (content_area), 5); |
965 | |
966 | - if (!bookmark) |
967 | + if (new_bookmark) |
968 | { |
969 | view = midori_browser_get_current_tab (browser); |
970 | if (is_folder) |
971 | @@ -993,6 +1069,12 @@ |
972 | bookmark = g_object_new (KATZE_TYPE_ITEM, |
973 | "uri", midori_view_get_display_uri (MIDORI_VIEW (view)), |
974 | "name", midori_view_get_display_title (MIDORI_VIEW (view)), NULL); |
975 | + |
976 | + katze_item_set_meta_integer ( |
977 | + bookmark, "parentid", |
978 | + (!bookmark_or_parent |
979 | + ? 0 |
980 | + : katze_item_get_meta_integer (bookmark_or_parent, "id"))); |
981 | } |
982 | |
983 | entry_title = gtk_entry_new (); |
984 | @@ -1020,7 +1102,7 @@ |
985 | } |
986 | |
987 | combo_folder = midori_bookmark_folder_button_new (browser->bookmarks, |
988 | - new_bookmark, katze_item_get_meta_integer (bookmark, "id"), |
989 | + katze_item_get_meta_integer (bookmark, "id"), |
990 | katze_item_get_meta_integer (bookmark, "parentid")); |
991 | gtk_container_add (GTK_CONTAINER (content_area), combo_folder); |
992 | |
993 | @@ -1054,7 +1136,7 @@ |
994 | { |
995 | gint64 selected; |
996 | |
997 | - katze_item_set_name (bookmark, |
998 | + katze_item_set_name (bookmark, |
999 | gtk_entry_get_text (GTK_ENTRY (entry_title))); |
1000 | katze_item_set_meta_integer (bookmark, "toolbar", |
1001 | gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_toolbar))); |
1002 | @@ -1072,16 +1154,11 @@ |
1003 | if (new_bookmark) |
1004 | katze_array_add_item (browser->bookmarks, bookmark); |
1005 | else |
1006 | - midori_bookmarks_update_item_db (db, bookmark); |
1007 | - midori_browser_update_history (bookmark, "bookmark", new_bookmark ? "create" : "modify"); |
1008 | + katze_array_update_item (browser->bookmarks, bookmark); |
1009 | |
1010 | - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_toolbar))) |
1011 | - if (!gtk_widget_get_visible (browser->bookmarkbar)) |
1012 | - _action_set_active (browser, "Bookmarkbar", TRUE); |
1013 | return_status = TRUE; |
1014 | } |
1015 | - if (gtk_widget_get_visible (browser->bookmarkbar)) |
1016 | - midori_bookmarkbar_populate (browser); |
1017 | + |
1018 | gtk_widget_destroy (dialog); |
1019 | return return_status; |
1020 | } |
1021 | @@ -3108,7 +3185,8 @@ |
1022 | condition = "parentid = %q"; |
1023 | |
1024 | bookmarks = midori_array_query (browser->bookmarks, |
1025 | - "id, title, parentid, uri, app, pos_panel, pos_bar", condition, id); |
1026 | + "id, title, parentid, uri, app, pos_panel, pos_bar", condition, id, |
1027 | + "pos_panel ASC,"); |
1028 | if (!bookmarks) |
1029 | return FALSE; |
1030 | |
1031 | @@ -4143,7 +4221,10 @@ |
1032 | else if (!KATZE_IS_ARRAY (item) && strcmp (stock_id, GTK_STOCK_DELETE)) |
1033 | gtk_widget_set_sensitive (menuitem, uri != NULL); |
1034 | g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item); |
1035 | - g_signal_connect (menuitem, "activate", G_CALLBACK (callback), userdata); |
1036 | + if (callback) |
1037 | + g_signal_connect (menuitem, "activate", G_CALLBACK (callback), userdata); |
1038 | + else |
1039 | + gtk_widget_set_sensitive (menuitem, FALSE); |
1040 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
1041 | gtk_widget_show (menuitem); |
1042 | } |
1043 | @@ -4444,7 +4525,7 @@ |
1044 | gtk_widget_show_all (hbox); |
1045 | |
1046 | combobox_folder = midori_bookmark_folder_button_new (browser->bookmarks, |
1047 | - FALSE, 0, 0); |
1048 | + 0, 0); |
1049 | gtk_container_add (GTK_CONTAINER (content_area), combobox_folder); |
1050 | |
1051 | gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); |
1052 | @@ -4538,7 +4619,7 @@ |
1053 | |
1054 | error = NULL; |
1055 | bookmarks = midori_array_query_recursive (browser->bookmarks, |
1056 | - "*", "parentid IS NULL", NULL, TRUE); |
1057 | + "*", "parentid IS NULL", NULL, NULL, TRUE); |
1058 | if (!midori_array_to_file (bookmarks, path, format, &error)) |
1059 | { |
1060 | sokoke_message_dialog (GTK_MESSAGE_ERROR, |
1061 | @@ -5963,6 +6044,21 @@ |
1062 | } |
1063 | } |
1064 | |
1065 | +static gboolean |
1066 | +midori_browser_idle (gpointer data) |
1067 | +{ |
1068 | + MidoriBrowser* browser = MIDORI_BROWSER (data); |
1069 | + |
1070 | + if (browser->bookmarkbar_populate) |
1071 | + { |
1072 | + midori_bookmarkbar_populate_idle (browser); |
1073 | + |
1074 | + browser->bookmarkbar_populate = FALSE; |
1075 | + } |
1076 | + |
1077 | + return FALSE; |
1078 | +} |
1079 | + |
1080 | static void |
1081 | midori_browser_init (MidoriBrowser* browser) |
1082 | { |
1083 | @@ -6140,6 +6236,8 @@ |
1084 | "array", dummy_array /* updated, unique */, |
1085 | NULL); |
1086 | g_object_connect (action, |
1087 | + "signal::populate-folder", |
1088 | + _action_bookmarks_populate_folder, browser, |
1089 | "signal::populate-popup", |
1090 | _action_tools_populate_popup, browser, |
1091 | "signal::activate-item-alt", |
1092 | @@ -6443,6 +6541,8 @@ |
1093 | katze_object_assign (browser->history, NULL); |
1094 | katze_object_assign (browser->dial, NULL); |
1095 | |
1096 | + g_idle_remove_by_data (browser); |
1097 | + |
1098 | G_OBJECT_CLASS (midori_browser_parent_class)->finalize (object); |
1099 | } |
1100 | |
1101 | @@ -6978,6 +7078,30 @@ |
1102 | } |
1103 | |
1104 | static void |
1105 | +midori_bookmarkbar_add_item_cb (KatzeArray* bookmarks, |
1106 | + KatzeItem* item, |
1107 | + MidoriBrowser* browser) |
1108 | +{ |
1109 | + if (gtk_widget_get_visible (browser->bookmarkbar)) |
1110 | + midori_bookmarkbar_populate (browser); |
1111 | + else if (katze_item_get_meta_boolean (item, "toolbar")) |
1112 | + _action_set_active (browser, "Bookmarkbar", TRUE); |
1113 | + midori_browser_update_history (item, "bookmark", "created"); |
1114 | +} |
1115 | + |
1116 | +static void |
1117 | +midori_bookmarkbar_update_item_cb (KatzeArray* bookmarks, |
1118 | + KatzeItem* item, |
1119 | + MidoriBrowser* browser) |
1120 | +{ |
1121 | + if (gtk_widget_get_visible (browser->bookmarkbar)) |
1122 | + midori_bookmarkbar_populate (browser); |
1123 | + else if (katze_item_get_meta_boolean (item, "toolbar")) |
1124 | + _action_set_active (browser, "Bookmarkbar", TRUE); |
1125 | + midori_browser_update_history (item, "bookmark", "modify"); |
1126 | +} |
1127 | + |
1128 | +static void |
1129 | midori_bookmarkbar_remove_item_cb (KatzeArray* bookmarks, |
1130 | KatzeItem* item, |
1131 | MidoriBrowser* browser) |
1132 | @@ -6990,6 +7114,16 @@ |
1133 | static void |
1134 | midori_bookmarkbar_populate (MidoriBrowser* browser) |
1135 | { |
1136 | + if (browser->bookmarkbar_populate) |
1137 | + return; |
1138 | + |
1139 | + g_idle_add (midori_browser_idle, browser); |
1140 | + browser->bookmarkbar_populate = TRUE; |
1141 | +} |
1142 | + |
1143 | +static void |
1144 | +midori_bookmarkbar_populate_idle (MidoriBrowser* browser) |
1145 | +{ |
1146 | KatzeArray* array; |
1147 | KatzeItem* item; |
1148 | |
1149 | @@ -7000,7 +7134,7 @@ |
1150 | gtk_separator_tool_item_new (), -1); |
1151 | |
1152 | array = midori_array_query (browser->bookmarks, |
1153 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL); |
1154 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL, "pos_bar ASC,"); |
1155 | if (!array) |
1156 | { |
1157 | _action_set_sensitive (browser, "BookmarkAdd", FALSE); |
1158 | @@ -7016,9 +7150,12 @@ |
1159 | { |
1160 | gint64 id = katze_item_get_meta_integer (item, "id"); |
1161 | gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT, id); |
1162 | - KatzeArray* subfolder = midori_array_query (browser->bookmarks, |
1163 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q AND uri != ''", |
1164 | - parentid); |
1165 | + KatzeArray* subfolder = midori_array_query ( |
1166 | + browser->bookmarks, |
1167 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", |
1168 | + "parentid = %q", |
1169 | + parentid, |
1170 | + "pos_panel ASC,"); |
1171 | |
1172 | katze_item_set_name (KATZE_ITEM (subfolder), katze_item_get_name (item)); |
1173 | katze_item_set_meta_integer (KATZE_ITEM (subfolder), "id", id); |
1174 | @@ -7059,8 +7196,15 @@ |
1175 | MidoriWebSettings* settings; |
1176 | |
1177 | if (browser->bookmarks != NULL) |
1178 | + { |
1179 | + g_signal_handlers_disconnect_by_func (browser->bookmarks, |
1180 | + midori_bookmarkbar_add_item_cb, browser); |
1181 | + g_signal_handlers_disconnect_by_func (browser->bookmarks, |
1182 | + midori_bookmarkbar_update_item_cb, browser); |
1183 | g_signal_handlers_disconnect_by_func (browser->bookmarks, |
1184 | midori_bookmarkbar_remove_item_cb, browser); |
1185 | + } |
1186 | + |
1187 | settings = midori_browser_get_settings (browser); |
1188 | g_signal_handlers_disconnect_by_func (settings, |
1189 | midori_browser_show_bookmarkbar_notify_value_cb, browser); |
1190 | @@ -7089,6 +7233,10 @@ |
1191 | g_signal_connect (settings, "notify::show-bookmarkbar", |
1192 | G_CALLBACK (midori_browser_show_bookmarkbar_notify_value_cb), browser); |
1193 | g_object_notify (G_OBJECT (settings), "show-bookmarkbar"); |
1194 | + g_signal_connect_after (bookmarks, "add-item", |
1195 | + G_CALLBACK (midori_bookmarkbar_add_item_cb), browser); |
1196 | + g_signal_connect_after (bookmarks, "update-item", |
1197 | + G_CALLBACK (midori_bookmarkbar_update_item_cb), browser); |
1198 | g_signal_connect_after (bookmarks, "remove-item", |
1199 | G_CALLBACK (midori_bookmarkbar_remove_item_cb), browser); |
1200 | } |
1201 | |
1202 | === modified file 'midori/midori-view.c' |
1203 | --- midori/midori-view.c 2013-05-08 00:51:02 +0000 |
1204 | +++ midori/midori-view.c 2013-05-21 05:35:32 +0000 |
1205 | @@ -2759,7 +2759,7 @@ |
1206 | _("Open Link in New _Window"), STOCK_WINDOW_NEW, |
1207 | G_CALLBACK (midori_web_view_menu_new_window_activate_cb), widget); |
1208 | midori_view_insert_menu_item (menu_shell, -1, |
1209 | - _("Open Link as Web A_pplication"), NULL, |
1210 | + _("Open Link as Web A_pplication"), GTK_STOCK_EXECUTE, |
1211 | G_CALLBACK (midori_web_view_menu_web_app_activate_cb), widget); |
1212 | } |
1213 | |
1214 | |
1215 | === modified file 'panels/midori-bookmarks.c' |
1216 | --- panels/midori-bookmarks.c 2013-02-11 21:49:41 +0000 |
1217 | +++ panels/midori-bookmarks.c 2013-05-21 05:35:32 +0000 |
1218 | @@ -25,6 +25,150 @@ |
1219 | |
1220 | #define COMPLETION_DELAY 200 |
1221 | |
1222 | +G_BEGIN_DECLS |
1223 | + |
1224 | +#define MIDORI_BOOKMARKS_TREE_STORE_TYPE \ |
1225 | + (midori_bookmarks_tree_store_get_type ()) |
1226 | +#define MIDORI_BOOKMARKS_TREE_STORE(obj) \ |
1227 | + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_BOOKMARKS_TREE_STORE_TYPE, MidoriBookmarksTreeStore)) |
1228 | +#define MIDORI_BOOKMARKS_TREE_STORE_CLASS(klass) \ |
1229 | + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_BOOKMARKS_TREE_STORE_TYPE, MidoriBookmarksTreeStoreClass)) |
1230 | + |
1231 | +static gboolean |
1232 | +midori_bookmarks_tree_store_drag_data_get (GtkTreeDragSource* drag_source, |
1233 | + GtkTreePath* source_path, |
1234 | + GtkSelectionData* selection_data); |
1235 | +static gboolean |
1236 | +midori_bookmarks_tree_store_drag_data_delete (GtkTreeDragSource* drag_source, |
1237 | + GtkTreePath* source_path); |
1238 | +static gboolean |
1239 | +midori_bookmarks_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest, |
1240 | + GtkTreePath *dest_path, |
1241 | + GtkSelectionData *selection_data); |
1242 | +static gboolean |
1243 | +midori_bookmarks_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, |
1244 | + GtkTreePath *dest_path, |
1245 | + GtkSelectionData *selection_data); |
1246 | + |
1247 | +typedef struct _MidoriBookmarksTreeStore MidoriBookmarksTreeStore; |
1248 | +typedef struct _MidoriBookmarksTreeStoreClass MidoriBookmarksTreeStoreClass; |
1249 | +typedef struct _TreeRowData TreeRowData; |
1250 | + |
1251 | +struct _MidoriBookmarksTreeStore |
1252 | +{ |
1253 | + GtkTreeStore parent_instance; |
1254 | + |
1255 | + GList* stock_got_rows; |
1256 | + GtkTreeView *source_view; |
1257 | +}; |
1258 | + |
1259 | +struct _MidoriBookmarksTreeStoreClass |
1260 | +{ |
1261 | + GtkTreeStoreClass parent_class; |
1262 | +}; |
1263 | + |
1264 | +struct _TreeRowData |
1265 | +{ |
1266 | + GtkTreeModel *model; |
1267 | + gchar path[4]; |
1268 | +}; |
1269 | + |
1270 | +static GtkTreeDragSourceIface * |
1271 | +gtk_tree_store_gtk_tree_drag_source_iface = NULL; |
1272 | +static GtkTreeDragDestIface * |
1273 | +gtk_tree_store_gtk_tree_drag_dest_iface = NULL; |
1274 | + |
1275 | +static void |
1276 | +midori_bookmarks_tree_store_drag_source_init (GtkTreeDragSourceIface *iface) |
1277 | +{ |
1278 | + gtk_tree_store_gtk_tree_drag_source_iface = g_type_interface_peek_parent (iface); |
1279 | + |
1280 | + iface->drag_data_get = midori_bookmarks_tree_store_drag_data_get; |
1281 | + iface->drag_data_delete = midori_bookmarks_tree_store_drag_data_delete; |
1282 | +} |
1283 | + |
1284 | +static void |
1285 | +midori_bookmarks_tree_store_drag_dest_init (GtkTreeDragDestIface *iface) |
1286 | +{ |
1287 | + gtk_tree_store_gtk_tree_drag_dest_iface = g_type_interface_peek_parent (iface); |
1288 | + |
1289 | + iface->row_drop_possible = midori_bookmarks_tree_store_row_drop_possible; |
1290 | + iface->drag_data_received = midori_bookmarks_tree_store_drag_data_received; |
1291 | +} |
1292 | + |
1293 | +static void |
1294 | +midori_bookmarks_tree_store_init (MidoriBookmarksTreeStore* item) |
1295 | +{ |
1296 | + item->stock_got_rows = NULL; |
1297 | + item->source_view = NULL; |
1298 | +} |
1299 | + |
1300 | +static void |
1301 | +midori_bookmarks_tree_store_class_init (MidoriBookmarksTreeStoreClass *class) |
1302 | +{ |
1303 | +} |
1304 | + |
1305 | +G_DEFINE_TYPE_WITH_CODE (MidoriBookmarksTreeStore, |
1306 | + midori_bookmarks_tree_store, |
1307 | + GTK_TYPE_TREE_STORE, |
1308 | + G_IMPLEMENT_INTERFACE ( |
1309 | + GTK_TYPE_TREE_DRAG_SOURCE, |
1310 | + midori_bookmarks_tree_store_drag_source_init) |
1311 | + G_IMPLEMENT_INTERFACE ( |
1312 | + GTK_TYPE_TREE_DRAG_DEST, |
1313 | + midori_bookmarks_tree_store_drag_dest_init)); |
1314 | + |
1315 | + |
1316 | +GtkTreeStore* |
1317 | +midori_bookmarks_tree_store_new (gint n_columns, ...) |
1318 | +{ |
1319 | + GtkTreeStore* tree_store = GTK_TREE_STORE (g_object_new (MIDORI_BOOKMARKS_TREE_STORE_TYPE, NULL)); |
1320 | + va_list ap; |
1321 | + GType* types; |
1322 | + gint n; |
1323 | + |
1324 | + if (!tree_store) |
1325 | + return NULL; |
1326 | + |
1327 | + types = g_new (GType, n_columns); |
1328 | + |
1329 | + if (!types) |
1330 | + { |
1331 | + g_object_unref(tree_store); |
1332 | + return NULL; |
1333 | + } |
1334 | + |
1335 | + va_start(ap, n_columns); |
1336 | + for (n = 0; n < n_columns; n++) |
1337 | + { |
1338 | + types[n] = va_arg(ap, GType); |
1339 | + } |
1340 | + va_end(ap); |
1341 | + |
1342 | + gtk_tree_store_set_column_types (tree_store, |
1343 | + n_columns, |
1344 | + types); |
1345 | + |
1346 | + g_free (types); |
1347 | + return tree_store; |
1348 | +} |
1349 | + |
1350 | + |
1351 | +GtkTreeStore* |
1352 | +midori_bookmarks_tree_store_newv (gint n_columns, GType *types) |
1353 | +{ |
1354 | + GtkTreeStore* tree_store = GTK_TREE_STORE (g_object_new (MIDORI_BOOKMARKS_TREE_STORE_TYPE, NULL)); |
1355 | + |
1356 | + if (!tree_store) |
1357 | + return NULL; |
1358 | + |
1359 | + gtk_tree_store_set_column_types (tree_store, |
1360 | + n_columns, |
1361 | + types); |
1362 | + |
1363 | + return tree_store; |
1364 | +} |
1365 | + |
1366 | gboolean |
1367 | midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, |
1368 | KatzeItem* bookmark, |
1369 | @@ -36,6 +180,12 @@ |
1370 | midori_browser_open_bookmark (MidoriBrowser* browser, |
1371 | KatzeItem* item); |
1372 | |
1373 | +static void |
1374 | +midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
1375 | + GtkTreePath* path, |
1376 | + GtkTreeIter* iter, |
1377 | + MidoriBookmarks* bookmarks); |
1378 | + |
1379 | struct _MidoriBookmarks |
1380 | { |
1381 | GtkVBox parent_instance; |
1382 | @@ -49,6 +199,16 @@ |
1383 | |
1384 | gint filter_timeout; |
1385 | gchar* filter; |
1386 | + |
1387 | + struct _stock_pending_event |
1388 | + { |
1389 | + gint x; |
1390 | + gint y; |
1391 | + } *pending_event, |
1392 | + stock_pending_event; |
1393 | + |
1394 | + GHashTable* updated_items; |
1395 | + GList* added_paths; |
1396 | }; |
1397 | |
1398 | struct _MidoriBookmarksClass |
1399 | @@ -86,6 +246,49 @@ |
1400 | GParamSpec* pspec); |
1401 | |
1402 | static void |
1403 | +midori_bookmarks_update_cb (KatzeArray* array, |
1404 | + MidoriBookmarks* bookmarks); |
1405 | +static void |
1406 | +midori_bookmarks_add_item_cb (KatzeArray* array, |
1407 | + KatzeItem* item, |
1408 | + MidoriBookmarks* bookmarks); |
1409 | +static void |
1410 | +midori_bookmarks_update_item_cb (KatzeArray* array, |
1411 | + KatzeItem* item, |
1412 | + MidoriBookmarks* bookmarks); |
1413 | +static void |
1414 | +midori_bookmarks_remove_item_cb (KatzeArray* array, |
1415 | + KatzeItem* item, |
1416 | + MidoriBookmarks* bookmarks); |
1417 | + |
1418 | +static void |
1419 | +midori_bookmarks_row_added_cb (GtkTreeModel* model, |
1420 | + GtkTreePath* path, |
1421 | + GtkTreeIter* iter, |
1422 | + MidoriBookmarks* bookmarks); |
1423 | +static void |
1424 | +midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
1425 | + GtkTreePath* path, |
1426 | + GtkTreeIter* iter, |
1427 | + MidoriBookmarks* bookmarks); |
1428 | +static void |
1429 | +midori_bookmarks_row_deleted_cb (GtkTreeModel* model, |
1430 | + GtkTreePath* path, |
1431 | + MidoriBookmarks* bookmarks); |
1432 | + |
1433 | +static void |
1434 | +midori_bookmarks_update_item (MidoriBookmarks* bookmarks, KatzeItem *item); |
1435 | + |
1436 | +static void |
1437 | +midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks); |
1438 | + |
1439 | +static void |
1440 | +midori_bookmarks_idle_remove_item (MidoriBookmarks* bookmarks, KatzeItem *item); |
1441 | + |
1442 | +static gboolean |
1443 | +midori_bookmarks_idle (gpointer data); |
1444 | + |
1445 | +static void |
1446 | midori_bookmarks_class_init (MidoriBookmarksClass* class) |
1447 | { |
1448 | GObjectClass* gobject_class; |
1449 | @@ -133,7 +336,7 @@ |
1450 | gchar* parent_id; |
1451 | |
1452 | parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid); |
1453 | - if (!(root_array = midori_array_query (array, "*", "parentid = %q", parent_id))) |
1454 | + if (!(root_array = midori_array_query (array, "*", "parentid = %q", parent_id, "pos_pnel DESC,"))) |
1455 | { |
1456 | g_free (parent_id); |
1457 | return; |
1458 | @@ -186,20 +389,20 @@ |
1459 | |
1460 | if (keyword && *keyword) |
1461 | array = midori_array_query (bookmarks->array, |
1462 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword); |
1463 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword, NULL); |
1464 | else |
1465 | { |
1466 | if (parentid > 0) |
1467 | { |
1468 | gchar* parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid); |
1469 | array = midori_array_query (bookmarks->array, |
1470 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id); |
1471 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id, "pos_panel DESC,"); |
1472 | |
1473 | g_free (parent_id); |
1474 | } |
1475 | else |
1476 | array = midori_array_query (bookmarks->array, |
1477 | - "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL); |
1478 | + "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL, "pos_panel DESC,"); |
1479 | } |
1480 | return array ? array : katze_array_new (KATZE_TYPE_ITEM); |
1481 | } |
1482 | @@ -216,19 +419,39 @@ |
1483 | KatzeItem* item; |
1484 | GtkTreeIter child; |
1485 | |
1486 | + g_signal_handlers_block_by_func (model, |
1487 | + midori_bookmarks_row_changed_cb, |
1488 | + bookmarks); |
1489 | + |
1490 | array = midori_bookmarks_read_from_db (bookmarks, parentid, keyword); |
1491 | katze_bookmark_populate_tree_view (array, model, parent); |
1492 | + |
1493 | + g_signal_handlers_unblock_by_func (model, |
1494 | + midori_bookmarks_row_changed_cb, |
1495 | + bookmarks); |
1496 | + |
1497 | + |
1498 | /* Remove invisible dummy row */ |
1499 | last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent); |
1500 | if (!last) |
1501 | return; |
1502 | + |
1503 | + g_signal_handlers_block_by_func (model, |
1504 | + midori_bookmarks_row_deleted_cb, |
1505 | + bookmarks); |
1506 | + |
1507 | gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model), &child, parent, last - 1); |
1508 | gtk_tree_model_get (GTK_TREE_MODEL (model), &child, 0, &item, -1); |
1509 | if (KATZE_ITEM_IS_SEPARATOR (item)) |
1510 | gtk_tree_store_remove (model, &child); |
1511 | else |
1512 | g_object_unref (item); |
1513 | -} |
1514 | + |
1515 | + g_signal_handlers_unblock_by_func (model, |
1516 | + midori_bookmarks_row_deleted_cb, |
1517 | + bookmarks); |
1518 | + |
1519 | + } |
1520 | |
1521 | gint64 |
1522 | midori_bookmarks_insert_item_db (sqlite3* db, |
1523 | @@ -316,16 +539,237 @@ |
1524 | return seq; |
1525 | } |
1526 | |
1527 | +static gboolean |
1528 | +midori_bookmarks_reach_item_recurse (GtkTreeModel* model, |
1529 | + GtkTreeIter* iter, |
1530 | + gint64 id) |
1531 | +{ |
1532 | + do |
1533 | + { |
1534 | + GtkTreeIter child; |
1535 | + KatzeItem *item; |
1536 | + gint64 itemid = -1; |
1537 | + |
1538 | + gtk_tree_model_get (model, iter, 0, &item, -1); |
1539 | + |
1540 | + if (!KATZE_ITEM_IS_SEPARATOR(item)) |
1541 | + { |
1542 | + itemid = katze_item_get_meta_integer (item, "id"); |
1543 | + g_object_unref (item); |
1544 | + } |
1545 | + |
1546 | + if (id == itemid) |
1547 | + return TRUE; |
1548 | + |
1549 | + if (gtk_tree_model_iter_children (model, &child, iter)) |
1550 | + { |
1551 | + if (midori_bookmarks_reach_item_recurse (model, &child, id)) |
1552 | + { |
1553 | + *iter = child; |
1554 | + return TRUE; |
1555 | + } |
1556 | + } |
1557 | + } |
1558 | + while (gtk_tree_model_iter_next(model, iter)); |
1559 | + |
1560 | + return FALSE; |
1561 | +} |
1562 | + |
1563 | +static gboolean |
1564 | +midori_bookmarks_reach_item (GtkTreeModel* model, |
1565 | + GtkTreeIter* iter, |
1566 | + gint64 id) |
1567 | +{ |
1568 | + if (!gtk_tree_model_get_iter_first(model, iter)) |
1569 | + return FALSE; |
1570 | + |
1571 | + return midori_bookmarks_reach_item_recurse (model, iter, id); |
1572 | +} |
1573 | + |
1574 | +static void |
1575 | +midori_bookmarks_add_item_to_model(MidoriBookmarks* bookmarks, |
1576 | + GtkTreeModel* model, |
1577 | + GtkTreeIter* parent, |
1578 | + KatzeItem* item) |
1579 | +{ |
1580 | + GtkTreeStore* tree_store = GTK_TREE_STORE (model); |
1581 | + gint last; |
1582 | + GtkTreeIter child; |
1583 | + |
1584 | + if (KATZE_ITEM_IS_BOOKMARK (item)) |
1585 | + { |
1586 | + gint position = 0; |
1587 | + |
1588 | + /* skip the folders to be consistent with the db query order */ |
1589 | + if (gtk_tree_model_iter_children (model, &child, parent)) |
1590 | + while (gtk_tree_model_iter_has_child (model, &child)) |
1591 | + { |
1592 | + position++; |
1593 | + if (!gtk_tree_model_iter_next (model, &child)) |
1594 | + break; |
1595 | + } |
1596 | + |
1597 | + gchar* tooltip = g_markup_escape_text (katze_item_get_uri (item), -1); |
1598 | + |
1599 | + gtk_tree_store_insert_with_values (tree_store, NULL, parent, |
1600 | + position, |
1601 | + 0, item, 1, tooltip, -1); |
1602 | + g_free (tooltip); |
1603 | + } |
1604 | + else if (KATZE_ITEM_IS_FOLDER (item)) |
1605 | + { |
1606 | + GtkTreeIter root_iter; |
1607 | + |
1608 | + gtk_tree_store_insert_with_values (tree_store, &root_iter, parent, |
1609 | + 0, 0, item, -1); |
1610 | + |
1611 | + /* That's an invisible dummy, so we always have an expander */ |
1612 | + gtk_tree_store_insert_with_values (tree_store, NULL, &root_iter, |
1613 | + 0, |
1614 | + 0, NULL, -1); |
1615 | + } |
1616 | + |
1617 | + /* Remove invisible dummy row */ |
1618 | + last = gtk_tree_model_iter_n_children (model, parent); |
1619 | + if (!last) |
1620 | + return; |
1621 | + |
1622 | + g_signal_handlers_block_by_func (model, |
1623 | + midori_bookmarks_row_deleted_cb, |
1624 | + bookmarks); |
1625 | + |
1626 | + gtk_tree_model_iter_nth_child (model, &child, parent, last - 1); |
1627 | + gtk_tree_model_get (model, &child, 0, &item, -1); |
1628 | + if (KATZE_ITEM_IS_SEPARATOR (item)) |
1629 | + gtk_tree_store_remove (tree_store, &child); |
1630 | + else |
1631 | + g_object_unref (item); |
1632 | + |
1633 | + g_signal_handlers_unblock_by_func (model, |
1634 | + midori_bookmarks_row_deleted_cb, |
1635 | + bookmarks); |
1636 | +} |
1637 | + |
1638 | +static void |
1639 | +midori_bookmarks_update_item_in_model(MidoriBookmarks* bookmarks, |
1640 | + GtkTreeStore* model, |
1641 | + GtkTreeIter* iter, |
1642 | + KatzeItem* item) |
1643 | +{ |
1644 | + g_signal_handlers_block_by_func (model, |
1645 | + midori_bookmarks_row_changed_cb, |
1646 | + bookmarks); |
1647 | + |
1648 | + if (KATZE_ITEM_IS_BOOKMARK (item)) |
1649 | + { |
1650 | + gchar* tooltip = g_markup_escape_text (katze_item_get_uri (item), -1); |
1651 | + |
1652 | + gtk_tree_store_set(model, iter, |
1653 | + 0, item, 1, tooltip, -1); |
1654 | + |
1655 | + g_free (tooltip); |
1656 | + } |
1657 | + else |
1658 | + { |
1659 | + gtk_tree_store_set(model, iter, |
1660 | + 0, item, -1); |
1661 | + } |
1662 | + |
1663 | + g_signal_handlers_unblock_by_func (model, |
1664 | + midori_bookmarks_row_changed_cb, |
1665 | + bookmarks); |
1666 | + |
1667 | +} |
1668 | + |
1669 | static void |
1670 | midori_bookmarks_add_item_cb (KatzeArray* array, |
1671 | KatzeItem* item, |
1672 | MidoriBookmarks* bookmarks) |
1673 | { |
1674 | - GtkTreeModel* model; |
1675 | - model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
1676 | - gtk_tree_store_clear (GTK_TREE_STORE (model)); |
1677 | - midori_bookmarks_read_from_db_to_model (bookmarks, |
1678 | - GTK_TREE_STORE (model), NULL, 0, bookmarks->filter); |
1679 | + GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
1680 | + GtkTreeIter iter; |
1681 | + gint64 parentid; |
1682 | + |
1683 | + g_assert (KATZE_IS_ITEM (item)); |
1684 | + |
1685 | + parentid = katze_item_get_meta_integer (item, "parentid"); |
1686 | + |
1687 | + if (!parentid) |
1688 | + midori_bookmarks_add_item_to_model (bookmarks, model, NULL, item); |
1689 | + else if (midori_bookmarks_reach_item (model, &iter, parentid)) |
1690 | + { |
1691 | + GtkTreePath* path = gtk_tree_model_get_path(model, &iter); |
1692 | + gint n_children = gtk_tree_model_iter_n_children (model, &iter); |
1693 | + |
1694 | + if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path) |
1695 | + || !n_children) |
1696 | + midori_bookmarks_add_item_to_model (bookmarks, model, &iter, item); |
1697 | + |
1698 | + gtk_tree_path_free (path); |
1699 | + } |
1700 | +} |
1701 | + |
1702 | +static void |
1703 | +midori_bookmarks_update_item_cb (KatzeArray* array, |
1704 | + KatzeItem* item, |
1705 | + MidoriBookmarks* bookmarks) |
1706 | +{ |
1707 | + gint64 id = katze_item_get_meta_integer (item, "id"); |
1708 | + gint64 parentid = katze_item_get_meta_integer (item, "parentid"); |
1709 | + GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
1710 | + GtkTreeIter iter; |
1711 | + |
1712 | + g_assert (KATZE_IS_ITEM (item)); |
1713 | + |
1714 | + if (midori_bookmarks_reach_item (model, &iter, id)) |
1715 | + { |
1716 | + gint64 old_parentid = 0; |
1717 | + GtkTreeIter parent; |
1718 | + |
1719 | + if (gtk_tree_model_iter_parent (model, &parent, &iter)) |
1720 | + { |
1721 | + KatzeItem* old_parent; |
1722 | + |
1723 | + gtk_tree_model_get (model, &parent, 0, &old_parent, -1); |
1724 | + |
1725 | + old_parentid = katze_item_get_meta_integer (old_parent, "id"); |
1726 | + |
1727 | + g_object_unref (old_parent); |
1728 | + |
1729 | + if (parentid == old_parentid) |
1730 | + { |
1731 | + midori_bookmarks_update_item_in_model (bookmarks, GTK_TREE_STORE (model), &iter, item); |
1732 | + } |
1733 | + else |
1734 | + { |
1735 | + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter); |
1736 | + |
1737 | + if (!gtk_tree_model_iter_has_child (model, &parent)) |
1738 | + { |
1739 | + GtkTreePath* path = gtk_tree_model_get_path(model, &parent); |
1740 | + |
1741 | + if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path)) |
1742 | + gtk_tree_view_collapse_row (GTK_TREE_VIEW (bookmarks->treeview), path); |
1743 | + |
1744 | + gtk_tree_path_free (path); |
1745 | + } |
1746 | + |
1747 | + midori_bookmarks_add_item_cb (array, item, bookmarks); |
1748 | + } |
1749 | + } |
1750 | + else if (parentid == 0) |
1751 | + { |
1752 | + midori_bookmarks_update_item_in_model (bookmarks, GTK_TREE_STORE (model), &iter, item); |
1753 | + } |
1754 | + else |
1755 | + { |
1756 | + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter); |
1757 | + |
1758 | + midori_bookmarks_add_item_cb (array, item, bookmarks); |
1759 | + } |
1760 | + } |
1761 | + else |
1762 | + midori_bookmarks_add_item_cb (array, item, bookmarks); |
1763 | } |
1764 | |
1765 | static void |
1766 | @@ -333,22 +777,665 @@ |
1767 | KatzeItem* item, |
1768 | MidoriBookmarks* bookmarks) |
1769 | { |
1770 | + gint64 id = katze_item_get_meta_integer (item, "id"); |
1771 | GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
1772 | - gtk_tree_store_clear (GTK_TREE_STORE (model)); |
1773 | - midori_bookmarks_read_from_db_to_model (bookmarks, |
1774 | - GTK_TREE_STORE (model), NULL, 0, bookmarks->filter); |
1775 | + GtkTreeIter iter; |
1776 | + |
1777 | + g_assert (KATZE_IS_ITEM (item)); |
1778 | + |
1779 | + midori_bookmarks_idle_remove_item (bookmarks, item); |
1780 | + |
1781 | + if (midori_bookmarks_reach_item (model, &iter, id)) |
1782 | + { |
1783 | + GtkTreeIter parent; |
1784 | + |
1785 | + if (gtk_tree_model_iter_parent (model, &parent, &iter)) |
1786 | + { |
1787 | + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter); |
1788 | + |
1789 | + if (!gtk_tree_model_iter_has_child (model, &parent)) |
1790 | + { |
1791 | + GtkTreePath* path = gtk_tree_model_get_path(model, &parent); |
1792 | + |
1793 | + if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path)) |
1794 | + gtk_tree_view_collapse_row (GTK_TREE_VIEW (bookmarks->treeview), path); |
1795 | + |
1796 | + gtk_tree_path_free (path); |
1797 | + } |
1798 | + } |
1799 | + else |
1800 | + { |
1801 | + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter); |
1802 | + } |
1803 | + |
1804 | + midori_bookmarks_statusbar_update (bookmarks); |
1805 | + } |
1806 | } |
1807 | |
1808 | + |
1809 | static void |
1810 | midori_bookmarks_update_cb (KatzeArray* array, |
1811 | MidoriBookmarks* bookmarks) |
1812 | { |
1813 | GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
1814 | + |
1815 | gtk_tree_store_clear (GTK_TREE_STORE (model)); |
1816 | midori_bookmarks_read_from_db_to_model (bookmarks, |
1817 | GTK_TREE_STORE (model), NULL, 0, bookmarks->filter); |
1818 | -} |
1819 | - |
1820 | + |
1821 | + midori_bookmarks_statusbar_update (bookmarks); |
1822 | +} |
1823 | + |
1824 | +gboolean |
1825 | +midori_bookmarks_tree_set_row_drag_data (GtkSelectionData *selection_data, |
1826 | + GtkTreeModel *tree_model, |
1827 | + GList* rows) |
1828 | +{ |
1829 | + TreeRowData *trd; |
1830 | + gint len; |
1831 | + gint struct_size; |
1832 | + gint length; |
1833 | + gint i; |
1834 | + GString *data; |
1835 | + |
1836 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
1837 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE); |
1838 | + g_return_val_if_fail (rows != NULL, FALSE); |
1839 | + |
1840 | + data = g_string_new(""); |
1841 | + |
1842 | + length = g_list_length (rows); |
1843 | + for (i = 0; i < length; i++) |
1844 | + { |
1845 | + GtkTreePath *path = (GtkTreePath *)g_list_nth_data (rows, i); |
1846 | + gchar *path_str = gtk_tree_path_to_string (path); |
1847 | + |
1848 | + g_string_append (data, path_str); |
1849 | + if (i < length-1) |
1850 | + g_string_append_c (data, '\n'); |
1851 | + } |
1852 | + |
1853 | + len = data->len; |
1854 | + |
1855 | + /* the old allocate-end-of-struct-to-hold-string trick */ |
1856 | + struct_size = sizeof (TreeRowData) + len + 1 - |
1857 | + (sizeof (TreeRowData) - G_STRUCT_OFFSET (TreeRowData, path)); |
1858 | + |
1859 | + trd = g_malloc (struct_size); |
1860 | + |
1861 | + strcpy (trd->path, data->str); |
1862 | + |
1863 | + g_string_free (data, TRUE); |
1864 | + |
1865 | + trd->model = tree_model; |
1866 | + |
1867 | + gtk_selection_data_set (selection_data, |
1868 | + gdk_atom_intern_static_string ("GTK_TREE_MODEL_MULTI_ROWS"), |
1869 | + 8, /* bytes */ |
1870 | + (void*)trd, |
1871 | + struct_size); |
1872 | + |
1873 | + g_free (trd); |
1874 | + |
1875 | + return TRUE; |
1876 | +} |
1877 | + |
1878 | +static gboolean |
1879 | +midori_bookmarks_tree_store_drag_data_get (GtkTreeDragSource* drag_source, |
1880 | + GtkTreePath* source_path, |
1881 | + GtkSelectionData* selection_data) |
1882 | +{ |
1883 | + MidoriBookmarksTreeStore *tree_store; |
1884 | + gboolean status = FALSE; |
1885 | + |
1886 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
1887 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (drag_source), FALSE); |
1888 | + g_return_val_if_fail (source_path != NULL, FALSE); |
1889 | + |
1890 | + tree_store = MIDORI_BOOKMARKS_TREE_STORE(drag_source); |
1891 | + |
1892 | + if (tree_store->stock_got_rows) |
1893 | + { |
1894 | + g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free); |
1895 | + tree_store->stock_got_rows = NULL; |
1896 | + } |
1897 | + |
1898 | + if (gtk_selection_data_get_target (selection_data) == |
1899 | + gdk_atom_intern_static_string ("GTK_TREE_MODEL_MULTI_ROWS")) |
1900 | + { |
1901 | + GtkTreeModel *model; |
1902 | + GList* rows; |
1903 | + if (katze_tree_view_get_selected_rows ( |
1904 | + tree_store->source_view, &model, &rows)) |
1905 | + { |
1906 | + status = midori_bookmarks_tree_set_row_drag_data (selection_data, model, rows); |
1907 | + |
1908 | + tree_store->stock_got_rows = rows; |
1909 | + } |
1910 | + } |
1911 | + |
1912 | + return status; |
1913 | +} |
1914 | + |
1915 | +static void |
1916 | +update_path_list_for_insert (GList * rows, GtkTreePath* path) |
1917 | +{ |
1918 | + gint length = g_list_length (rows); |
1919 | + gint i; |
1920 | + |
1921 | + for (i = 0; i < length; i++ ) |
1922 | + { |
1923 | + GtkTreePath *src_path_r = (GtkTreePath *)g_list_nth_data (rows, i); |
1924 | + gint la = gtk_tree_path_get_depth (path); |
1925 | + gint lb = gtk_tree_path_get_depth (src_path_r); |
1926 | + gint *ia = gtk_tree_path_get_indices (path); |
1927 | + gint *ib = gtk_tree_path_get_indices (src_path_r); |
1928 | + gint j; |
1929 | + |
1930 | + if (la > lb) /* insert was donne in a deeper branch than source */ |
1931 | + continue; |
1932 | + |
1933 | + if (ia[la-1] > ib[la-1]) /* insert was donne after source */ |
1934 | + continue; |
1935 | + |
1936 | + for (j = 0; j < la; j++) |
1937 | + { |
1938 | + if (ia[j] != ib[j]) break; |
1939 | + } |
1940 | + |
1941 | + if (j < la-1) /* insert and source are not in the same branch */ |
1942 | + continue; |
1943 | + |
1944 | + /* source at depth level of insert must be incremented due to the insert */ |
1945 | + ib[la-1] += 1; |
1946 | + } |
1947 | +} |
1948 | + |
1949 | +static void |
1950 | +update_path_list_for_delete (GList * rows, GtkTreePath* path) |
1951 | +{ |
1952 | + gint length = g_list_length (rows); |
1953 | + gint i; |
1954 | + |
1955 | + for (i = 0; i < length; i++ ) |
1956 | + { |
1957 | + GtkTreePath *src_path_r = (GtkTreePath *)g_list_nth_data (rows, i); |
1958 | + gint la = gtk_tree_path_get_depth (path); |
1959 | + gint lb = gtk_tree_path_get_depth (src_path_r); |
1960 | + gint *ia = gtk_tree_path_get_indices (path); |
1961 | + gint *ib = gtk_tree_path_get_indices (src_path_r); |
1962 | + gint j; |
1963 | + |
1964 | + if (la > lb) /* removal was donne in a deeper branch than source */ |
1965 | + continue; |
1966 | + |
1967 | + if (ia[la-1] > ib[la-1]) /* removal was donne after source */ |
1968 | + continue; |
1969 | + |
1970 | + for (j = 0; j < la; j++) |
1971 | + { |
1972 | + if (ia[j] != ib[j]) break; |
1973 | + } |
1974 | + |
1975 | + if (j < la-1) /* removal and source are not in the same branch */ |
1976 | + continue; |
1977 | + |
1978 | + /* source at depth level of removal must be decremented due to the removal */ |
1979 | + ib[la-1] -= 1; |
1980 | + } |
1981 | +} |
1982 | + |
1983 | +static gboolean |
1984 | +midori_bookmarks_tree_store_drag_data_delete (GtkTreeDragSource* drag_source, |
1985 | + GtkTreePath* source_path) |
1986 | +{ |
1987 | + gboolean status = TRUE; |
1988 | + guint length; |
1989 | + guint i; |
1990 | + MidoriBookmarksTreeStore *tree_store = MIDORI_BOOKMARKS_TREE_STORE(drag_source); |
1991 | + GtkTreeModel* model = GTK_TREE_MODEL(drag_source); |
1992 | + |
1993 | + if (!tree_store->stock_got_rows) |
1994 | + return TRUE; |
1995 | + |
1996 | + length = g_list_length (tree_store->stock_got_rows); |
1997 | + for (i = 0; i < length; i++) |
1998 | + { |
1999 | + GtkTreePath *prev = (GtkTreePath *)g_list_nth_data (tree_store->stock_got_rows, i); |
2000 | + GtkTreeIter iter; |
2001 | + |
2002 | + if (gtk_tree_model_get_iter (model, &iter, prev)) |
2003 | + { |
2004 | + gint j; |
2005 | + gchar* src_path_str = gtk_tree_path_to_string (prev); |
2006 | + |
2007 | + /* remove item updating source paths */ |
2008 | + g_free(src_path_str); |
2009 | + |
2010 | + gtk_tree_store_remove (GTK_TREE_STORE (drag_source), &iter); |
2011 | + |
2012 | + update_path_list_for_delete (tree_store->stock_got_rows, prev); |
2013 | + } |
2014 | + else |
2015 | + status = FALSE; |
2016 | + } |
2017 | + |
2018 | + g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free); |
2019 | + tree_store->stock_got_rows = NULL; |
2020 | + |
2021 | + return status; |
2022 | +} |
2023 | + |
2024 | +static gboolean |
2025 | +midori_bookmarks_tree_store_get_rows_drag_data (GtkSelectionData *selection_data, |
2026 | + GtkTreeModel **tree_model, |
2027 | + GList **rows) |
2028 | +{ |
2029 | + GList *list; |
2030 | + TreeRowData *trd; |
2031 | + |
2032 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
2033 | + |
2034 | + if (tree_model) |
2035 | + *tree_model = NULL; |
2036 | + |
2037 | + if (rows) |
2038 | + *rows = NULL; |
2039 | + |
2040 | + if (gtk_selection_data_get_target (selection_data) != |
2041 | + gdk_atom_intern_static_string ("GTK_TREE_MODEL_MULTI_ROWS")) |
2042 | + return FALSE; |
2043 | + |
2044 | + if (gtk_selection_data_get_length (selection_data) < 0) |
2045 | + return FALSE; |
2046 | + |
2047 | + trd = (void*) gtk_selection_data_get_data (selection_data); |
2048 | + |
2049 | + if (tree_model) |
2050 | + *tree_model = trd->model; |
2051 | + |
2052 | + if (rows) |
2053 | + { |
2054 | + GList *list = NULL; |
2055 | + gchar *trd_path = g_strdup (trd->path); |
2056 | + gchar *path_str; |
2057 | + |
2058 | + path_str = strtok(trd_path, "\n"); |
2059 | + while (path_str && *path_str) |
2060 | + { |
2061 | + list = g_list_append (list, gtk_tree_path_new_from_string (path_str)); |
2062 | + path_str = strtok (NULL, "\n"); |
2063 | + } |
2064 | + |
2065 | + *rows = list; |
2066 | + g_free (trd_path); |
2067 | + } |
2068 | + |
2069 | + return TRUE; |
2070 | +} |
2071 | + |
2072 | +static gboolean |
2073 | +midori_bookmarks_tree_store_row_drop_possible (GtkTreeDragDest* drag_dest, |
2074 | + GtkTreePath* dest_path, |
2075 | + GtkSelectionData* selection_data) |
2076 | +{ |
2077 | + GtkTreeModel* dest_model = GTK_TREE_MODEL(drag_dest); |
2078 | + GtkTreeIter dest_parent; |
2079 | + GtkTreePath *parent = gtk_tree_path_copy (dest_path); |
2080 | + GtkTreeIter *dest_parent_p = NULL; |
2081 | + gboolean row_drop_possible = TRUE; |
2082 | + |
2083 | + if (gtk_tree_path_up (parent) && |
2084 | + gtk_tree_path_get_depth (parent) > 0) |
2085 | + { |
2086 | + gtk_tree_model_get_iter (dest_model, |
2087 | + &dest_parent, |
2088 | + parent); |
2089 | + dest_parent_p = &dest_parent; |
2090 | + } |
2091 | + gtk_tree_path_free (parent); |
2092 | + |
2093 | + if (dest_parent_p) |
2094 | + { |
2095 | + KatzeItem* item; |
2096 | + |
2097 | + gtk_tree_model_get (dest_model, dest_parent_p, 0, &item, -1); |
2098 | + |
2099 | + if (!KATZE_ITEM_IS_FOLDER(item)) |
2100 | + row_drop_possible = FALSE; |
2101 | + |
2102 | + if (item) |
2103 | + g_object_unref (item); |
2104 | + } |
2105 | + |
2106 | + if (!row_drop_possible) |
2107 | + return FALSE; |
2108 | + |
2109 | + if (gtk_selection_data_get_target (selection_data) == |
2110 | + gdk_atom_intern_static_string ("GTK_TREE_MODEL_MULTI_ROWS")) |
2111 | + { |
2112 | + GtkTreeModel *model; |
2113 | + GList* rows; |
2114 | + |
2115 | + if (midori_bookmarks_tree_store_get_rows_drag_data (selection_data, |
2116 | + &model, |
2117 | + &rows)) |
2118 | + { |
2119 | + /* TODO: */ |
2120 | + /* if (destination_is_in_folders (GTK_TREE_MODEL(drag_dest), dest_path) */ |
2121 | + /* && selection_contains_bookmarks (mode, rows)) */ |
2122 | + /* { */ |
2123 | + /* row_drop_possible = FALSE; */ |
2124 | + /* goto done; */ |
2125 | + /* } */ |
2126 | + /* if (destination_is_in_bookmarks (GTK_TREE_MODEL(drag_dest), dest_path) */ |
2127 | + /* && selection_contains_folders (mode, rows)) */ |
2128 | + /* { */ |
2129 | + /* row_drop_possible = FALSE; */ |
2130 | + /* goto done; */ |
2131 | + /* } */ |
2132 | + if (model == GTK_TREE_MODEL(drag_dest)) |
2133 | + { |
2134 | + gint length = g_list_length (rows); |
2135 | + gint i; |
2136 | + |
2137 | + for (i = 0; i < length; i++) |
2138 | + { |
2139 | + gint j; |
2140 | + GtkTreePath *src_path = (GtkTreePath *)g_list_nth_data (rows, i); |
2141 | + |
2142 | + /* Can't drop into ourself. */ |
2143 | + if (gtk_tree_path_is_ancestor (src_path, |
2144 | + dest_path)) |
2145 | + { |
2146 | + row_drop_possible = FALSE; |
2147 | + goto done; |
2148 | + } |
2149 | + update_path_list_for_insert (rows, dest_path); |
2150 | + } |
2151 | + } |
2152 | + done: |
2153 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2154 | + } |
2155 | + else |
2156 | + return FALSE; |
2157 | + } |
2158 | + else |
2159 | + return FALSE; |
2160 | + |
2161 | + return row_drop_possible; |
2162 | +} |
2163 | + |
2164 | +static void |
2165 | +copy_node_data (GtkTreeStore *src_store, |
2166 | + GtkTreeIter *src_iter, |
2167 | + GtkTreeStore *dest_store, |
2168 | + GtkTreeIter *dest_iter) |
2169 | +{ |
2170 | + gint i; |
2171 | + gint n_columns; |
2172 | + GtkTreeModel* src_model = GTK_TREE_MODEL (src_store); |
2173 | + |
2174 | + n_columns = gtk_tree_model_get_n_columns (src_model); |
2175 | + |
2176 | + for (i = 0; i < n_columns; i++) |
2177 | + { |
2178 | + void *item; |
2179 | + |
2180 | + gtk_tree_model_get (src_model, src_iter, i, &item, -1); |
2181 | + gtk_tree_store_set (dest_store, dest_iter, i, item, -1); |
2182 | + } |
2183 | +} |
2184 | + |
2185 | +static void |
2186 | +recursive_node_copy (GtkTreeStore *src_store, |
2187 | + GtkTreeIter *src_iter, |
2188 | + GtkTreeStore *dest_store, |
2189 | + GtkTreeIter *dest_iter) |
2190 | +{ |
2191 | + GtkTreeIter child; |
2192 | + GtkTreeModel *src_model = GTK_TREE_MODEL (src_store); |
2193 | + |
2194 | + copy_node_data (src_store, src_iter, dest_store, dest_iter); |
2195 | + |
2196 | + if (gtk_tree_model_iter_children (src_model, &child, src_iter)) |
2197 | + { |
2198 | + /* Need to create children and recurse. Note our |
2199 | + * dependence on persistent iterators here. |
2200 | + */ |
2201 | + do |
2202 | + { |
2203 | + GtkTreeIter copy; |
2204 | + |
2205 | + /* Gee, a really slow algorithm... ;-) FIXME */ |
2206 | + gtk_tree_store_append (dest_store, |
2207 | + ©, |
2208 | + dest_iter); |
2209 | + |
2210 | + recursive_node_copy (src_store, &child, dest_store, ©); |
2211 | + } |
2212 | + while (gtk_tree_model_iter_next (src_model, &child)); |
2213 | + } |
2214 | +} |
2215 | + |
2216 | +static gboolean |
2217 | +midori_bookmarks_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, |
2218 | + GtkTreePath *dest_path, |
2219 | + GtkSelectionData *selection_data) |
2220 | +{ |
2221 | + gboolean status = TRUE; |
2222 | + |
2223 | + g_return_val_if_fail (selection_data != NULL, FALSE); |
2224 | + g_return_val_if_fail (GTK_IS_TREE_MODEL (drag_dest), FALSE); |
2225 | + g_return_val_if_fail (dest_path != NULL, FALSE); |
2226 | + |
2227 | + if (gtk_selection_data_get_target (selection_data) == |
2228 | + gdk_atom_intern_static_string ("GTK_TREE_MODEL_MULTI_ROWS")) |
2229 | + { |
2230 | + GtkTreeStore *dest_store = GTK_TREE_STORE (drag_dest); |
2231 | + GtkTreeModel *dest_model = GTK_TREE_MODEL (drag_dest); |
2232 | + GtkTreeModel *src_model; |
2233 | + GList* rows; |
2234 | + |
2235 | + if (midori_bookmarks_tree_store_get_rows_drag_data (selection_data, |
2236 | + &src_model, |
2237 | + &rows)) |
2238 | + { |
2239 | + GtkTreeStore *src_store = GTK_TREE_STORE (src_model); |
2240 | + GtkTreePath *prev = gtk_tree_path_copy (dest_path); |
2241 | + |
2242 | + gint count = 0; |
2243 | + gint length = g_list_length (rows); |
2244 | + gint i; |
2245 | + |
2246 | + for (i = 0; i < length; i++) |
2247 | + { |
2248 | + gint j; |
2249 | + GtkTreeIter dest_iter; |
2250 | + GtkTreeIter src_iter; |
2251 | + GtkTreePath *src_path = (GtkTreePath *)g_list_nth_data (rows, i); |
2252 | + |
2253 | + if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path)) |
2254 | + continue; |
2255 | + |
2256 | + /* Get the path to insert _after_ (dest is the path to insert _before_) */ |
2257 | + if (i == 0) |
2258 | + { |
2259 | + if (!gtk_tree_path_prev (prev)) |
2260 | + { /* Get the parent, NULL if parent is the root */ |
2261 | + GtkTreeIter dest_parent; |
2262 | + GtkTreePath *parent = gtk_tree_path_copy (dest_path); |
2263 | + GtkTreeIter *dest_parent_p = NULL; |
2264 | + |
2265 | + if (gtk_tree_path_up (parent) && |
2266 | + gtk_tree_path_get_depth (parent) > 0) |
2267 | + { |
2268 | + gtk_tree_model_get_iter (dest_model, |
2269 | + &dest_parent, |
2270 | + parent); |
2271 | + dest_parent_p = &dest_parent; |
2272 | + } |
2273 | + gtk_tree_path_free (parent); |
2274 | + |
2275 | + gtk_tree_store_prepend (dest_store, &dest_iter, dest_parent_p); |
2276 | + } |
2277 | + else if (gtk_tree_model_get_iter (dest_model, &dest_iter, prev)) |
2278 | + { |
2279 | + GtkTreeIter tmp_iter = dest_iter; |
2280 | + |
2281 | + gtk_tree_store_insert_after (dest_store, &dest_iter, NULL, |
2282 | + &tmp_iter); |
2283 | + } |
2284 | + } |
2285 | + else if (gtk_tree_model_get_iter (dest_model, &dest_iter, prev)) |
2286 | + { |
2287 | + GtkTreeIter tmp_iter = dest_iter; |
2288 | + |
2289 | + gtk_tree_store_insert_after (dest_store, &dest_iter, NULL, |
2290 | + &tmp_iter); |
2291 | + } |
2292 | + |
2293 | + gtk_tree_path_free (prev); |
2294 | + |
2295 | + recursive_node_copy (src_store, &src_iter, dest_store, &dest_iter); |
2296 | + count++; |
2297 | + |
2298 | + prev = gtk_tree_model_get_path (dest_model, &dest_iter); |
2299 | + |
2300 | + if (src_store != dest_store) |
2301 | + continue; |
2302 | + |
2303 | + update_path_list_for_insert (rows, prev); |
2304 | + } |
2305 | + |
2306 | + gtk_tree_path_free (prev); |
2307 | + |
2308 | + g_assert (count == length); |
2309 | + |
2310 | + if (src_store == dest_store) |
2311 | + { |
2312 | + MidoriBookmarksTreeStore *tree_store = MIDORI_BOOKMARKS_TREE_STORE(src_store); |
2313 | + |
2314 | + g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free); |
2315 | + tree_store->stock_got_rows = rows; |
2316 | + } |
2317 | + else |
2318 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2319 | + } |
2320 | + } |
2321 | + |
2322 | + return status; |
2323 | +} |
2324 | + |
2325 | +static void |
2326 | +midori_bookmarks_set_item_positon (GtkTreeModel* model, |
2327 | + GtkTreeIter* iter, |
2328 | + gint64 parentid, |
2329 | + MidoriBookmarks* bookmarks) |
2330 | +{ |
2331 | + KatzeItem* item; |
2332 | + gint position = 0; |
2333 | + GtkTreeIter next = *iter; |
2334 | + |
2335 | + do { |
2336 | + gboolean update = FALSE; |
2337 | + gtk_tree_model_get (model, &next, 0, &item, -1); |
2338 | + |
2339 | + if (!KATZE_IS_ITEM (item)) |
2340 | + continue; |
2341 | + |
2342 | + if (position != katze_item_get_meta_integer (item, "pos_panel")) |
2343 | + { |
2344 | + katze_item_set_meta_integer (item, "pos_panel", position); |
2345 | + update = TRUE; |
2346 | + } |
2347 | + if (parentid != katze_item_get_meta_integer (item, "parentid")) |
2348 | + { |
2349 | + katze_item_set_meta_integer (item, "parentid", parentid); |
2350 | + update = TRUE; |
2351 | + } |
2352 | + |
2353 | + if (update) |
2354 | + midori_bookmarks_update_item (bookmarks, item); |
2355 | + |
2356 | + position++; |
2357 | + |
2358 | + g_object_unref (item); |
2359 | + } |
2360 | + while (gtk_tree_model_iter_next (model, &next)); |
2361 | +} |
2362 | + |
2363 | +static void |
2364 | +midori_bookmarks_row_added_cb (GtkTreeModel* model, |
2365 | + GtkTreePath* path, |
2366 | + GtkTreeIter* iter, |
2367 | + MidoriBookmarks* bookmarks) |
2368 | +{ |
2369 | + if (!g_hash_table_size (bookmarks->updated_items) |
2370 | + || (!g_list_length (bookmarks->added_paths))) |
2371 | + g_idle_add (midori_bookmarks_idle, bookmarks); |
2372 | + |
2373 | + update_path_list_for_insert (bookmarks->added_paths, path); |
2374 | + |
2375 | + bookmarks->added_paths = g_list_append (bookmarks->added_paths, gtk_tree_path_copy (path)); |
2376 | +} |
2377 | + |
2378 | +static void |
2379 | +update_items_for_parent (GtkTreeModel* model, |
2380 | + GtkTreePath* path, |
2381 | + MidoriBookmarks* bookmarks) |
2382 | +{ |
2383 | + if ((gtk_tree_path_get_depth (path) > 1) |
2384 | + && gtk_tree_path_up (path)) |
2385 | + { |
2386 | + KatzeItem *item; |
2387 | + GtkTreeIter parent; |
2388 | + GtkTreeIter local_iter; |
2389 | + gint64 id; |
2390 | + |
2391 | + if (!gtk_tree_model_get_iter (model, &parent, path)) |
2392 | + return; |
2393 | + |
2394 | + gtk_tree_model_get (model, &parent, 0, &item, -1); |
2395 | + |
2396 | + g_assert (KATZE_ITEM_IS_FOLDER (item)); |
2397 | + |
2398 | + id = katze_item_get_meta_integer (item, "id"); |
2399 | + |
2400 | + g_object_unref (item); |
2401 | + |
2402 | + if (gtk_tree_model_iter_children (model, &local_iter, &parent)) |
2403 | + midori_bookmarks_set_item_positon(model, &local_iter, id, bookmarks); |
2404 | + } |
2405 | + else |
2406 | + { |
2407 | + GtkTreeIter local_iter; |
2408 | + if (gtk_tree_model_get_iter_first (model, &local_iter)) |
2409 | + midori_bookmarks_set_item_positon(model, &local_iter, 0, bookmarks); |
2410 | + } |
2411 | +} |
2412 | + |
2413 | +static void |
2414 | +midori_bookmarks_row_deleted_cb (GtkTreeModel* model, |
2415 | + GtkTreePath* path, |
2416 | + MidoriBookmarks* bookmarks) |
2417 | +{ |
2418 | + GList* found; |
2419 | + |
2420 | + if (!g_hash_table_size (bookmarks->updated_items) |
2421 | + || (!g_list_length (bookmarks->added_paths))) |
2422 | + g_idle_add (midori_bookmarks_idle, bookmarks); |
2423 | + |
2424 | + while (found = g_list_find_custom (bookmarks->added_paths, |
2425 | + path, (GCompareFunc)gtk_tree_path_compare)) |
2426 | + { |
2427 | + bookmarks->added_paths = g_list_remove(bookmarks->added_paths, found->data); |
2428 | + gtk_tree_path_free ((GtkTreePath*)found->data); |
2429 | + } |
2430 | + |
2431 | + update_path_list_for_delete (bookmarks->added_paths, path); |
2432 | + update_items_for_parent (model, path, bookmarks); |
2433 | +} |
2434 | |
2435 | static void |
2436 | midori_bookmarks_row_changed_cb (GtkTreeModel* model, |
2437 | @@ -356,44 +1443,59 @@ |
2438 | GtkTreeIter* iter, |
2439 | MidoriBookmarks* bookmarks) |
2440 | { |
2441 | - KatzeItem* item; |
2442 | - GtkTreeIter parent; |
2443 | - KatzeItem* new_parent = NULL; |
2444 | - gint64 parentid; |
2445 | - |
2446 | - gtk_tree_model_get (model, iter, 0, &item, -1); |
2447 | - |
2448 | - if (gtk_tree_model_iter_parent (model, &parent, iter)) |
2449 | - { |
2450 | - gtk_tree_model_get (model, &parent, 0, &new_parent, -1); |
2451 | - |
2452 | - /* Bookmarks must not be moved into non-folder items */ |
2453 | - if (!KATZE_ITEM_IS_FOLDER (new_parent)) |
2454 | - parentid = 0; |
2455 | - else |
2456 | - parentid = katze_item_get_meta_integer (new_parent, "id"); |
2457 | - } |
2458 | - else |
2459 | - parentid = 0; |
2460 | - |
2461 | - katze_array_remove_item (bookmarks->array, item); |
2462 | - katze_item_set_meta_integer (item, "parentid", parentid); |
2463 | - katze_array_add_item (bookmarks->array, item); |
2464 | - |
2465 | - g_object_unref (item); |
2466 | - if (new_parent) |
2467 | - g_object_unref (new_parent); |
2468 | + update_items_for_parent (model, path, bookmarks); |
2469 | } |
2470 | |
2471 | static void |
2472 | -midori_bookmarks_add_clicked_cb (GtkWidget* toolitem) |
2473 | +midori_bookmarks_add_clicked_cb (GtkWidget* toolitem, |
2474 | + MidoriBookmarks* bookmarks) |
2475 | { |
2476 | MidoriBrowser* browser = midori_browser_get_for_widget (toolitem); |
2477 | - /* FIXME: Take selected folder into account */ |
2478 | + GtkTreeView* treeview = GTK_TREE_VIEW (bookmarks->treeview); |
2479 | + GtkTreeModel* model; |
2480 | + GtkTreeIter iter; |
2481 | + KatzeItem* parent = NULL; |
2482 | + |
2483 | + if (katze_tree_view_get_selected_iter (treeview, |
2484 | + &model, &iter)) |
2485 | + { |
2486 | + gboolean done = FALSE; |
2487 | + while (!done) |
2488 | + { |
2489 | + gtk_tree_model_get (model, &iter, 0, &parent, -1); |
2490 | + |
2491 | + if (KATZE_ITEM_IS_FOLDER (parent)) |
2492 | + { |
2493 | + GtkTreePath* path = gtk_tree_model_get_path(model, &iter); |
2494 | + |
2495 | + if (!gtk_tree_view_row_expanded (treeview, path)) |
2496 | + gtk_tree_view_expand_row (treeview, path, FALSE); |
2497 | + |
2498 | + gtk_tree_path_free (path); |
2499 | + done = TRUE; |
2500 | + } |
2501 | + else |
2502 | + { |
2503 | + GtkTreeIter child = iter; |
2504 | + |
2505 | + if (parent) g_object_unref (parent); |
2506 | + parent = NULL; |
2507 | + |
2508 | + if (!gtk_tree_model_iter_parent (model, &iter, &child)) |
2509 | + { |
2510 | + done = TRUE; |
2511 | + } |
2512 | + } |
2513 | + } |
2514 | + } |
2515 | + |
2516 | if (g_str_equal (gtk_widget_get_name (toolitem), "BookmarkFolderAdd")) |
2517 | - midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, TRUE, toolitem); |
2518 | + midori_browser_edit_bookmark_dialog_new (browser, parent, TRUE, TRUE, toolitem); |
2519 | else |
2520 | - midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, FALSE, toolitem); |
2521 | + midori_browser_edit_bookmark_dialog_new (browser, parent, TRUE, FALSE, toolitem); |
2522 | + |
2523 | + if (parent) |
2524 | + g_object_unref (parent); |
2525 | } |
2526 | |
2527 | static void |
2528 | @@ -408,24 +1510,15 @@ |
2529 | { |
2530 | KatzeItem* item; |
2531 | MidoriBrowser* browser; |
2532 | - gint64 parentid; |
2533 | |
2534 | gtk_tree_model_get (model, &iter, 0, &item, -1); |
2535 | |
2536 | g_assert (!KATZE_ITEM_IS_SEPARATOR (item)); |
2537 | |
2538 | browser = midori_browser_get_for_widget (bookmarks->treeview); |
2539 | - parentid = katze_item_get_meta_integer (item, "parentid"); |
2540 | midori_browser_edit_bookmark_dialog_new ( |
2541 | browser, item, FALSE, KATZE_ITEM_IS_FOLDER (item), NULL); |
2542 | |
2543 | - if (katze_item_get_meta_integer (item, "parentid") != parentid) |
2544 | - { |
2545 | - gtk_tree_store_clear (GTK_TREE_STORE (model)); |
2546 | - midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), |
2547 | - NULL, 0, NULL); |
2548 | - } |
2549 | - |
2550 | g_object_unref (item); |
2551 | } |
2552 | } |
2553 | @@ -433,12 +1526,226 @@ |
2554 | static void |
2555 | midori_bookmarks_toolbar_update (MidoriBookmarks *bookmarks) |
2556 | { |
2557 | - gboolean selected; |
2558 | + gint selected; |
2559 | |
2560 | - selected = katze_tree_view_get_selected_iter ( |
2561 | + selected = katze_tree_view_get_selected_rows ( |
2562 | GTK_TREE_VIEW (bookmarks->treeview), NULL, NULL); |
2563 | - gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->delete), selected); |
2564 | - gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->edit), selected); |
2565 | + gtk_widget_set_sensitive ( |
2566 | + GTK_WIDGET (bookmarks->delete), (selected > 0 ? TRUE : FALSE)); |
2567 | + gtk_widget_set_sensitive ( |
2568 | + GTK_WIDGET (bookmarks->edit), (selected == 1 ? TRUE : FALSE)); |
2569 | +} |
2570 | + |
2571 | +static void |
2572 | +midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks) |
2573 | +{ |
2574 | + gchar* text = NULL; |
2575 | + GtkTreeModel* model; |
2576 | + GList *rows; |
2577 | + gint selected; |
2578 | + |
2579 | + selected = katze_tree_view_get_selected_rows ( |
2580 | + GTK_TREE_VIEW (bookmarks->treeview), &model, &rows); |
2581 | + |
2582 | + if (selected == 1) |
2583 | + { |
2584 | + GtkTreePath* path = (GtkTreePath *)g_list_nth_data (rows, 0); |
2585 | + GtkTreeIter iter; |
2586 | + KatzeItem* item; |
2587 | + const gchar* name; |
2588 | + |
2589 | + if (!gtk_tree_model_get_iter (model, &iter, path)) |
2590 | + return; |
2591 | + |
2592 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
2593 | + |
2594 | + g_assert (!KATZE_ITEM_IS_SEPARATOR (item)); |
2595 | + |
2596 | + name = katze_item_get_name (item); |
2597 | + |
2598 | + if (KATZE_ITEM_IS_FOLDER (item)) |
2599 | + { |
2600 | + gint child_folders_count = midori_array_count_recursive( |
2601 | + bookmarks->array, |
2602 | + "uri = ''", |
2603 | + NULL, |
2604 | + item, |
2605 | + FALSE); |
2606 | + gint child_bookmarks_count = midori_array_count_recursive( |
2607 | + bookmarks->array, |
2608 | + "uri <> ''", |
2609 | + NULL, |
2610 | + item, |
2611 | + FALSE); |
2612 | + |
2613 | + if (!child_bookmarks_count && !child_folders_count) |
2614 | + text = g_strdup_printf( |
2615 | + _("%s : empty folder"), |
2616 | + name); |
2617 | + else if (!child_bookmarks_count && (child_folders_count == 1)) |
2618 | + text = g_strdup_printf( |
2619 | + _("%s : folder, one subfolder and no bookmark"), |
2620 | + name); |
2621 | + else if (!child_bookmarks_count && child_folders_count) |
2622 | + text = g_strdup_printf( |
2623 | + _("%s : folder, %d subfolders and no bookmark"), |
2624 | + name, child_folders_count); |
2625 | + else if ((child_bookmarks_count == 1) && !child_folders_count) |
2626 | + text = g_strdup_printf( |
2627 | + _("%s : folder, one bookmark"), |
2628 | + name); |
2629 | + else if ((child_bookmarks_count == 1) && (child_folders_count == 1)) |
2630 | + text = g_strdup_printf( |
2631 | + _("%s : folder, one bookmark and one subfolder"), |
2632 | + name); |
2633 | + else if ((child_bookmarks_count == 1) && child_folders_count) |
2634 | + text = g_strdup_printf( |
2635 | + _("%s : folder, one bookmark and %d subfolders"), |
2636 | + name, child_folders_count); |
2637 | + else if (child_bookmarks_count && !child_folders_count) |
2638 | + text = g_strdup_printf( |
2639 | + _("%s : folder, %d bookmarks"), |
2640 | + name, child_bookmarks_count); |
2641 | + else if (child_bookmarks_count && (child_folders_count == 1)) |
2642 | + text = g_strdup_printf( |
2643 | + _("%s : folder, %d bookmarks and one subfolder"), |
2644 | + name, child_bookmarks_count); |
2645 | + else if (child_bookmarks_count && child_folders_count) |
2646 | + text = g_strdup_printf( |
2647 | + _("%s : folder, %d bookmarks and %d subfolders"), |
2648 | + name, child_bookmarks_count, child_folders_count); |
2649 | + } |
2650 | + else if (KATZE_ITEM_IS_BOOKMARK (item)) |
2651 | + { |
2652 | + const gchar* uri = katze_item_get_uri (item); |
2653 | + |
2654 | + if (katze_item_get_meta_boolean (item, "app")) |
2655 | + text = g_strdup_printf (_("%s : web application bookmark to : %s"), name, uri); |
2656 | + else |
2657 | + text = g_strdup_printf (_("%s : bookmark to : %s"), name, uri); |
2658 | + } |
2659 | + |
2660 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2661 | + } |
2662 | + else if (selected > 1) |
2663 | + { |
2664 | + gint i; |
2665 | + gint selected_folders_count = 0; |
2666 | + gint selected_bookmarks_count = 0; |
2667 | + |
2668 | + for (i = 0 ; i < selected ; i++) |
2669 | + { |
2670 | + GtkTreeIter iter; |
2671 | + KatzeItem* item; |
2672 | + |
2673 | + g_return_if_fail (gtk_tree_model_get_iter ( |
2674 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, i))); |
2675 | + |
2676 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
2677 | + |
2678 | + g_assert (!KATZE_ITEM_IS_SEPARATOR (item)); |
2679 | + |
2680 | + if (KATZE_ITEM_IS_FOLDER (item)) |
2681 | + { |
2682 | + selected_folders_count++; |
2683 | + } |
2684 | + else |
2685 | + { |
2686 | + selected_bookmarks_count++; |
2687 | + } |
2688 | + } |
2689 | + |
2690 | + if (!selected_bookmarks_count && !selected_folders_count) |
2691 | + g_assert_not_reached (); |
2692 | + else if (!selected_bookmarks_count && (selected_folders_count == 1)) |
2693 | + text = g_strdup_printf( |
2694 | + _("one folder and no bookmark selected")); |
2695 | + else if (!selected_bookmarks_count && selected_folders_count) |
2696 | + text = g_strdup_printf( |
2697 | + _("%d folders and no bookmark selected"), |
2698 | + selected_folders_count); |
2699 | + else if ((selected_bookmarks_count == 1) && !selected_folders_count) |
2700 | + text = g_strdup_printf( |
2701 | + _("one bookmark selected")); |
2702 | + else if ((selected_bookmarks_count == 1) && (selected_folders_count == 1)) |
2703 | + text = g_strdup_printf( |
2704 | + _("one bookmark and one folder selected")); |
2705 | + else if ((selected_bookmarks_count == 1) && selected_folders_count) |
2706 | + text = g_strdup_printf( |
2707 | + _("one bookmark and %d folders selected"), |
2708 | + selected_folders_count); |
2709 | + else if (selected_bookmarks_count && !selected_folders_count) |
2710 | + text = g_strdup_printf( |
2711 | + _("%d bookmarks selected"), |
2712 | + selected_bookmarks_count); |
2713 | + else if (selected_bookmarks_count && (selected_folders_count == 1)) |
2714 | + text = g_strdup_printf( |
2715 | + _("%d bookmarks and one folder selected"), |
2716 | + selected_bookmarks_count); |
2717 | + else if (selected_bookmarks_count && selected_folders_count) |
2718 | + text = g_strdup_printf( |
2719 | + _("%d bookmarks and %d folders selected"), |
2720 | + selected_bookmarks_count, selected_folders_count); |
2721 | + |
2722 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2723 | + } |
2724 | + else |
2725 | + { |
2726 | + gint child_folders_count = midori_array_count_recursive( |
2727 | + bookmarks->array, |
2728 | + "uri = ''", |
2729 | + NULL, |
2730 | + NULL, |
2731 | + FALSE); |
2732 | + gint child_bookmarks_count = midori_array_count_recursive( |
2733 | + bookmarks->array, |
2734 | + "uri <> ''", |
2735 | + NULL, |
2736 | + NULL, |
2737 | + FALSE); |
2738 | + |
2739 | + if (!child_bookmarks_count && !child_folders_count) |
2740 | + text = g_strdup_printf( |
2741 | + _("Bookmarks : empty")); |
2742 | + else if (!child_bookmarks_count && (child_folders_count == 1)) |
2743 | + text = g_strdup_printf( |
2744 | + _("Bookmarks : one folder and no bookmark")); |
2745 | + else if (!child_bookmarks_count && child_folders_count) |
2746 | + text = g_strdup_printf( |
2747 | + _("Bookmarks : %d folders and no bookmark"), |
2748 | + child_folders_count); |
2749 | + else if ((child_bookmarks_count == 1) && !child_folders_count) |
2750 | + text = g_strdup_printf( |
2751 | + _("Bookmarks : one bookmark")); |
2752 | + else if ((child_bookmarks_count == 1) && (child_folders_count == 1)) |
2753 | + text = g_strdup_printf( |
2754 | + _("Bookmarks : one bookmark and one folder")); |
2755 | + else if ((child_bookmarks_count == 1) && child_folders_count) |
2756 | + text = g_strdup_printf( |
2757 | + _("Bookmarks : one bookmark and %d folders"), |
2758 | + child_folders_count); |
2759 | + else if (child_bookmarks_count && !child_folders_count) |
2760 | + text = g_strdup_printf( |
2761 | + _("Bookmarks : %d bookmarks"), |
2762 | + child_bookmarks_count); |
2763 | + else if (child_bookmarks_count && (child_folders_count == 1)) |
2764 | + text = g_strdup_printf( |
2765 | + _("Bookmarks : %d bookmarks and one folder"), |
2766 | + child_bookmarks_count); |
2767 | + else if (child_bookmarks_count && child_folders_count) |
2768 | + text = g_strdup_printf( |
2769 | + _("Bookmarks : %d bookmarks and %d folders"), |
2770 | + child_bookmarks_count, child_folders_count); |
2771 | + } |
2772 | + |
2773 | + if (text) |
2774 | + { |
2775 | + MidoriBrowser* browser = midori_browser_get_for_widget (bookmarks->treeview); |
2776 | + |
2777 | + g_object_set (browser, "statusbar-text", text, NULL); |
2778 | + |
2779 | + g_free(text); |
2780 | + } |
2781 | } |
2782 | |
2783 | gboolean |
2784 | @@ -458,7 +1765,8 @@ |
2785 | |
2786 | sqlcmd = sqlite3_mprintf ( |
2787 | "UPDATE bookmarks SET " |
2788 | - "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d " |
2789 | + "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d, " |
2790 | + "pos_panel=%" G_GINT64_FORMAT ", pos_bar=%" G_GINT64_FORMAT " " |
2791 | "WHERE id = %" G_GINT64_FORMAT ";", |
2792 | parentid, |
2793 | katze_item_get_name (item), |
2794 | @@ -466,8 +1774,14 @@ |
2795 | katze_str_non_null (katze_item_get_meta_string (item, "desc")), |
2796 | katze_item_get_meta_boolean (item, "toolbar"), |
2797 | katze_item_get_meta_boolean (item, "app"), |
2798 | + katze_item_get_meta_integer (item, "pos_panel"), |
2799 | + katze_item_get_meta_integer (item, "pos_bar"), |
2800 | katze_item_get_meta_integer (item, "id")); |
2801 | |
2802 | + /* g_printf("update: %d -> %d\n", */ |
2803 | + /* (gint)katze_item_get_meta_integer (item, "id"), */ |
2804 | + /* (gint)katze_item_get_meta_integer (item, "pos_panel")); */ |
2805 | + |
2806 | updated = TRUE; |
2807 | if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK) |
2808 | { |
2809 | @@ -487,23 +1801,38 @@ |
2810 | MidoriBookmarks* bookmarks) |
2811 | { |
2812 | GtkTreeModel* model; |
2813 | - GtkTreeIter iter; |
2814 | + GList* rows; |
2815 | + gint length; |
2816 | |
2817 | - if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview), |
2818 | - &model, &iter)) |
2819 | + length = katze_tree_view_get_selected_rows(GTK_TREE_VIEW (bookmarks->treeview), |
2820 | + &model, &rows); |
2821 | + while (length) |
2822 | { |
2823 | - KatzeItem* item; |
2824 | - |
2825 | - gtk_tree_model_get (model, &iter, 0, &item, -1); |
2826 | - |
2827 | - /* Manually remove the iter and block clearing the treeview */ |
2828 | - gtk_tree_store_remove (GTK_TREE_STORE (model), &iter); |
2829 | - g_signal_handlers_block_by_func (bookmarks->array, |
2830 | - midori_bookmarks_remove_item_cb, bookmarks); |
2831 | - katze_array_remove_item (bookmarks->array, item); |
2832 | - g_signal_handlers_unblock_by_func (bookmarks->array, |
2833 | - midori_bookmarks_remove_item_cb, bookmarks); |
2834 | - g_object_unref (item); |
2835 | + gint new_length; |
2836 | + GtkTreeIter iter; |
2837 | + |
2838 | + if (gtk_tree_model_get_iter ( |
2839 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, 0))) |
2840 | + { |
2841 | + KatzeItem* item; |
2842 | + |
2843 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
2844 | + |
2845 | + if (KATZE_IS_ITEM(item)) |
2846 | + { |
2847 | + katze_array_remove_item (bookmarks->array, item); |
2848 | + } |
2849 | + |
2850 | + g_object_unref (item); |
2851 | + } |
2852 | + |
2853 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
2854 | + |
2855 | + new_length = katze_tree_view_get_selected_rows(GTK_TREE_VIEW (bookmarks->treeview), |
2856 | + &model, &rows); |
2857 | + |
2858 | + /* avoid infinite loop due to delete failure */ |
2859 | + length = (new_length == length) ? 0 : new_length; |
2860 | } |
2861 | } |
2862 | |
2863 | @@ -547,6 +1876,7 @@ |
2864 | gtk_widget_show (GTK_WIDGET (toolitem)); |
2865 | bookmarks->delete = GTK_WIDGET (toolitem); |
2866 | midori_bookmarks_toolbar_update (bookmarks); |
2867 | + midori_bookmarks_statusbar_update (bookmarks); |
2868 | toolitem = gtk_separator_tool_item_new (); |
2869 | gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE); |
2870 | gtk_tool_item_set_expand (toolitem, TRUE); |
2871 | @@ -599,10 +1929,18 @@ |
2872 | midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), NULL, 0, NULL); |
2873 | g_signal_connect_after (bookmarks->array, "add-item", |
2874 | G_CALLBACK (midori_bookmarks_add_item_cb), bookmarks); |
2875 | + g_signal_connect_after (bookmarks->array, "update-item", |
2876 | + G_CALLBACK (midori_bookmarks_update_item_cb), bookmarks); |
2877 | g_signal_connect (bookmarks->array, "remove-item", |
2878 | G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks); |
2879 | g_signal_connect (bookmarks->array, "update", |
2880 | G_CALLBACK (midori_bookmarks_update_cb), bookmarks); |
2881 | + g_signal_connect_after (model, "row-inserted", |
2882 | + G_CALLBACK (midori_bookmarks_row_added_cb), |
2883 | + bookmarks); |
2884 | + g_signal_connect_after (model, "row-deleted", |
2885 | + G_CALLBACK (midori_bookmarks_row_deleted_cb), |
2886 | + bookmarks); |
2887 | g_signal_connect_after (model, "row-changed", |
2888 | G_CALLBACK (midori_bookmarks_row_changed_cb), |
2889 | bookmarks); |
2890 | @@ -745,7 +2083,10 @@ |
2891 | else if (!KATZE_ITEM_IS_FOLDER (item) && strcmp (stock_id, GTK_STOCK_DELETE)) |
2892 | gtk_widget_set_sensitive (menuitem, uri != NULL); |
2893 | g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item); |
2894 | - g_signal_connect (menuitem, "activate", G_CALLBACK (callback), bookmarks); |
2895 | + if (callback) |
2896 | + g_signal_connect (menuitem, "activate", G_CALLBACK (callback), bookmarks); |
2897 | + else |
2898 | + gtk_widget_set_sensitive (menuitem, FALSE); |
2899 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
2900 | gtk_widget_show (menuitem); |
2901 | } |
2902 | @@ -766,39 +2107,125 @@ |
2903 | } |
2904 | } |
2905 | |
2906 | +static GtkWidget* |
2907 | +midori_bookmarks_open_bookmark_in_tab (KatzeItem *item, |
2908 | + MidoriBrowser* browser) |
2909 | +{ |
2910 | + const gchar* uri = katze_item_get_uri (item); |
2911 | + |
2912 | + if (!uri || !*uri) |
2913 | + return NULL; |
2914 | + |
2915 | + return midori_browser_add_item (browser, item); |
2916 | +} |
2917 | + |
2918 | +static GtkWidget* |
2919 | +midori_bookmarks_open_folder_in_tab (gint64 parentid, |
2920 | + MidoriBookmarks* bookmarks, |
2921 | + MidoriBrowser* browser) |
2922 | +{ |
2923 | + GtkWidget* last_view = NULL; |
2924 | + KatzeArray* array; |
2925 | + |
2926 | + array = midori_bookmarks_read_from_db (bookmarks, parentid, NULL); |
2927 | + |
2928 | + if (KATZE_IS_ARRAY (array)) |
2929 | + { |
2930 | + KatzeItem* child; |
2931 | + |
2932 | + KATZE_ARRAY_FOREACH_ITEM (child, array) |
2933 | + { |
2934 | + GtkWidget* view = midori_bookmarks_open_bookmark_in_tab (child, browser); |
2935 | + if (view) |
2936 | + last_view = view; |
2937 | + } |
2938 | + } |
2939 | + |
2940 | + return last_view; |
2941 | +} |
2942 | + |
2943 | + |
2944 | +static void |
2945 | +midori_bookmarks_run_web_application_cb (GtkWidget* menuitem, |
2946 | + MidoriBookmarks* bookmarks) |
2947 | +{ |
2948 | + KatzeItem* item; |
2949 | + const gchar* uri; |
2950 | + |
2951 | + item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem"); |
2952 | + |
2953 | + if ((uri = katze_item_get_uri (item)) && *uri) |
2954 | + { |
2955 | + gchar* uri_fixed = sokoke_magic_uri (uri, TRUE, FALSE); |
2956 | + if (!uri_fixed) |
2957 | + uri_fixed = g_strdup (uri); |
2958 | + |
2959 | + sokoke_spawn_app (uri_fixed, FALSE); |
2960 | + |
2961 | + g_free (uri_fixed); |
2962 | + } |
2963 | +} |
2964 | + |
2965 | static void |
2966 | midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem, |
2967 | MidoriBookmarks* bookmarks) |
2968 | { |
2969 | - KatzeItem* item; |
2970 | - const gchar* uri; |
2971 | - |
2972 | - item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem"); |
2973 | - if (KATZE_ITEM_IS_FOLDER (item)) |
2974 | - { |
2975 | - KatzeItem* child; |
2976 | - KatzeArray* array; |
2977 | - |
2978 | - array = midori_bookmarks_read_from_db (bookmarks, |
2979 | - katze_item_get_meta_integer (item, "parentid"), NULL); |
2980 | - |
2981 | - g_return_if_fail (KATZE_IS_ARRAY (array)); |
2982 | - KATZE_ARRAY_FOREACH_ITEM (child, array) |
2983 | - { |
2984 | - if ((uri = katze_item_get_uri (child)) && *uri) |
2985 | - { |
2986 | - MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
2987 | - GtkWidget* view = midori_browser_add_item (browser, child); |
2988 | - midori_browser_set_current_tab_smartly (browser, view); |
2989 | - } |
2990 | - } |
2991 | - } |
2992 | - else if ((uri = katze_item_get_uri (item)) && *uri) |
2993 | - { |
2994 | - MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
2995 | - GtkWidget* view = midori_browser_add_item (browser, item); |
2996 | - midori_browser_set_current_tab_smartly (browser, view); |
2997 | - } |
2998 | + GtkWidget* last_view = NULL; |
2999 | + MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks)); |
3000 | + GtkTreeModel* model; |
3001 | + GList* rows; |
3002 | + gint length; |
3003 | + gint i; |
3004 | + |
3005 | + length = katze_tree_view_get_selected_rows (GTK_TREE_VIEW (bookmarks->treeview), |
3006 | + &model, &rows); |
3007 | + |
3008 | + if (!length) |
3009 | + { |
3010 | + KatzeItem* root = KATZE_ITEM (bookmarks->array); |
3011 | + KatzeItem* item = KATZE_ITEM (g_object_get_data (G_OBJECT (menuitem), "KatzeItem")); |
3012 | + |
3013 | + if (item != root) |
3014 | + return; |
3015 | + |
3016 | + last_view = midori_bookmarks_open_folder_in_tab (0, bookmarks, browser); |
3017 | + } |
3018 | + else |
3019 | + { |
3020 | + for (i = 0 ; i < length; i++) |
3021 | + { |
3022 | + GtkTreeIter iter; |
3023 | + |
3024 | + if (gtk_tree_model_get_iter ( |
3025 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, i))) |
3026 | + { |
3027 | + GtkWidget* view = NULL; |
3028 | + KatzeItem* item; |
3029 | + const gchar* uri; |
3030 | + |
3031 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
3032 | + |
3033 | + if (KATZE_ITEM_IS_SEPARATOR(item)) |
3034 | + continue; |
3035 | + |
3036 | + if (KATZE_ITEM_IS_FOLDER (item)) |
3037 | + view = midori_bookmarks_open_folder_in_tab ( |
3038 | + katze_item_get_meta_integer (item, "id"), bookmarks, browser); |
3039 | + else |
3040 | + view = midori_bookmarks_open_bookmark_in_tab (item, browser); |
3041 | + |
3042 | + g_object_unref (item); |
3043 | + |
3044 | + if (view) |
3045 | + last_view = view; |
3046 | + } |
3047 | + } |
3048 | + |
3049 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3050 | + } |
3051 | + |
3052 | + if (last_view) |
3053 | + midori_browser_set_current_tab_smartly (browser, last_view); |
3054 | } |
3055 | |
3056 | static void |
3057 | @@ -826,32 +2253,113 @@ |
3058 | KatzeItem* item, |
3059 | MidoriBookmarks* bookmarks) |
3060 | { |
3061 | + KatzeItem* root = KATZE_ITEM (bookmarks->array); |
3062 | GtkWidget* menu; |
3063 | GtkWidget* menuitem; |
3064 | |
3065 | menu = gtk_menu_new (); |
3066 | - if (KATZE_ITEM_IS_FOLDER (item)) |
3067 | - midori_bookmarks_popup_item (menu, |
3068 | - STOCK_TAB_NEW, _("Open all in _Tabs"), |
3069 | - item, midori_bookmarks_open_in_tab_activate_cb, bookmarks); |
3070 | + if ((item == root) |
3071 | + || KATZE_ITEM_IS_FOLDER (item)) |
3072 | + { |
3073 | + gint child_bookmarks_count = midori_array_count_recursive( |
3074 | + bookmarks->array, |
3075 | + "uri <> ''", |
3076 | + NULL, |
3077 | + item, |
3078 | + FALSE); |
3079 | + |
3080 | + if (!child_bookmarks_count) |
3081 | + midori_bookmarks_popup_item (menu, |
3082 | + STOCK_TAB_NEW, _("Open all in _Tabs"), |
3083 | + item, NULL, bookmarks); |
3084 | + else |
3085 | + midori_bookmarks_popup_item (menu, |
3086 | + STOCK_TAB_NEW, _("Open all in _Tabs"), |
3087 | + item, midori_bookmarks_open_in_tab_activate_cb, bookmarks); |
3088 | + } |
3089 | else |
3090 | { |
3091 | - midori_bookmarks_popup_item (menu, GTK_STOCK_OPEN, NULL, |
3092 | - item, midori_bookmarks_open_activate_cb, bookmarks); |
3093 | + if (katze_item_get_meta_boolean (item, "app")) |
3094 | + { |
3095 | + midori_bookmarks_popup_item (menu, |
3096 | + GTK_STOCK_EXECUTE, _("Open as Web A_pplication"), |
3097 | + item, midori_bookmarks_run_web_application_cb, bookmarks); |
3098 | + midori_bookmarks_popup_item (menu, GTK_STOCK_OPEN, NULL, |
3099 | + item, midori_bookmarks_open_activate_cb, bookmarks); |
3100 | + } |
3101 | + else |
3102 | + { |
3103 | + midori_bookmarks_popup_item (menu, GTK_STOCK_OPEN, NULL, |
3104 | + item, midori_bookmarks_open_activate_cb, bookmarks); |
3105 | + midori_bookmarks_popup_item (menu, |
3106 | + GTK_STOCK_EXECUTE, _("Open as Web A_pplication"), |
3107 | + item, midori_bookmarks_run_web_application_cb, bookmarks); |
3108 | + } |
3109 | + |
3110 | midori_bookmarks_popup_item (menu, STOCK_TAB_NEW, _("Open in New _Tab"), |
3111 | item, midori_bookmarks_open_in_tab_activate_cb, bookmarks); |
3112 | midori_bookmarks_popup_item (menu, STOCK_WINDOW_NEW, _("Open in New _Window"), |
3113 | item, midori_bookmarks_open_in_window_activate_cb, bookmarks); |
3114 | } |
3115 | - menuitem = gtk_separator_menu_item_new (); |
3116 | - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
3117 | - gtk_widget_show (menuitem); |
3118 | - midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL, |
3119 | - item, midori_bookmarks_edit_clicked_cb, bookmarks); |
3120 | - midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
3121 | - item, midori_bookmarks_delete_clicked_cb, bookmarks); |
3122 | - |
3123 | - katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
3124 | + |
3125 | + menuitem = gtk_separator_menu_item_new (); |
3126 | + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
3127 | + gtk_widget_show (menuitem); |
3128 | + |
3129 | + midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL, |
3130 | + item, (item == root) ? NULL : midori_bookmarks_edit_clicked_cb, bookmarks); |
3131 | + midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
3132 | + item, (item == root) ? NULL : midori_bookmarks_delete_clicked_cb, bookmarks); |
3133 | + |
3134 | + katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
3135 | +} |
3136 | + |
3137 | +static void |
3138 | +midori_bookmarks_multi_popup (GtkWidget* widget, |
3139 | + GdkEventButton* event, |
3140 | + MidoriBookmarks* bookmarks, |
3141 | + GtkTreeModel* model, |
3142 | + gint count, |
3143 | + GList* rows) |
3144 | +{ |
3145 | + GtkWidget* menu; |
3146 | + GtkWidget* menuitem; |
3147 | + |
3148 | + menu = gtk_menu_new (); |
3149 | + |
3150 | + midori_bookmarks_popup_item (menu, |
3151 | + STOCK_TAB_NEW, _("Open all in _Tabs"), |
3152 | + KATZE_ITEM(bookmarks->array), midori_bookmarks_open_in_tab_activate_cb, bookmarks); |
3153 | + menuitem = gtk_separator_menu_item_new (); |
3154 | + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
3155 | + gtk_widget_show (menuitem); |
3156 | + |
3157 | + midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL, |
3158 | + NULL, NULL, bookmarks); |
3159 | + midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL, |
3160 | + KATZE_ITEM(bookmarks->array), midori_bookmarks_delete_clicked_cb, bookmarks); |
3161 | + |
3162 | + katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR); |
3163 | +} |
3164 | + |
3165 | +static gboolean |
3166 | +midori_bookmarks_do_block_selection (GtkTreeSelection *selection, |
3167 | + GtkTreeModel *model, |
3168 | + GtkTreePath *path, |
3169 | + gboolean path_currently_selected, |
3170 | + gpointer data) |
3171 | +{ |
3172 | + return FALSE; |
3173 | +} |
3174 | + |
3175 | +static gboolean |
3176 | +midori_bookmarks_do_not_block_selection (GtkTreeSelection *selection, |
3177 | + GtkTreeModel *model, |
3178 | + GtkTreePath *path, |
3179 | + gboolean path_currently_selected, |
3180 | + gpointer data) |
3181 | +{ |
3182 | + return TRUE; |
3183 | } |
3184 | |
3185 | static gboolean |
3186 | @@ -862,32 +2370,198 @@ |
3187 | GtkTreeModel* model; |
3188 | GtkTreeIter iter; |
3189 | |
3190 | - if (event->button != 2 && event->button != 3) |
3191 | + if (bookmarks->pending_event) |
3192 | + { |
3193 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
3194 | + GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview); |
3195 | + gint x = bookmarks->stock_pending_event.x; |
3196 | + gint y = bookmarks->stock_pending_event.y; |
3197 | + |
3198 | + bookmarks->pending_event = NULL; |
3199 | + gtk_tree_selection_set_select_function ( |
3200 | + selection, midori_bookmarks_do_not_block_selection, NULL, NULL); |
3201 | + |
3202 | + if (x != event->x || y != event->y) |
3203 | + return TRUE; |
3204 | + } |
3205 | + |
3206 | + if (event->button == 3) |
3207 | + return TRUE; |
3208 | + |
3209 | + if (event->button != 2) |
3210 | return FALSE; |
3211 | |
3212 | if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter)) |
3213 | { |
3214 | - KatzeItem* item; |
3215 | - |
3216 | - gtk_tree_model_get (model, &iter, 0, &item, -1); |
3217 | - |
3218 | - if (event->button == 2) |
3219 | - { |
3220 | - const gchar* uri; |
3221 | - if (KATZE_ITEM_IS_BOOKMARK (item) && (uri = katze_item_get_uri (item)) && *uri) |
3222 | - { |
3223 | - MidoriBrowser* browser = midori_browser_get_for_widget (widget); |
3224 | - GtkWidget* view = midori_browser_add_uri (browser, uri); |
3225 | - midori_browser_set_current_tab (browser, view); |
3226 | - } |
3227 | - } |
3228 | - else |
3229 | - midori_bookmarks_popup (widget, event, item, bookmarks); |
3230 | - |
3231 | - if (item != NULL) |
3232 | - g_object_unref (item); |
3233 | - return TRUE; |
3234 | - } |
3235 | + gboolean done = FALSE; |
3236 | + KatzeItem* item; |
3237 | + |
3238 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
3239 | + |
3240 | + if (KATZE_ITEM_IS_BOOKMARK (item)) |
3241 | + { |
3242 | + MidoriBrowser* browser = midori_browser_get_for_widget (widget); |
3243 | + GtkWidget* view = midori_bookmarks_open_bookmark_in_tab ( |
3244 | + item, browser); |
3245 | + |
3246 | + if (widget) |
3247 | + { |
3248 | + midori_browser_set_current_tab_smartly (browser, view); |
3249 | + done = TRUE; |
3250 | + } |
3251 | + } |
3252 | + |
3253 | + g_object_unref (item); |
3254 | + |
3255 | + return done; |
3256 | + } |
3257 | + |
3258 | + return FALSE; |
3259 | +} |
3260 | + |
3261 | +static gboolean |
3262 | +midori_bookmarks_block_selection(GtkWidget* widget, |
3263 | + GdkEventButton* event, |
3264 | + MidoriBookmarks* bookmarks) |
3265 | +{ |
3266 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
3267 | + GtkTreePath* path; |
3268 | + GtkTreeSelection* selection; |
3269 | + gint cell_x; |
3270 | + gint cell_y; |
3271 | + |
3272 | + if (!gtk_tree_view_get_path_at_pos ( |
3273 | + treeview, event->x, event->y, |
3274 | + &path, NULL, &cell_x, &cell_y)) |
3275 | + return FALSE; |
3276 | + |
3277 | + gtk_widget_grab_focus (widget); |
3278 | + |
3279 | + selection = gtk_tree_view_get_selection (treeview); |
3280 | + |
3281 | + if (gtk_tree_selection_path_is_selected (selection, path) |
3282 | + && !(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK))) |
3283 | + { |
3284 | + bookmarks->pending_event = &bookmarks->stock_pending_event; |
3285 | + bookmarks->stock_pending_event.x = event->x; |
3286 | + bookmarks->stock_pending_event.y = event->y; |
3287 | + gtk_tree_selection_set_select_function ( |
3288 | + selection, midori_bookmarks_do_block_selection, NULL, NULL); |
3289 | + } |
3290 | + else |
3291 | + { |
3292 | + bookmarks->pending_event = NULL; |
3293 | + gtk_tree_selection_set_select_function ( |
3294 | + selection, midori_bookmarks_do_not_block_selection, NULL, NULL); |
3295 | + } |
3296 | + |
3297 | + return FALSE; |
3298 | +} |
3299 | + |
3300 | +static gboolean |
3301 | +midori_bookmarks_button_press_event_cb (GtkWidget* widget, |
3302 | + GdkEventButton* event, |
3303 | + MidoriBookmarks* bookmarks) |
3304 | +{ |
3305 | + GtkTreeView* treeview = GTK_TREE_VIEW(widget); |
3306 | + GtkTreePath* path; |
3307 | + GtkTreeSelection* selection; |
3308 | + GtkTreeModel* model; |
3309 | + gint selected; |
3310 | + GList* rows; |
3311 | + gint cell_x; |
3312 | + gint cell_y; |
3313 | + |
3314 | + if (event->button == 1) |
3315 | + return midori_bookmarks_block_selection (widget, event, bookmarks); |
3316 | + |
3317 | + if (event->button != 3) |
3318 | + return FALSE; |
3319 | + |
3320 | + selection = gtk_tree_view_get_selection (treeview); |
3321 | + |
3322 | + if (!gtk_tree_view_get_path_at_pos ( |
3323 | + treeview, event->x, event->y, |
3324 | + &path, NULL, &cell_x, &cell_y)) |
3325 | + { |
3326 | + /* FIXME: popup opening below treeview |
3327 | + * Rationale: the user is actually in ROOT folder |
3328 | + * we may need to have a non editable, non deletable, ROOT folder popup |
3329 | + * Open all in Tabs |
3330 | + * Separator |
3331 | + * Edit [inactive] |
3332 | + * Delete [inactive] |
3333 | + * Here we just mimic the Files behaviour: |
3334 | + * 1- unselect all |
3335 | + * 2- let popup based on selection process |
3336 | + */ |
3337 | + |
3338 | + gtk_tree_selection_unselect_all (selection); |
3339 | + } |
3340 | + else if (!gtk_tree_selection_path_is_selected (selection, path)) |
3341 | + { |
3342 | + /* Use case: popup opening on item not in selection |
3343 | + * Rationale: the user is addressing a single item not in selection |
3344 | + * we may need a single item popup with callbacks working on the item, |
3345 | + * not the selection. |
3346 | + * Here we just mimic the Files behaviour: |
3347 | + * 1- change the selection to the item the popup is opened on |
3348 | + * 2- let popup based on selection process |
3349 | + */ |
3350 | + |
3351 | + gtk_tree_selection_unselect_all (selection); |
3352 | + gtk_tree_selection_select_path (selection, path); |
3353 | + } |
3354 | + |
3355 | + selected = katze_tree_view_get_selected_rows(GTK_TREE_VIEW (widget), &model, &rows); |
3356 | + |
3357 | + if (!selected) |
3358 | + { |
3359 | + KatzeItem* root = KATZE_ITEM (bookmarks->array); |
3360 | + |
3361 | + midori_bookmarks_popup (widget, event, root, bookmarks); |
3362 | + |
3363 | + return TRUE; |
3364 | + } |
3365 | + |
3366 | + if (selected == 1) |
3367 | + { |
3368 | + GtkTreeIter iter; |
3369 | + KatzeItem* item; |
3370 | + |
3371 | + if (!gtk_tree_model_get_iter ( |
3372 | + model, &iter, (GtkTreePath *)g_list_nth_data (rows, 0))) |
3373 | + { |
3374 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3375 | + |
3376 | + return FALSE; |
3377 | + } |
3378 | + |
3379 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
3380 | + |
3381 | + midori_bookmarks_popup (widget, event, item, bookmarks); |
3382 | + |
3383 | + g_object_unref (item); |
3384 | + |
3385 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3386 | + |
3387 | + return TRUE; |
3388 | + } |
3389 | + |
3390 | + if (selected > 1) |
3391 | + { |
3392 | + midori_bookmarks_multi_popup (widget, |
3393 | + event, |
3394 | + bookmarks, |
3395 | + model, |
3396 | + selected, |
3397 | + rows); |
3398 | + |
3399 | + g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free); |
3400 | + |
3401 | + return TRUE; |
3402 | + } |
3403 | + |
3404 | return FALSE; |
3405 | } |
3406 | |
3407 | @@ -918,46 +2592,82 @@ |
3408 | } |
3409 | } |
3410 | |
3411 | -static void |
3412 | -midori_bookmarks_row_expanded_cb (GtkTreeView* treeview, |
3413 | - GtkTreeIter* iter, |
3414 | - GtkTreePath* path, |
3415 | - MidoriBookmarks* bookmarks) |
3416 | +static gboolean |
3417 | +midori_bookmarks_test_expand_row_cb (GtkTreeView* treeview, |
3418 | + GtkTreeIter* iter, |
3419 | + GtkTreePath* path, |
3420 | + MidoriBookmarks* bookmarks) |
3421 | { |
3422 | GtkTreeModel* model; |
3423 | + GtkTreeIter child; |
3424 | KatzeItem* item; |
3425 | + gint64 id; |
3426 | |
3427 | model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); |
3428 | + |
3429 | gtk_tree_model_get (model, iter, 0, &item, -1); |
3430 | + |
3431 | + g_return_val_if_fail (KATZE_IS_ITEM(item), TRUE); |
3432 | + |
3433 | + g_signal_handlers_block_by_func (model, |
3434 | + midori_bookmarks_row_deleted_cb, |
3435 | + bookmarks); |
3436 | + |
3437 | + id = katze_item_get_meta_integer (item, "id"); |
3438 | + |
3439 | + g_object_unref (item); |
3440 | + |
3441 | + while (gtk_tree_model_iter_children (model, &child, iter)) |
3442 | + gtk_tree_store_remove (GTK_TREE_STORE (model), &child); |
3443 | + /* That's an invisible dummy, so we always have an expander */ |
3444 | + gtk_tree_store_insert_with_values (GTK_TREE_STORE (model), &child, iter, |
3445 | + 0, 0, NULL, -1); |
3446 | + |
3447 | + g_signal_handlers_unblock_by_func (model, |
3448 | + midori_bookmarks_row_deleted_cb, |
3449 | + bookmarks); |
3450 | + |
3451 | midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model), |
3452 | - iter, katze_item_get_meta_integer (item, "id"), NULL); |
3453 | - g_object_unref (item); |
3454 | + iter, id, NULL); |
3455 | + |
3456 | + return FALSE; |
3457 | } |
3458 | |
3459 | static void |
3460 | midori_bookmarks_row_collapsed_cb (GtkTreeView *treeview, |
3461 | GtkTreeIter *parent, |
3462 | GtkTreePath *path, |
3463 | - gpointer user_data) |
3464 | + MidoriBookmarks* bookmarks) |
3465 | { |
3466 | GtkTreeModel* model; |
3467 | GtkTreeStore* treestore; |
3468 | GtkTreeIter child; |
3469 | |
3470 | model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); |
3471 | + |
3472 | + g_signal_handlers_block_by_func (model, |
3473 | + midori_bookmarks_row_deleted_cb, |
3474 | + bookmarks); |
3475 | + |
3476 | treestore = GTK_TREE_STORE (model); |
3477 | while (gtk_tree_model_iter_nth_child (model, &child, parent, 0)) |
3478 | gtk_tree_store_remove (treestore, &child); |
3479 | /* That's an invisible dummy, so we always have an expander */ |
3480 | gtk_tree_store_insert_with_values (treestore, &child, parent, |
3481 | 0, 0, NULL, -1); |
3482 | -} |
3483 | + |
3484 | + g_signal_handlers_block_by_func (model, |
3485 | + midori_bookmarks_row_deleted_cb, |
3486 | + bookmarks); |
3487 | + |
3488 | + } |
3489 | |
3490 | static void |
3491 | midori_bookmarks_selection_changed_cb (GtkTreeSelection *treeview, |
3492 | MidoriBookmarks *bookmarks) |
3493 | { |
3494 | midori_bookmarks_toolbar_update (bookmarks); |
3495 | + midori_bookmarks_statusbar_update (bookmarks); |
3496 | } |
3497 | |
3498 | static gboolean |
3499 | @@ -993,6 +2703,123 @@ |
3500 | midori_bookmarks_filter_timeout_cb, bookmarks, NULL); |
3501 | } |
3502 | |
3503 | +static GtkTargetEntry midori_bookmarks_dnd_target_entries[]= |
3504 | +{ |
3505 | + {"GTK_TREE_MODEL_MULTI_ROWS", GTK_TARGET_SAME_WIDGET, 0}, |
3506 | +}; |
3507 | + |
3508 | +#define MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES \ |
3509 | + G_N_ELEMENTS (midori_bookmarks_dnd_target_entries) |
3510 | + |
3511 | +static guint |
3512 | +item_hash (gconstpointer item) |
3513 | +{ |
3514 | + gint64 id = katze_item_get_meta_integer (KATZE_ITEM (item), "id"); |
3515 | + return g_int64_hash (&id); |
3516 | +} |
3517 | + |
3518 | +static gboolean |
3519 | +item_equal (gconstpointer item_a, gconstpointer item_b) |
3520 | +{ |
3521 | + gint64 id_a = katze_item_get_meta_integer (KATZE_ITEM (item_a), "id"); |
3522 | + gint64 id_b = katze_item_get_meta_integer (KATZE_ITEM (item_b), "id"); |
3523 | + return (id_a == id_b)? TRUE : FALSE; |
3524 | +} |
3525 | + |
3526 | +static gboolean |
3527 | +midori_bookmarks_idle (gpointer data) |
3528 | +{ |
3529 | + MidoriBookmarks* bookmarks = MIDORI_BOOKMARKS (data); |
3530 | + GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview)); |
3531 | + GHashTableIter hash_iter; |
3532 | + gpointer key, value; |
3533 | + GList* list_iter; |
3534 | + |
3535 | + /* update remaining additions */ |
3536 | + |
3537 | + list_iter = bookmarks->added_paths; |
3538 | + while (list_iter) |
3539 | + { |
3540 | + GtkTreePath* path = (GtkTreePath*)list_iter->data; |
3541 | + |
3542 | + update_items_for_parent (model, path, bookmarks); |
3543 | + |
3544 | + list_iter = g_list_next (list_iter); |
3545 | + } |
3546 | + |
3547 | + g_list_free_full (bookmarks->added_paths, (GDestroyNotify) gtk_tree_path_free); |
3548 | + bookmarks->added_paths = NULL; |
3549 | + |
3550 | + /* then finalize updates */ |
3551 | + g_signal_handlers_block_by_func (bookmarks->array, |
3552 | + midori_bookmarks_update_item_cb, |
3553 | + bookmarks); |
3554 | + |
3555 | + g_hash_table_iter_init (&hash_iter, bookmarks->updated_items); |
3556 | + |
3557 | + while (g_hash_table_iter_next (&hash_iter, &key, &value)) |
3558 | + { |
3559 | + KatzeItem *item = KATZE_ITEM(key); |
3560 | + |
3561 | + katze_array_update_item (bookmarks->array, item); |
3562 | + g_object_unref (item); |
3563 | + } |
3564 | + |
3565 | + g_signal_handlers_unblock_by_func (bookmarks->array, |
3566 | + midori_bookmarks_update_item_cb, |
3567 | + bookmarks); |
3568 | + |
3569 | + g_hash_table_remove_all (bookmarks->updated_items); |
3570 | + |
3571 | + return FALSE; |
3572 | +} |
3573 | + |
3574 | +static void |
3575 | +midori_bookmarks_update_item (MidoriBookmarks* bookmarks, KatzeItem *item) |
3576 | +{ |
3577 | + if (!g_hash_table_size (bookmarks->updated_items) |
3578 | + || (!g_list_length (bookmarks->added_paths))) |
3579 | + g_idle_add (midori_bookmarks_idle, bookmarks); |
3580 | + else if (g_hash_table_lookup (bookmarks->updated_items, item)) |
3581 | + return; |
3582 | + |
3583 | + g_object_ref (item); |
3584 | + g_hash_table_insert (bookmarks->updated_items, item, item); |
3585 | +} |
3586 | + |
3587 | +static void |
3588 | +midori_bookmarks_idle_remove_item (MidoriBookmarks* bookmarks, KatzeItem *item) |
3589 | +{ |
3590 | + gpointer found; |
3591 | + |
3592 | + if (KATZE_ITEM_IS_FOLDER (item)) |
3593 | + { |
3594 | + gint64 id = katze_item_get_meta_integer (item, "id"); |
3595 | + GHashTableIter iter; |
3596 | + gpointer key, value; |
3597 | + |
3598 | + g_hash_table_iter_init (&iter, bookmarks->updated_items); |
3599 | + |
3600 | + while (g_hash_table_iter_next (&iter, &key, &value)) |
3601 | + { |
3602 | + KatzeItem *hash_item = KATZE_ITEM(key); |
3603 | + |
3604 | + gint64 parentid = katze_item_get_meta_integer (hash_item, "parentid"); |
3605 | + if (parentid == id) |
3606 | + { |
3607 | + g_hash_table_iter_remove (&iter); |
3608 | + g_object_unref (hash_item); |
3609 | + } |
3610 | + } |
3611 | + } |
3612 | + |
3613 | + if (found = g_hash_table_lookup (bookmarks->updated_items, item)) |
3614 | + { |
3615 | + g_hash_table_remove (bookmarks->updated_items, found); |
3616 | + g_object_unref (found); |
3617 | + } |
3618 | +} |
3619 | + |
3620 | static void |
3621 | midori_bookmarks_init (MidoriBookmarks* bookmarks) |
3622 | { |
3623 | @@ -1005,6 +2832,8 @@ |
3624 | GtkCellRenderer* renderer_text; |
3625 | GtkTreeSelection* selection; |
3626 | |
3627 | + bookmarks->pending_event = NULL; |
3628 | + |
3629 | /* Create the filter entry */ |
3630 | entry = sokoke_search_entry_new (_("Search Bookmarks")); |
3631 | g_signal_connect_after (entry, "changed", |
3632 | @@ -1015,7 +2844,7 @@ |
3633 | gtk_box_pack_start (GTK_BOX (bookmarks), box, FALSE, FALSE, 5); |
3634 | |
3635 | /* Create the treeview */ |
3636 | - model = gtk_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING); |
3637 | + model = midori_bookmarks_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING); |
3638 | treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); |
3639 | gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); |
3640 | gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), 1); |
3641 | @@ -1032,29 +2861,49 @@ |
3642 | (GtkTreeCellDataFunc)midori_bookmarks_treeview_render_text_cb, |
3643 | treeview, NULL); |
3644 | gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); |
3645 | - gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE); |
3646 | + gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), FALSE); |
3647 | + gtk_tree_view_enable_model_drag_source ( |
3648 | + GTK_TREE_VIEW (treeview), |
3649 | + GDK_BUTTON1_MASK, |
3650 | + midori_bookmarks_dnd_target_entries, |
3651 | + MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES, |
3652 | + GDK_ACTION_MOVE|GDK_ACTION_LINK); |
3653 | + gtk_tree_view_enable_model_drag_dest ( |
3654 | + GTK_TREE_VIEW (treeview), |
3655 | + midori_bookmarks_dnd_target_entries, |
3656 | + MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES, |
3657 | + GDK_ACTION_MOVE|GDK_ACTION_LINK); |
3658 | g_object_unref (model); |
3659 | g_object_connect (treeview, |
3660 | "signal::row-activated", |
3661 | midori_bookmarks_row_activated_cb, bookmarks, |
3662 | + "signal::button-press-event", |
3663 | + midori_bookmarks_button_press_event_cb, bookmarks, |
3664 | "signal::button-release-event", |
3665 | midori_bookmarks_button_release_event_cb, bookmarks, |
3666 | "signal::key-release-event", |
3667 | midori_bookmarks_key_release_event_cb, bookmarks, |
3668 | "signal::popup-menu", |
3669 | midori_bookmarks_popup_menu_cb, bookmarks, |
3670 | - "signal::row-expanded", |
3671 | - midori_bookmarks_row_expanded_cb, bookmarks, |
3672 | + "signal::test-expand-row", |
3673 | + midori_bookmarks_test_expand_row_cb, bookmarks, |
3674 | "signal::row-collapsed", |
3675 | midori_bookmarks_row_collapsed_cb, bookmarks, |
3676 | NULL); |
3677 | + |
3678 | + MIDORI_BOOKMARKS_TREE_STORE (model)->source_view = GTK_TREE_VIEW (treeview); |
3679 | + |
3680 | selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); |
3681 | + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); |
3682 | g_signal_connect_after (selection, "changed", |
3683 | G_CALLBACK (midori_bookmarks_selection_changed_cb), |
3684 | bookmarks); |
3685 | gtk_widget_show (treeview); |
3686 | gtk_box_pack_start (GTK_BOX (bookmarks), treeview, TRUE, TRUE, 0); |
3687 | bookmarks->treeview = treeview; |
3688 | + |
3689 | + bookmarks->updated_items = g_hash_table_new (item_hash, item_equal); |
3690 | + bookmarks->added_paths = NULL; |
3691 | } |
3692 | |
3693 | static void |
3694 | @@ -1064,5 +2913,9 @@ |
3695 | |
3696 | if (bookmarks->app) |
3697 | g_object_unref (bookmarks->app); |
3698 | + |
3699 | + g_idle_remove_by_data (bookmarks); |
3700 | + g_hash_table_unref (bookmarks->updated_items); |
3701 | + g_list_free_full (bookmarks->added_paths, (GDestroyNotify) gtk_tree_path_free); |
3702 | + bookmarks->added_paths = NULL; |
3703 | } |
3704 | - |
3705 | |
3706 | === modified file 'tests/bookmarks.c' |
3707 | --- tests/bookmarks.c 2012-11-25 15:37:41 +0000 |
3708 | +++ tests/bookmarks.c 2013-05-21 05:35:32 +0000 |
3709 | @@ -128,7 +128,7 @@ |
3710 | } |
3711 | |
3712 | db_items = midori_array_query_recursive (db_bookmarks, |
3713 | - "*", "title='%q'", katze_item_get_name (test_item), FALSE); |
3714 | + "*", "title='%q'", katze_item_get_name (test_item), NULL, FALSE); |
3715 | |
3716 | /* FIXME g_assert_cmpint (katze_array_get_length (db_items), ==, 1); */ |
3717 | db_item = katze_array_get_nth_item (db_items, 0); |
Hey André, thanks for this huge work! I have a couple of problems to report however...
It seems for some reason there is a bunch of .po files scattered around your branch :p
Also, the build fails with:
../panels/ midori- bookmarks. c: In function ‘midori_ bookmarks_ tree_store_ drag_data_ get’: midori- bookmarks. c:903:23: error: dereferencing pointer to incomplete type midori- bookmarks. c: In function ‘midori_ bookmarks_ tree_store_ get_rows_ drag_data’ : midori- bookmarks. c:1044: 23: error: dereferencing pointer to incomplete type midori- bookmarks. c:1047: 23: error: dereferencing pointer to incomplete type midori- bookmarks. c:1050: 33: error: dereferencing pointer to incomplete type midori- bookmarks. c: In function ‘midori_ bookmarks_ tree_store_ row_drop_ possible’ : midori- bookmarks. c:1112: 23: error: dereferencing pointer to incomplete type midori- bookmarks. c: In function ‘midori_ bookmarks_ tree_store_ drag_data_ received’ : midori- bookmarks. c:1229: 23: error: dereferencing pointer to incomplete type
../panels/
../panels/
../panels/
../panels/
../panels/
../panels/
../panels/
../panels/
../panels/