Merge lp:~aauzi/midori/fix-1179624 into lp:midori
- fix-1179624
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Cris Dywan | ||||
Approved revision: | 6180 | ||||
Merged at revision: | 6202 | ||||
Proposed branch: | lp:~aauzi/midori/fix-1179624 | ||||
Merge into: | lp:midori | ||||
Diff against target: |
547 lines (+404/-10) 4 files modified
midori/midori-array.c (+150/-0) midori/midori-array.h (+7/-0) midori/midori-browser.c (+15/-4) panels/midori-bookmarks.c (+232/-6) |
||||
To merge this branch: | bzr merge lp:~aauzi/midori/fix-1179624 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cris Dywan | Approve | ||
André Auzi | Needs Resubmitting | ||
Paweł Forysiuk | Approve | ||
Review via email:
|
This proposal supersedes a proposal from 2013-05-31.
Commit message
Show visual feedback when hovering over items in bookmark panel
Description of the change
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cris Dywan (kalikiana) wrote : Posted in a previous version of this proposal | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
André Auzi (aauzi) wrote : Posted in a previous version of this proposal | # |
> 385 + else if (!child_
> 386 + text = g_strdup_printf(
> 387 + _("%s : folder, %d subfolders and no bookmark"),
> 388 + name, child_folders_
>
> This should be done using ngettext, leaving gettext to figure out plural forms
> (there may be a dual form or other grammatical implications the code can't
> handle).
Interesting. I was not aware of ngettext existence. I will give it a try.
> Is it necessary to implement midori_
> midori_
> seems a bit wasteful.
Well, the count within a folder is done using a COUNT(*) sql statement but SQLite does not implement recursive queries therefore I had to implement recursion within the code.
I nevertheless agree, midori_
Especially if we consider the fact that I not only retrieve the sub folder id but also its *uri* (!!!goof!!!)
This being noticed I still have doubts about the feature, initially I thought we could need to implement fancy stuff like giving the counts for the whole tree depth if the user press the 'alt' or 'ctrl' modifiers but the feedback I get with one child level actually suits my needs, I wonder if the need of such feature would come up one day.
If nobody needs it, it's the whole idea of recursion that's wasteful and we could just get rid of it and stick to one child level count which is achieved with a single SQL statement.
I wonder if it was the meaning of the remark?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cris Dywan (kalikiana) wrote : Posted in a previous version of this proposal | # |
Thanks a lot for the updates! I think personally it's fine to do the counting this way, as usual I'd like Paweł's opinion on any bookmark UI changes.
Meanwhile "Open as Web A_pplication" was dropped as a pseudo-bookmark feature, please drop it here as well. Generel agreement is to leave this functionality to the web app extension.
There's also a merge conflict, you'll want to 'bzr merge lp:midori' to resolve it (see also the wiki).
Btw you can use "--fixes=lp:1179624" as an argument to "bzr commit" instead of in the message which makes a clickable link in the log and ensures closing of the bug once it's merged.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Paweł Forysiuk (tuxator) wrote : Posted in a previous version of this proposal | # |
Looks promising.
Please resolve conflicts and drop webapp code, it should slim the patch a bit
making it easier to read.
47 + text = g_strdup_printf(
448 + _("%s : folder, %s and %s"),
449 + name,
450 + child_bookmarks
451 + child_folders_str);
Can you maybe "pack" such statements? I don't think this style is used in midori code and it
balloons the patch as well. I see it a couple of places.
+ text = g_strdup_
+ name, child_bookmarks
Something like this is still readable i think.
As for translatable strings it would be wise to add comments for translators there
/* i18n: some explanation */ Should help those reading the code as well.
Otherwise code looks good. Let's see again after update.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
André Auzi (aauzi) wrote : Posted in a previous version of this proposal | # |
Thanks for the remarks.
Concerning the "web application" removal it was not clear to me if the status bar text and GTK_STOCK_EXECUTE icon use was to be removed as well. I just left them in the proposal so far.
In my opinion they should stay because it's the only remaining visual hint of the special behaviour of a click on such bookmarks.
Nevertheless it's your design decision, just let me know if I have to cleanup this part as well.
If not, a nice improvement, that's unfortunately not yet in my skills abilities, would be to use a combined icon made of the site's favicon and a "web application marker" (maybe a star or something like that...)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cris Dywan (kalikiana) wrote : Posted in a previous version of this proposal | # |
André, to clarify. I brought up the app handling because your patch extends it further. The change moving away from it I referred to is https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
André Auzi (aauzi) wrote : Posted in a previous version of this proposal | # |
Ok I think I've understood.
App handling is going to be something completely different and refering to metadata "app" would produce an integration issue.
I get rid of it.
Thanks for clarifying.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
André Auzi (aauzi) wrote : Posted in a previous version of this proposal | # |
comments from:
pfor: displaying title and uri feels kinda redundant to be fair, you see the same information in the panel
pfor: and i guess it depends on the bookmark and your monitor size but sometimes it will obscure the info
pfor: i would just do something like that
pfor: bookmark leading to: ...
pfor: webapp launching: ....
pfor: folder containing: ....
pfor: in statusbar you can have enabled statusbar features that would take some space, with text as such all "critical" info should be still visible
pfor: i would leave the webapp code out for now
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Paweł Forysiuk (tuxator) wrote : Posted in a previous version of this proposal | # |
8 + if (KATZE_
199 + {
200 + gint child_bookmarks
201 + "uri <> ''", NULL, item, FALSE);
202 +
203 + if (!child_
204 + midori_
205 + STOCK_TAB_NEW, _("Open all in _Tabs"), item, NULL, browser);
206 + else
207 + midori_
208 + STOCK_TAB_NEW, _("Open all in _Tabs"),
209 + item, midori_
210 + }
This part looks a bit strange.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
André Auzi (aauzi) wrote : Posted in a previous version of this proposal | # |
> 8 + if (KATZE_
> 199 + {
> 200 + gint child_bookmarks
> (browser-
> 201 + "uri <> ''", NULL, item, FALSE);
> 202 +
> 203 + if (!child_
> 204 + midori_
> 205 + STOCK_TAB_NEW, _("Open all in _Tabs"), item, NULL,
> browser);
> 206 + else
> 207 + midori_
> 208 + STOCK_TAB_NEW, _("Open all in _Tabs"),
> 209 + item,
> midori_
> 210 + }
>
> This part looks a bit strange.
hmm, I guess it's the coding style that looks unfamiliar.
Maybe I could rewrite it this way:
if (KATZE_
{
gint child_bookmarks
"uri <> ''", NULL, item, FALSE);
}
The intent is to make the menu item insensitive when the folder does not contain bookmarks as suggested in : http://
It's related to the following change in midori_
182 - g_signal_connect (menuitem, "activate", G_CALLBACK (callback), userdata);
183 + if (callback)
184 + g_signal_connect (menuitem, "activate", G_CALLBACK (callback), userdata);
185 + else
186 + gtk_widget_
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Paweł Forysiuk (tuxator) wrote : | # |
Works nicely. Code looks good to me.
Thanks for the updates.
Now i kinda miss getting this feedback when hovering over items in bookmarks bar ;)
I think the most of the code could be reused in that case so it should not be hard
to do this after as a subsequent patch maybe.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
André Auzi (aauzi) wrote : | # |
> Works nicely. Code looks good to me.
> Thanks for the updates.
>
> Now i kinda miss getting this feedback when hovering over items in bookmarks
> bar ;)
> I think the most of the code could be reused in that case so it should not be
> hard
> to do this after as a subsequent patch maybe.
Thank you for the quick review and approval.
Concerning the bookmark bar (and bookmark menu btw) they're a totally different story and I didn't feel confident enough with katze-arrayaction's design to change anything around it by the time I started this patch.
Things have changed and their update will probably come ;)
If you want to help me in this process please feel free to comment my other proposals maybe starting by https:/
Beside, I will report the changes made here in the companion bug fixes.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cris Dywan (kalikiana) wrote : | # |
278 +midori_
I would prefer it all text in the statusbar starts uppercase, "Empty folder", "Folder containing" and so on, otherwise it will look poor, spelling has an incredible impact on how you see text
323 + text = g_strdup_printf (_("bookmark leading to : %s"), uri)
No space before : in English
406 +midori_
412 + KatzeItem* item;
420 + if (gtk_tree_
421 + gtk_tree_model_get (model, &iter, 0, &item, -1);
I read an undefined item there if the condition is FALSE.
If you could sort out these last nitpickes I think the patch is good to go
- 6180. By André Auzi
-
Take into account review comments + merge lp:midori
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
André Auzi (aauzi) wrote : | # |
> 278 +midori_
>
> I would prefer it all text in the statusbar starts uppercase, "Empty folder",
> "Folder containing" and so on, otherwise it will look poor, spelling has an
> incredible impact on how you see text
>
> 323 + text = g_strdup_printf (_("bookmark leading to : %s"),
> uri)
>
> No space before : in English
>
> 406 +midori_
> 412 + KatzeItem* item;
> 420 + if (gtk_tree_
> 421 + gtk_tree_model_get (model, &iter, 0, &item, -1);
>
> I read an undefined item there if the condition is FALSE.
>
> If you could sort out these last nitpickes I think the patch is good to go
No problem. Done.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cody Garver (codygarver) wrote : | # |
André, don't mark the branch as Resubmit, that's meant for reviewers to do and it makes the branch less visible on the page that lists available merges. Instead you should only make a regular comment that says you made the requested changes.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cris Dywan (kalikiana) wrote : | # |
Please don't merge trunk and fixes in one commit, it makes the diff harder to read (though I knew what I was looking for in this case and it wasn't so bad).
Looks good now!
Preview Diff
1 | === modified file 'midori/midori-array.c' |
2 | --- midori/midori-array.c 2013-04-16 23:16:24 +0000 |
3 | +++ midori/midori-array.c 2013-06-04 17:32:25 +0000 |
4 | @@ -1194,3 +1194,153 @@ |
5 | return midori_array_query_recursive (bookmarks, fields, condition, value, FALSE); |
6 | } |
7 | |
8 | +static gint64 |
9 | +count_from_sqlite (sqlite3* db, |
10 | + const gchar* sqlcmd) |
11 | +{ |
12 | + gint64 count = -1; |
13 | + sqlite3_stmt* stmt; |
14 | + gint result; |
15 | + |
16 | + result = sqlite3_prepare_v2 (db, sqlcmd, -1, &stmt, NULL); |
17 | + if (result != SQLITE_OK) |
18 | + return -1; |
19 | + |
20 | + g_assert (sqlite3_column_count (stmt) == 1); |
21 | + |
22 | + if ((result = sqlite3_step (stmt)) == SQLITE_ROW) |
23 | + count = sqlite3_column_int64(stmt, 0); |
24 | + |
25 | + sqlite3_clear_bindings (stmt); |
26 | + sqlite3_reset (stmt); |
27 | + |
28 | + return count; |
29 | +} |
30 | + |
31 | +static gint64 |
32 | +midori_array_count_recursive_by_id (KatzeArray* bookmarks, |
33 | + const gchar* condition, |
34 | + const gchar* value, |
35 | + gint64 id, |
36 | + gboolean recursive) |
37 | +{ |
38 | + gint64 count = -1; |
39 | + sqlite3* db; |
40 | + gchar* sqlcmd; |
41 | + char* sqlcmd_value; |
42 | + sqlite3_stmt* stmt; |
43 | + gint result; |
44 | + GList* ids; |
45 | + GList* iter_ids; |
46 | + |
47 | + g_return_val_if_fail (condition, -1); |
48 | + g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), -1); |
49 | + db = g_object_get_data (G_OBJECT (bookmarks), "db"); |
50 | + g_return_val_if_fail (db != NULL, -1); |
51 | + |
52 | + g_assert(!strstr("parentid", condition)); |
53 | + |
54 | + if (id > 0) |
55 | + sqlcmd = g_strdup_printf ("SELECT COUNT(*) FROM bookmarks " |
56 | + "WHERE parentid = %" G_GINT64_FORMAT " AND %s", |
57 | + id, |
58 | + condition); |
59 | + else |
60 | + sqlcmd = g_strdup_printf ("SELECT COUNT(*) FROM bookmarks " |
61 | + "WHERE parentid IS NULL AND %s ", |
62 | + condition); |
63 | + |
64 | + if (strstr (condition, "%q")) |
65 | + { |
66 | + sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : ""); |
67 | + count = count_from_sqlite (db, sqlcmd_value); |
68 | + sqlite3_free (sqlcmd_value); |
69 | + } |
70 | + else |
71 | + count = count_from_sqlite (db, sqlcmd); |
72 | + |
73 | + g_free (sqlcmd); |
74 | + |
75 | + if (!recursive || (count < 0)) |
76 | + return count; |
77 | + |
78 | + ids = NULL; |
79 | + |
80 | + if (id > 0) |
81 | + sqlcmd_value = sqlite3_mprintf ( |
82 | + "SELECT id FROM bookmarks " |
83 | + "WHERE parentid = %" G_GINT64_FORMAT " AND uri = ''", id); |
84 | + else |
85 | + sqlcmd_value = sqlite3_mprintf ( |
86 | + "SELECT id FROM bookmarks " |
87 | + "WHERE parentid IS NULL AND uri = ''"); |
88 | + |
89 | + if (sqlite3_prepare_v2 (db, sqlcmd_value, -1, &stmt, NULL) == SQLITE_OK) |
90 | + { |
91 | + g_assert (sqlite3_column_count (stmt) == 1); |
92 | + |
93 | + if ((result = sqlite3_step (stmt)) == SQLITE_ROW) |
94 | + { |
95 | + gint64* pid = g_new (gint64, 1); |
96 | + |
97 | + *pid = sqlite3_column_int64(stmt, 0); |
98 | + ids = g_list_append (ids, pid); |
99 | + } |
100 | + |
101 | + sqlite3_clear_bindings (stmt); |
102 | + sqlite3_reset (stmt); |
103 | + } |
104 | + |
105 | + sqlite3_free (sqlcmd_value); |
106 | + |
107 | + iter_ids = ids; |
108 | + while (iter_ids) |
109 | + { |
110 | + gint64 sub_count = midori_array_count_recursive_by_id (bookmarks, |
111 | + condition, |
112 | + value, |
113 | + *(gint64*)(iter_ids->data), |
114 | + recursive); |
115 | + |
116 | + if (sub_count < 0) |
117 | + { |
118 | + g_list_free_full (ids, g_free); |
119 | + return -1; |
120 | + } |
121 | + |
122 | + count += sub_count; |
123 | + iter_ids = g_list_next (iter_ids); |
124 | + } |
125 | + |
126 | + g_list_free_full (ids, g_free); |
127 | + return count; |
128 | +} |
129 | + |
130 | +/** |
131 | + * midori_array_count_recursive: |
132 | + * @array: the main bookmark array |
133 | + * @condition: condition, like "folder = '%q'" |
134 | + * @value: a value to be inserted if @condition contains %q |
135 | + * @recursive: if %TRUE include children |
136 | + * |
137 | + * Return value: the number of elements on success, -1 otherwise |
138 | + * |
139 | + * Since: 0.5.2 |
140 | + **/ |
141 | +gint64 |
142 | +midori_array_count_recursive (KatzeArray* bookmarks, |
143 | + const gchar* condition, |
144 | + const gchar* value, |
145 | + KatzeItem* folder, |
146 | + gboolean recursive) |
147 | +{ |
148 | + gint64 id = -1; |
149 | + |
150 | + g_return_val_if_fail (!folder || KATZE_ITEM_IS_FOLDER (folder), -1); |
151 | + |
152 | + id = folder ? katze_item_get_meta_integer (folder, "id") : 0; |
153 | + |
154 | + return midori_array_count_recursive_by_id (bookmarks, condition, |
155 | + value, id, |
156 | + recursive); |
157 | +} |
158 | |
159 | === modified file 'midori/midori-array.h' |
160 | --- midori/midori-array.h 2012-01-03 20:15:19 +0000 |
161 | +++ midori/midori-array.h 2013-06-04 17:32:25 +0000 |
162 | @@ -47,4 +47,11 @@ |
163 | katze_array_from_sqlite (sqlite3* db, |
164 | const gchar* sqlcmd); |
165 | |
166 | +gint64 |
167 | +midori_array_count_recursive (KatzeArray* bookmarks, |
168 | + const gchar* condition, |
169 | + const gchar* value, |
170 | + KatzeItem* folder, |
171 | + gboolean recursive); |
172 | + |
173 | #endif /* !__MIDORI_ARRAY_H__ */ |
174 | |
175 | === modified file 'midori/midori-browser.c' |
176 | --- midori/midori-browser.c 2013-05-31 03:40:27 +0000 |
177 | +++ midori/midori-browser.c 2013-06-04 17:32:25 +0000 |
178 | @@ -4147,7 +4147,10 @@ |
179 | else if (!KATZE_IS_ARRAY (item) && strcmp (stock_id, GTK_STOCK_DELETE)) |
180 | gtk_widget_set_sensitive (menuitem, uri != NULL); |
181 | g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item); |
182 | - g_signal_connect (menuitem, "activate", G_CALLBACK (callback), userdata); |
183 | + if (callback) |
184 | + g_signal_connect (menuitem, "activate", G_CALLBACK (callback), userdata); |
185 | + else |
186 | + gtk_widget_set_sensitive (menuitem, FALSE); |
187 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
188 | gtk_widget_show (menuitem); |
189 | } |
190 | @@ -4237,10 +4240,16 @@ |
191 | GtkWidget* menuitem; |
192 | |
193 | menu = gtk_menu_new (); |
194 | - if (!katze_item_get_uri (item)) |
195 | + if (KATZE_ITEM_IS_FOLDER (item)) |
196 | + { |
197 | + gint child_bookmarks_count = midori_array_count_recursive (browser->bookmarks, |
198 | + "uri <> ''", NULL, item, FALSE); |
199 | + |
200 | midori_browser_bookmark_popup_item (menu, |
201 | - STOCK_TAB_NEW, _("Open all in _Tabs"), |
202 | - item, midori_browser_bookmark_open_in_tab_activate_cb, browser); |
203 | + STOCK_TAB_NEW, _("Open all in _Tabs"), item, |
204 | + (!child_bookmarks_count ? NULL : midori_browser_bookmark_open_in_tab_activate_cb), |
205 | + browser); |
206 | + } |
207 | else |
208 | { |
209 | midori_browser_bookmark_popup_item (menu, GTK_STOCK_OPEN, NULL, |
210 | @@ -4252,9 +4261,11 @@ |
211 | STOCK_WINDOW_NEW, _("Open in New _Window"), |
212 | item, midori_browser_bookmark_open_in_window_activate_cb, browser); |
213 | } |
214 | + |
215 | menuitem = gtk_separator_menu_item_new (); |
216 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
217 | gtk_widget_show (menuitem); |
218 | + |
219 | midori_browser_bookmark_popup_item (menu, GTK_STOCK_EDIT, NULL, |
220 | item, midori_browser_bookmark_edit_activate_cb, widget); |
221 | midori_browser_bookmark_popup_item (menu, GTK_STOCK_DELETE, NULL, |
222 | |
223 | === modified file 'panels/midori-bookmarks.c' |
224 | --- panels/midori-bookmarks.c 2013-02-11 21:49:41 +0000 |
225 | +++ panels/midori-bookmarks.c 2013-06-04 17:32:25 +0000 |
226 | @@ -39,7 +39,6 @@ |
227 | struct _MidoriBookmarks |
228 | { |
229 | GtkVBox parent_instance; |
230 | - |
231 | GtkWidget* toolbar; |
232 | GtkWidget* edit; |
233 | GtkWidget* delete; |
234 | @@ -49,6 +48,8 @@ |
235 | |
236 | gint filter_timeout; |
237 | gchar* filter; |
238 | + |
239 | + KatzeItem* hovering_item; |
240 | }; |
241 | |
242 | struct _MidoriBookmarksClass |
243 | @@ -86,6 +87,9 @@ |
244 | GParamSpec* pspec); |
245 | |
246 | static void |
247 | +midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks); |
248 | + |
249 | +static void |
250 | midori_bookmarks_class_init (MidoriBookmarksClass* class) |
251 | { |
252 | GObjectClass* gobject_class; |
253 | @@ -441,6 +445,109 @@ |
254 | gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->edit), selected); |
255 | } |
256 | |
257 | +static gchar* |
258 | +midori_bookmarks_statusbar_bookmarks_str (gint count) |
259 | +{ |
260 | + if (!count) |
261 | + return NULL; |
262 | + |
263 | + /* i18n: [n] bookmark(s) */ |
264 | + return g_strdup_printf (ngettext ("%d bookmark", "%d bookmarks", count), count); |
265 | +} |
266 | + |
267 | +static gchar* |
268 | +midori_bookmarks_statusbar_subfolders_str (gint count) |
269 | +{ |
270 | + if (!count) |
271 | + return NULL; |
272 | + |
273 | + /* i18n: [n] subfolder(s) */ |
274 | + return g_strdup_printf (ngettext ("%d subfolder", "%d subfolders", count), count); |
275 | +} |
276 | + |
277 | +static void |
278 | +midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks) |
279 | +{ |
280 | + gchar* text = NULL; |
281 | + GtkTreeModel* model; |
282 | + GtkTreeIter iter; |
283 | + gboolean selected; |
284 | + |
285 | + if (bookmarks->hovering_item) |
286 | + { |
287 | + KatzeItem* item = bookmarks->hovering_item; |
288 | + |
289 | + g_assert (!KATZE_ITEM_IS_SEPARATOR (item)); |
290 | + |
291 | + if (KATZE_ITEM_IS_FOLDER (item)) |
292 | + { |
293 | + gint child_folders_count = midori_array_count_recursive (bookmarks->array, |
294 | + "uri = ''", NULL, item, FALSE); |
295 | + gint child_bookmarks_count = midori_array_count_recursive (bookmarks->array, |
296 | + "uri <> ''", NULL, item, FALSE); |
297 | + gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count); |
298 | + gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count); |
299 | + |
300 | + if (!child_bookmarks_count && !child_folders_count) |
301 | + /* i18n: Empty folder */ |
302 | + text = g_strdup_printf (_("Empty folder")); |
303 | + else if (!child_bookmarks_count && (child_folders_count >= 1)) |
304 | + /* i18n: Folder containing [[n] folder(s)] and no bookmark */ |
305 | + text = g_strdup_printf (_("Folder containing %s and no bookmark"), |
306 | + child_folders_str); |
307 | + else if ((child_bookmarks_count >= 1) && !child_folders_count) |
308 | + /* i18n: Folder containing [[n] bookmark(s)] */ |
309 | + text = g_strdup_printf (_("Folder containing %s"), child_bookmarks_str); |
310 | + else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1)) |
311 | + /* i18n: Folder containing [[n] bookmark(s)] and [[n] folder(s)] */ |
312 | + text = g_strdup_printf (_("Folder containing %s and %s"), |
313 | + child_bookmarks_str, child_folders_str); |
314 | + |
315 | + g_free (child_folders_str); |
316 | + g_free (child_bookmarks_str); |
317 | + } |
318 | + else if (KATZE_ITEM_IS_BOOKMARK (item)) |
319 | + { |
320 | + const gchar* uri = katze_item_get_uri (item); |
321 | + |
322 | + /* i18n: Bookmark leading to: [bookmark uri] */ |
323 | + text = g_strdup_printf (_("Bookmark leading to: %s"), uri); |
324 | + } |
325 | + } |
326 | + else |
327 | + { |
328 | + gint child_folders_count = midori_array_count_recursive (bookmarks->array, |
329 | + "uri = ''", NULL, NULL, FALSE); |
330 | + gint child_bookmarks_count = midori_array_count_recursive (bookmarks->array, |
331 | + "uri <> ''", NULL, NULL, FALSE); |
332 | + gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count); |
333 | + gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count); |
334 | + |
335 | + if (!child_bookmarks_count && (child_folders_count >= 1)) |
336 | + /* i18n: [[n] folder(s)] and no bookmark */ |
337 | + text = g_strdup_printf (_("%s and no bookmark"), |
338 | + child_folders_str); |
339 | + else if ((child_bookmarks_count >= 1) && !child_folders_count) |
340 | + text = g_strdup (child_bookmarks_str); |
341 | + else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1)) |
342 | + /* i18n: [[n] bookmark(s)] and [[n] folder(s)] */ |
343 | + text = g_strdup_printf (_("%s and %s"), |
344 | + child_bookmarks_str, child_folders_str); |
345 | + |
346 | + g_free (child_folders_str); |
347 | + g_free (child_bookmarks_str); |
348 | + } |
349 | + |
350 | + if (text) |
351 | + { |
352 | + MidoriBrowser* browser = midori_browser_get_for_widget (bookmarks->treeview); |
353 | + |
354 | + g_object_set (browser, "statusbar-text", text, NULL); |
355 | + |
356 | + g_free(text); |
357 | + } |
358 | +} |
359 | + |
360 | gboolean |
361 | midori_bookmarks_update_item_db (sqlite3* db, |
362 | KatzeItem* item) |
363 | @@ -472,7 +579,7 @@ |
364 | if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK) |
365 | { |
366 | updated = FALSE; |
367 | - g_printerr (_("Failed to update bookmark : %s\n"), errmsg); |
368 | + g_printerr (_("Failed to update bookmark: %s\n"), errmsg); |
369 | sqlite3_free (errmsg); |
370 | } |
371 | |
372 | @@ -547,6 +654,7 @@ |
373 | gtk_widget_show (GTK_WIDGET (toolitem)); |
374 | bookmarks->delete = GTK_WIDGET (toolitem); |
375 | midori_bookmarks_toolbar_update (bookmarks); |
376 | + midori_bookmarks_statusbar_update (bookmarks); |
377 | toolitem = gtk_separator_tool_item_new (); |
378 | gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE); |
379 | gtk_tool_item_set_expand (toolitem, TRUE); |
380 | @@ -745,7 +853,10 @@ |
381 | else if (!KATZE_ITEM_IS_FOLDER (item) && strcmp (stock_id, GTK_STOCK_DELETE)) |
382 | gtk_widget_set_sensitive (menuitem, uri != NULL); |
383 | g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item); |
384 | - g_signal_connect (menuitem, "activate", G_CALLBACK (callback), bookmarks); |
385 | + if (callback) |
386 | + g_signal_connect (menuitem, "activate", G_CALLBACK (callback), bookmarks); |
387 | + else |
388 | + gtk_widget_set_sensitive (menuitem, FALSE); |
389 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); |
390 | gtk_widget_show (menuitem); |
391 | } |
392 | @@ -831,9 +942,15 @@ |
393 | |
394 | menu = gtk_menu_new (); |
395 | if (KATZE_ITEM_IS_FOLDER (item)) |
396 | + { |
397 | + gint child_bookmarks_count = midori_array_count_recursive (bookmarks->array, |
398 | + "uri <> ''", NULL, item, FALSE); |
399 | + |
400 | midori_bookmarks_popup_item (menu, |
401 | - STOCK_TAB_NEW, _("Open all in _Tabs"), |
402 | - item, midori_bookmarks_open_in_tab_activate_cb, bookmarks); |
403 | + STOCK_TAB_NEW, _("Open all in _Tabs"), item, |
404 | + (!child_bookmarks_count ? NULL : midori_bookmarks_open_in_tab_activate_cb), |
405 | + bookmarks); |
406 | + } |
407 | else |
408 | { |
409 | midori_bookmarks_popup_item (menu, GTK_STOCK_OPEN, NULL, |
410 | @@ -960,6 +1077,103 @@ |
411 | midori_bookmarks_toolbar_update (bookmarks); |
412 | } |
413 | |
414 | +static KatzeItem* |
415 | +midori_bookmarks_get_item_at_pos (GtkTreeView *treeview, |
416 | + gint x, gint y) |
417 | +{ |
418 | + GtkTreeModel* model = gtk_tree_view_get_model (treeview); |
419 | + GtkTreePath* path; |
420 | + GtkTreeIter iter; |
421 | + KatzeItem* item = NULL; |
422 | + |
423 | + gtk_tree_view_get_path_at_pos (treeview, x, y, |
424 | + &path, NULL, NULL, NULL); |
425 | + |
426 | + if (!path) |
427 | + return NULL; |
428 | + |
429 | + if (gtk_tree_model_get_iter (model, &iter, path)) |
430 | + gtk_tree_model_get (model, &iter, 0, &item, -1); |
431 | + |
432 | + gtk_tree_path_free (path); |
433 | + |
434 | + return item; |
435 | +} |
436 | + |
437 | +static gboolean |
438 | +midori_bookmarks_enter_notify_event_cb (GtkTreeView *treeview, |
439 | + GdkEventCrossing *event, |
440 | + MidoriBookmarks *bookmarks) |
441 | +{ |
442 | + KatzeItem* item = midori_bookmarks_get_item_at_pos (treeview, event->x, event->y); |
443 | + |
444 | + if (bookmarks->hovering_item) |
445 | + g_object_unref (bookmarks->hovering_item); |
446 | + |
447 | + bookmarks->hovering_item = item; |
448 | + |
449 | + midori_bookmarks_statusbar_update (bookmarks); |
450 | + |
451 | + return FALSE; |
452 | +} |
453 | + |
454 | +static gboolean |
455 | +midori_bookmarks_motion_notify_event_cb (GtkTreeView *treeview, |
456 | + GdkEventMotion *event, |
457 | + MidoriBookmarks *bookmarks) |
458 | +{ |
459 | + gboolean item_changed; |
460 | + KatzeItem* item; |
461 | + gint x; |
462 | + gint y; |
463 | + |
464 | + if (event->is_hint) |
465 | + gtk_widget_get_pointer (GTK_WIDGET (treeview), &x, &y); |
466 | + else |
467 | + { |
468 | + x = event->x; |
469 | + y = event->y; |
470 | + } |
471 | + |
472 | + item = midori_bookmarks_get_item_at_pos (treeview, x, y); |
473 | + |
474 | + item_changed = (bookmarks->hovering_item != item) ? TRUE : FALSE; |
475 | + |
476 | + if (!item_changed) |
477 | + { |
478 | + if (item) |
479 | + g_object_unref (item); |
480 | + } |
481 | + else |
482 | + { |
483 | + if (bookmarks->hovering_item) |
484 | + g_object_unref (bookmarks->hovering_item); |
485 | + |
486 | + bookmarks->hovering_item = item; |
487 | + |
488 | + midori_bookmarks_statusbar_update (bookmarks); |
489 | + } |
490 | + |
491 | + return FALSE; |
492 | +} |
493 | + |
494 | +static gboolean |
495 | +midori_bookmarks_leave_notify_event_cb (GtkTreeView *treeview, |
496 | + GdkEventCrossing *event, |
497 | + MidoriBookmarks *bookmarks) |
498 | +{ |
499 | + MidoriBrowser* browser = midori_browser_get_for_widget (bookmarks->treeview); |
500 | + |
501 | + if (bookmarks->hovering_item) |
502 | + g_object_unref (bookmarks->hovering_item); |
503 | + |
504 | + bookmarks->hovering_item = NULL; |
505 | + |
506 | + g_object_set (browser, "statusbar-text", "", NULL); |
507 | + |
508 | + return FALSE; |
509 | +} |
510 | + |
511 | static gboolean |
512 | midori_bookmarks_filter_timeout_cb (gpointer data) |
513 | { |
514 | @@ -1047,7 +1261,17 @@ |
515 | midori_bookmarks_row_expanded_cb, bookmarks, |
516 | "signal::row-collapsed", |
517 | midori_bookmarks_row_collapsed_cb, bookmarks, |
518 | + "signal::enter-notify-event", |
519 | + midori_bookmarks_enter_notify_event_cb, bookmarks, |
520 | + "signal::motion-notify-event", |
521 | + midori_bookmarks_motion_notify_event_cb, bookmarks, |
522 | + "signal::leave-notify-event", |
523 | + midori_bookmarks_leave_notify_event_cb, bookmarks, |
524 | NULL); |
525 | + gtk_widget_add_events (GTK_WIDGET (treeview), |
526 | + GDK_POINTER_MOTION_MASK |
527 | + | GDK_POINTER_MOTION_HINT_MASK); |
528 | + |
529 | selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); |
530 | g_signal_connect_after (selection, "changed", |
531 | G_CALLBACK (midori_bookmarks_selection_changed_cb), |
532 | @@ -1055,6 +1279,7 @@ |
533 | gtk_widget_show (treeview); |
534 | gtk_box_pack_start (GTK_BOX (bookmarks), treeview, TRUE, TRUE, 0); |
535 | bookmarks->treeview = treeview; |
536 | + bookmarks->hovering_item = NULL; |
537 | } |
538 | |
539 | static void |
540 | @@ -1064,5 +1289,6 @@ |
541 | |
542 | if (bookmarks->app) |
543 | g_object_unref (bookmarks->app); |
544 | + if (bookmarks->hovering_item) |
545 | + g_object_unref (bookmarks->hovering_item); |
546 | } |
547 | - |
385 + else if (!child_ bookmarks_ count && child_folders_ count) count);
386 + text = g_strdup_printf(
387 + _("%s : folder, %d subfolders and no bookmark"),
388 + name, child_folders_
This should be done using ngettext, leaving gettext to figure out plural forms (there may be a dual form or other grammatical implications the code can't handle).
Is it necessary to implement midori_ array_count_ recursive using midori_ array_query_ recursive rather than asking SQlite to count rows? This seems a bit wasteful.