Merge lp:~junrrein/pantheon-files/progressuihandler-to-vala into lp:~elementary-apps/pantheon-files/trunk
- progressuihandler-to-vala
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | David Gomes |
Approved revision: | 1350 |
Merged at revision: | 1302 |
Proposed branch: | lp:~junrrein/pantheon-files/progressuihandler-to-vala |
Merge into: | lp:~elementary-apps/pantheon-files/trunk |
Prerequisite: | lp:~junrrein/pantheon-files/unity-quicklist-to-vala |
Diff against target: |
1313 lines (+444/-773) 8 files modified
libcore/marlincore-C.vapi (+23/-0) src/Application.vala (+1/-1) src/CMakeLists.txt (+2/-1) src/ProgressUIHandler.vala (+413/-0) src/QuicklistHandler.vala (+1/-9) src/marlin-progress-ui-handler.c (+0/-691) src/marlin-progress-ui-handler.h (+0/-64) src/marlin.vapi (+4/-7) |
To merge this branch: | bzr merge lp:~junrrein/pantheon-files/progressuihandler-to-vala |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
David Gomes (community) | Approve | ||
Cody Garver (community) | Approve | ||
Review via email: mp+179622@code.launchpad.net |
Commit message
Port marlin-
Description of the change
Port marlin-
What needs to be tested is basically the notification policy for in-progress files operations. Taken from the code:
/* Our policy for showing progress notification is the following:
* - File operations that end within two seconds do not get notified in any way.
* - If no file operations are running, and one passes the two seconds
* timeout, a window is displayed with the progress.
* - If the window is closed, we show a resident notification, or a status icon, depending on
* the capabilities of the notification daemon running in the session.
* - If some file operations are running, and another one passes the two seconds
* timeout, and the window is showing, we add it to the window directly.
* - In the same case, but when the window is not showing, we update the resident
* notification, changing its message, or the status icon's tooltip.
* - When one file operation finishes, if it's not the last one, we only update the
* resident notification's message, or the status icon's tooltip.
* - In the same case, if it's the last one, we close the resident notification,
* or the status icon, and trigger a transient one.
* - In the same case, but the window was showing, we just hide the window.
*/
David Gomes (davidgomes) wrote : | # |
Newline after 360, 381, 431, 441. I'll also be testing this and the other branches under Unity of course.
David Gomes (davidgomes) wrote : | # |
>/home/
compilation terminated.
Doesn't compile for me on Ubuntu 13.04.
David Gomes (davidgomes) wrote : | # |
Actually, disregard that last comment it was meant to be posted here - https:/
This branch compiles and runs just fine. I didn't test *everything* but side. Unity displayed the progress of long file operations just fine and there were no bugs regarding that so I'm approving this test-wise. Now all that needs to be done are the code style fixes and it'll be ready to merge.
David Gomes (davidgomes) wrote : | # |
It also properly fixes bug 1208994.
- 1346. By Julián Unrrein
-
Merge from parent branch.
- 1347. By Julián Unrrein
-
Improve code style.
Julián Unrrein (junrrein) wrote : | # |
Applied code style suggestions.
See diff lines 266-267. It's the same question I asked in my other branch. Is the list being properly freed?
- 1348. By Julián Unrrein
-
Remove unneeded methods from QuicklistHandle
r.vala. - 1349. By Julián Unrrein
-
Remove redundant ternary operation.
- 1350. By Julián Unrrein
-
Remove TODO comment.
Julián Unrrein (junrrein) wrote : | # |
Freeing the list explicitly is not necessary - Vala frees it automatically when it is pointed to null.
Preview Diff
1 | === modified file 'libcore/marlincore-C.vapi' |
2 | --- libcore/marlincore-C.vapi 2013-08-06 20:20:44 +0000 |
3 | +++ libcore/marlincore-C.vapi 2013-08-16 22:51:52 +0000 |
4 | @@ -106,6 +106,29 @@ |
5 | public void undo (UndoFinishCallback? cb); |
6 | public void redo (UndoFinishCallback? cb); |
7 | } |
8 | + |
9 | + [CCode (cheader_filename = "marlin-progress-info.h")] |
10 | + public class Progress.Info : Object { |
11 | + public Info (); |
12 | + public signal void started (); |
13 | + public signal void finished (); |
14 | + public signal void progress_changed (); |
15 | + public void cancel (); |
16 | + public double get_progress (); |
17 | + public double get_current (); |
18 | + public double get_total (); |
19 | + public bool get_is_finished (); |
20 | + public bool get_is_paused (); |
21 | + public Cancellable get_cancellable (); |
22 | + } |
23 | + |
24 | + [CCode (cheader_filename = "marlin-progress-info-manager.h")] |
25 | + public class Progress.InfoManager : Object { |
26 | + public InfoManager (); |
27 | + public signal void new_progress_info (Progress.Info info); |
28 | + public void add_new_info (Progress.Info info); |
29 | + public unowned List<Progress.Info> get_all_infos (); |
30 | + } |
31 | } |
32 | |
33 | [CCode (cprefix = "MarlinFile", lower_case_cprefix = "marlin_file_", cheader_filename = "marlin-file-changes-queue.h")] |
34 | |
35 | === modified file 'src/Application.vala' |
36 | --- src/Application.vala 2013-08-16 22:51:52 +0000 |
37 | +++ src/Application.vala 2013-08-16 22:51:52 +0000 |
38 | @@ -41,7 +41,7 @@ |
39 | application_singleton = this; |
40 | } |
41 | |
42 | - public static new Application get () { |
43 | + public static new unowned Application get () { |
44 | if (application_singleton == null) |
45 | application_singleton = new Marlin.Application (); |
46 | |
47 | |
48 | === modified file 'src/CMakeLists.txt' |
49 | --- src/CMakeLists.txt 2013-08-16 22:51:52 +0000 |
50 | +++ src/CMakeLists.txt 2013-08-16 22:51:52 +0000 |
51 | @@ -42,6 +42,7 @@ |
52 | Application.vala |
53 | main.vala |
54 | marlin-deep-count.vala |
55 | + ProgressUIHandler.vala |
56 | QuicklistHandler.vala |
57 | View/DiskRenderer.vala |
58 | View/DirectoryNotFound.vala |
59 | @@ -86,6 +87,7 @@ |
60 | Application.vala |
61 | main.vala |
62 | marlin-deep-count.vala |
63 | + ProgressUIHandler.vala |
64 | View/DiskRenderer.vala |
65 | View/DirectoryNotFound.vala |
66 | View/Window.vala |
67 | @@ -148,7 +150,6 @@ |
68 | fm-columns-view.c |
69 | marlin-connect-server-dialog.c |
70 | marlin-connect-server-operation.c |
71 | - marlin-progress-ui-handler.c |
72 | marlin-progress-info-widget.c |
73 | ${VALA_C} ) |
74 | |
75 | |
76 | === added file 'src/ProgressUIHandler.vala' |
77 | --- src/ProgressUIHandler.vala 1970-01-01 00:00:00 +0000 |
78 | +++ src/ProgressUIHandler.vala 2013-08-16 22:51:52 +0000 |
79 | @@ -0,0 +1,413 @@ |
80 | +/*** |
81 | + Copyright (C) 2007, 2011 Red Hat, Inc. |
82 | + Copyright (C) 2013 Julián Unrrein <junrrein@gmail.com> |
83 | + |
84 | + This program is free software: you can redistribute it and/or modify it |
85 | + under the terms of the GNU Lesser General Public License version 3, as published |
86 | + by the Free Software Foundation. |
87 | + |
88 | + This program is distributed in the hope that it will be useful, but |
89 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
90 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
91 | + PURPOSE. See the GNU General Public License for more details. |
92 | + |
93 | + You should have received a copy of the GNU General Public License along |
94 | + with this program. If not, see <http://www.gnu.org/licenses/>. |
95 | + |
96 | + Authors: Alexander Larsson <alexl@redhat.com> |
97 | + Cosimo Cecchi <cosimoc@redhat.com> |
98 | + Julián Unrrein <junrrein@gmail.com> |
99 | +***/ |
100 | + |
101 | +public class Marlin.Progress.UIHandler : Object { |
102 | + |
103 | + private Marlin.Progress.InfoManager manager = null; |
104 | + |
105 | + private Gtk.Widget progress_window = null; |
106 | + private Gtk.Widget window_vbox = null; |
107 | + private uint active_infos = 0; |
108 | + |
109 | + private bool notification_supports_persistence = false; |
110 | + private Notify.Notification progress_notification = null; |
111 | + private Gtk.StatusIcon status_icon = null; |
112 | +#if HAVE_UNITY |
113 | + private Marlin.QuicklistHandler quicklist_handler = null; |
114 | +#endif |
115 | + |
116 | + private const string ACTION_DETAILS = "details"; |
117 | + |
118 | + /* Our policy for showing progress notification is the following: |
119 | + * - File operations that end within two seconds do not get notified in any way. |
120 | + * - If no file operations are running, and one passes the two seconds |
121 | + * timeout, a window is displayed with the progress. |
122 | + * - If the window is closed, we show a resident notification, or a status icon, depending on |
123 | + * the capabilities of the notification daemon running in the session. |
124 | + * - If some file operations are running, and another one passes the two seconds |
125 | + * timeout, and the window is showing, we add it to the window directly. |
126 | + * - In the same case, but when the window is not showing, we update the resident |
127 | + * notification, changing its message, or the status icon's tooltip. |
128 | + * - When one file operation finishes, if it's not the last one, we only update the |
129 | + * resident notification's message, or the status icon's tooltip. |
130 | + * - In the same case, if it's the last one, we close the resident notification, |
131 | + * or the status icon, and trigger a transient one. |
132 | + * - In the same case, but the window was showing, we just hide the window. |
133 | + */ |
134 | + |
135 | + public UIHandler () { |
136 | + this.manager = new Marlin.Progress.InfoManager (); |
137 | + |
138 | + manager.new_progress_info.connect ((info) => { |
139 | + info.started.connect (progress_info_started_cb); |
140 | + }); |
141 | + |
142 | + this.notification_supports_persistence = server_has_persistence (); |
143 | + } |
144 | + |
145 | + private bool server_has_persistence () { |
146 | + unowned List<string> cappabilities = Notify.get_server_caps (); |
147 | + |
148 | + return cappabilities.find ("persistence") != null; |
149 | + } |
150 | + |
151 | + private void progress_info_started_cb (Marlin.Progress.Info info) { |
152 | + var application = Marlin.Application.get (); |
153 | + application.hold (); |
154 | + |
155 | + info.finished.connect (() => { |
156 | + debug ("Release application"); |
157 | + application.release (); |
158 | + }); |
159 | + |
160 | + Timeout.add_seconds (2, () => { |
161 | + if (info.get_is_paused ()) |
162 | + return true; |
163 | + |
164 | + if (!info.get_is_finished ()) |
165 | + handle_new_progress_info (info); |
166 | + |
167 | + return false; |
168 | + }); |
169 | + } |
170 | + |
171 | + private void handle_new_progress_info (Marlin.Progress.Info info) { |
172 | + info.finished.connect (progress_info_finished_cb); |
173 | + |
174 | + this.active_infos++; |
175 | + |
176 | + if (this.active_infos == 1) { |
177 | + /* This is the only active operation, present the window */ |
178 | + add_to_window (info); |
179 | + (this.progress_window as Gtk.Window).present (); |
180 | + } else { |
181 | + if (this.progress_window.visible) |
182 | + add_to_window (info); |
183 | + else |
184 | + update_notification_or_status (); |
185 | + } |
186 | + |
187 | +#if HAVE_UNITY |
188 | + update_unity_launcher (info, true); |
189 | +#endif |
190 | + } |
191 | + |
192 | + private void add_to_window (Marlin.Progress.Info info) { |
193 | + ensure_window (); |
194 | + |
195 | + var progress_widget = new Marlin.Progress.InfoWidget (info); |
196 | + (this.window_vbox as Gtk.Box).pack_start (progress_widget, false, false, 6); |
197 | + |
198 | + progress_widget.show (); |
199 | + if (this.progress_window.visible) |
200 | + (this.progress_window as Gtk.Window).present (); |
201 | + } |
202 | + |
203 | + private void ensure_window () { |
204 | + if (this.progress_window != null) |
205 | + return; |
206 | + |
207 | + this.progress_window = new Gtk.Window (Gtk.WindowType.TOPLEVEL); |
208 | + |
209 | + (this.progress_window as Gtk.Window).resizable = false; |
210 | + (this.progress_window as Gtk.Container).set_border_width (10); |
211 | + (this.progress_window as Gtk.Window).title = _("File Operations"); |
212 | + (this.progress_window as Gtk.Window).set_wmclass ("file_progress", "Marlin"); |
213 | + (this.progress_window as Gtk.Window).set_position (Gtk.WindowPosition.CENTER); |
214 | + (this.progress_window as Gtk.Window).icon_name = "system-file-manager"; |
215 | + |
216 | + this.window_vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 5); |
217 | + |
218 | + (this.progress_window as Gtk.Container).add (this.window_vbox); |
219 | + this.window_vbox.show (); |
220 | + |
221 | + this.progress_window.delete_event.connect ((widget, event) => { |
222 | + widget.hide (); |
223 | + update_notification_or_status (); |
224 | + return true; |
225 | + }); |
226 | + } |
227 | + |
228 | + private void update_notification_or_status () { |
229 | + if (this.notification_supports_persistence) |
230 | + update_notification (); |
231 | + else |
232 | + update_status_icon (); |
233 | + } |
234 | + |
235 | + private void progress_info_finished_cb (Marlin.Progress.Info info) { |
236 | + this.active_infos--; |
237 | + |
238 | + if (this.active_infos > 0) { |
239 | + if (!this.progress_window.visible) |
240 | + update_notification_or_status (); |
241 | + } else { |
242 | + if (this.progress_window.visible) { |
243 | + progress_window.hide (); |
244 | + } else { |
245 | + hide_notification_or_status (); |
246 | + show_complete_notification (); |
247 | + } |
248 | + } |
249 | + |
250 | +#if HAVE_UNITY |
251 | + update_unity_launcher (info, false); |
252 | +#endif |
253 | + } |
254 | + |
255 | + private void hide_notification_or_status () { |
256 | + if (this.status_icon != null) |
257 | + this.status_icon.visible = false; |
258 | + |
259 | + if (this.progress_notification != null) { |
260 | + try { |
261 | + this.progress_notification.close (); |
262 | + } catch (Error error) { |
263 | + warning ("There was an error when showing the notification: %s", error.message); |
264 | + } |
265 | + |
266 | + this.progress_notification = null; |
267 | + } |
268 | + } |
269 | + |
270 | + private void show_complete_notification () { |
271 | + /* Don't display the notification if we'd be using a status icon */ |
272 | + if (!this.notification_supports_persistence) |
273 | + return; |
274 | + |
275 | + var complete_notification = new Notify.Notification (_("File Operations"), |
276 | + _("All file operations have been successfully completed"), |
277 | + null); |
278 | + try { |
279 | + complete_notification.show (); |
280 | + } catch (Error error) { |
281 | + warning ("There was an error when showing the notification: %s", error.message); |
282 | + } |
283 | + } |
284 | + |
285 | + private void update_notification () { |
286 | + ensure_notification (); |
287 | + |
288 | + string body = ngettext ("%'d file operation active", |
289 | + "%'d file operations active", |
290 | + this.active_infos); |
291 | + |
292 | + this.progress_notification.update (_("File Operations"), |
293 | + body, ""); |
294 | + |
295 | + try { |
296 | + this.progress_notification.show (); |
297 | + } catch (Error error) { |
298 | + warning ("There was an error when showing the notification: %s", error.message); |
299 | + } |
300 | + } |
301 | + |
302 | + private void ensure_notification () { |
303 | + if (this.progress_notification != null) |
304 | + return; |
305 | + |
306 | + this.progress_notification = new Notify.Notification (_("File Operations"), |
307 | + null, null); |
308 | + |
309 | + this.progress_notification.set_category ("transfer"); |
310 | + this.progress_notification.set_hint ("resident", new Variant.boolean (true)); |
311 | + this.progress_notification.add_action (ACTION_DETAILS, |
312 | + _("Show Details"), |
313 | + (Notify.ActionCallback) notification_show_details_cb); |
314 | + } |
315 | + |
316 | + private void notification_show_details_cb (Notify.Notification notification, |
317 | + string action_name) { |
318 | + if (action_name != ACTION_DETAILS) |
319 | + return; |
320 | + |
321 | + try { |
322 | + progress_notification.close (); |
323 | + } catch (Error error) { |
324 | + warning ("There was an error when closing the notification: %s", error.message); |
325 | + } |
326 | + |
327 | + (progress_window as Gtk.Window).present (); |
328 | + } |
329 | + |
330 | + private void update_status_icon () { |
331 | + ensure_status_icon (); |
332 | + |
333 | + string tooltip = ngettext ("%'d file operation active", |
334 | + "%'d file operations active", |
335 | + this.active_infos); |
336 | + |
337 | + this.status_icon.set_tooltip_text (tooltip); |
338 | + |
339 | + this.status_icon.visible = true; |
340 | + } |
341 | + |
342 | + private void ensure_status_icon () { |
343 | + if (this.status_icon != null) |
344 | + return; |
345 | + |
346 | + var icon = new ThemedIcon.with_default_fallbacks ("system-file-manager-symbolic"); |
347 | + this.status_icon = new Gtk.StatusIcon.from_gicon (icon); |
348 | + |
349 | + this.status_icon.activate.connect (() => { |
350 | + this.status_icon.visible = false; |
351 | + (this.progress_window as Gtk.Window).present (); |
352 | + }); |
353 | + |
354 | + this.status_icon.visible = false; |
355 | + } |
356 | + |
357 | +#if HAVE_UNITY |
358 | + private void update_unity_launcher (Marlin.Progress.Info info, |
359 | + bool added) { |
360 | + |
361 | + if (this.quicklist_handler == null) { |
362 | + this.quicklist_handler = QuicklistHandler.get_singleton (); |
363 | + |
364 | + if (this.quicklist_handler == null) |
365 | + return; |
366 | + |
367 | + build_unity_quicklist (); |
368 | + } |
369 | + |
370 | + foreach (var marlin_lentry in this.quicklist_handler.launcher_entries) |
371 | + update_unity_launcher_entry (info, marlin_lentry); |
372 | + |
373 | + if (added) |
374 | + info.progress_changed.connect (unity_progress_changed); |
375 | + } |
376 | + |
377 | + private void build_unity_quicklist () { |
378 | + /* Create menu items for the quicklist */ |
379 | + foreach (var marlin_lentry in this.quicklist_handler.launcher_entries) { |
380 | + /* Separator between bookmarks and progress items */ |
381 | + var separator = new Dbusmenu.Menuitem (); |
382 | + |
383 | + separator.property_set (Dbusmenu.MENUITEM_PROP_TYPE, |
384 | + Dbusmenu.CLIENT_TYPES_SEPARATOR); |
385 | + separator.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
386 | + "Progress items separator"); |
387 | + marlin_lentry.progress_quicklists.append (separator); |
388 | + |
389 | + /* "Show progress window" menu item */ |
390 | + var show_menuitem = new Dbusmenu.Menuitem (); |
391 | + |
392 | + show_menuitem.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
393 | + _("Show Copy Dialog")); |
394 | + |
395 | + show_menuitem.item_activated.connect (() => { |
396 | + (this.progress_window as Gtk.Window).present (); |
397 | + }); |
398 | + |
399 | + marlin_lentry.progress_quicklists.append (show_menuitem); |
400 | + |
401 | + /* "Cancel in-progress operations" menu item */ |
402 | + var cancel_menuitem = new Dbusmenu.Menuitem (); |
403 | + |
404 | + cancel_menuitem.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
405 | + _("Cancel All In-progress Actions")); |
406 | + |
407 | + cancel_menuitem.item_activated.connect (() => { |
408 | + unowned List<Marlin.Progress.Info> infos = this.manager.get_all_infos (); |
409 | + |
410 | + foreach (var info in infos) |
411 | + info.cancel (); |
412 | + }); |
413 | + |
414 | + marlin_lentry.progress_quicklists.append (cancel_menuitem); |
415 | + } |
416 | + } |
417 | + |
418 | + private void update_unity_launcher_entry (Marlin.Progress.Info info, |
419 | + Marlin.LauncherEntry marlin_lentry) { |
420 | + Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
421 | + |
422 | + if (this.active_infos > 0) { |
423 | + unity_lentry.progress_visible = true; |
424 | + unity_progress_changed (); |
425 | + show_unity_quicklist (marlin_lentry, true); |
426 | + } else { |
427 | + unity_lentry.progress_visible = false; |
428 | + unity_lentry.progress = 0.0; |
429 | + show_unity_quicklist (marlin_lentry, false); |
430 | + |
431 | + Cancellable pc = info.get_cancellable (); |
432 | + |
433 | + if (!pc.is_cancelled ()) { |
434 | + unity_lentry.urgent = true; |
435 | + |
436 | + Timeout.add_seconds (2, () => { |
437 | + unity_lentry.urgent = false; |
438 | + return false; |
439 | + }); |
440 | + } |
441 | + } |
442 | + } |
443 | + |
444 | + private void show_unity_quicklist (Marlin.LauncherEntry marlin_lentry, |
445 | + bool show) { |
446 | + |
447 | + Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
448 | + Dbusmenu.Menuitem quicklist = unity_lentry.quicklist; |
449 | + |
450 | + foreach (Dbusmenu.Menuitem menuitem in marlin_lentry.progress_quicklists) { |
451 | + if (show) { |
452 | + if (menuitem.get_parent () == null) |
453 | + quicklist.child_add_position (menuitem, -1); |
454 | + } else { |
455 | + quicklist.child_delete (menuitem); |
456 | + } |
457 | + } |
458 | + } |
459 | + |
460 | + private void unity_progress_changed () { |
461 | + double progress = 0; |
462 | + double current = 0; |
463 | + double total = 0; |
464 | + unowned List<Marlin.Progress.Info> infos = this.manager.get_all_infos (); |
465 | + |
466 | + foreach (var _info in infos) { |
467 | + double c = _info.get_current (); |
468 | + double t = _info.get_total (); |
469 | + |
470 | + if (c < 0) |
471 | + c = 0; |
472 | + |
473 | + if (t <= 0) |
474 | + continue; |
475 | + |
476 | + current += c; |
477 | + total += t; |
478 | + } |
479 | + |
480 | + if (current >= 0 && total > 0) |
481 | + progress = current / total; |
482 | + |
483 | + if (progress > 1.0) |
484 | + progress = 1.0; |
485 | + |
486 | + foreach (Marlin.LauncherEntry marlin_lentry in this.quicklist_handler.launcher_entries) { |
487 | + Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
488 | + unity_lentry.progress = progress; |
489 | + } |
490 | + } |
491 | +#endif |
492 | +} |
493 | |
494 | === modified file 'src/QuicklistHandler.vala' |
495 | --- src/QuicklistHandler.vala 2013-08-16 22:51:52 +0000 |
496 | +++ src/QuicklistHandler.vala 2013-08-16 22:51:52 +0000 |
497 | @@ -27,7 +27,7 @@ |
498 | |
499 | public class QuicklistHandler : Object { |
500 | |
501 | - private List<Marlin.LauncherEntry> launcher_entries = null; |
502 | + public List<Marlin.LauncherEntry> launcher_entries = null; |
503 | |
504 | private QuicklistHandler () { |
505 | this.entry_add ("pantheon-files.desktop"); |
506 | @@ -52,14 +52,6 @@ |
507 | return quicklisthandler_singleton; |
508 | } |
509 | |
510 | - public unowned List<Marlin.LauncherEntry> get_launcher_entries () { |
511 | - return this.launcher_entries; |
512 | - } |
513 | - |
514 | - public static Unity.LauncherEntry get_launcher_entry (List<Marlin.LauncherEntry> list) { |
515 | - return list.data.entry; |
516 | - } |
517 | - |
518 | private void entry_add (string entry_id) { |
519 | var unity_lentry = Unity.LauncherEntry.get_for_desktop_id (entry_id); |
520 | |
521 | |
522 | === removed file 'src/marlin-progress-ui-handler.c' |
523 | --- src/marlin-progress-ui-handler.c 2013-08-16 22:51:52 +0000 |
524 | +++ src/marlin-progress-ui-handler.c 1970-01-01 00:00:00 +0000 |
525 | @@ -1,691 +0,0 @@ |
526 | -/* |
527 | - * marlin-progress-ui-handler.c: file operation progress user interface. |
528 | - * |
529 | - * Copyright (C) 2007, 2011 Red Hat, Inc. |
530 | - * |
531 | - * This program is free software; you can redistribute it and/or |
532 | - * modify it under the terms of the GNU General Public License as |
533 | - * published by the Free Software Foundation; either version 2 of the |
534 | - * License, or (at your option) any later version. |
535 | - * |
536 | - * This program is distributed in the hope that it will be useful, |
537 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
538 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
539 | - * General Public License for more details. |
540 | - * |
541 | - * You should have received a copy of the GNU General Public |
542 | - * License along with this program; if not, write to the |
543 | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
544 | - * Boston, MA 02111-1307, USA. |
545 | - * |
546 | - * Authors: Alexander Larsson <alexl@redhat.com> |
547 | - * Cosimo Cecchi <cosimoc@redhat.com> |
548 | - * Marco Trevisan <3v1n0@ubuntu.com> |
549 | - * |
550 | - */ |
551 | - |
552 | -#include "marlin-progress-ui-handler.h" |
553 | - |
554 | -#include "marlin-vala.h" |
555 | -#include "marlin-progress-info-widget.h" |
556 | - |
557 | -#include "marlin-progress-info.h" |
558 | -#include "marlin-progress-info-manager.h" |
559 | -#include "eel-i18n.h" |
560 | - |
561 | -#include <libnotify/notify.h> |
562 | - |
563 | -#ifdef HAVE_UNITY |
564 | -#include <unity.h> |
565 | -#endif |
566 | - |
567 | -struct _MarlinProgressUIHandlerPriv { |
568 | - MarlinProgressInfoManager *manager; |
569 | - |
570 | - GtkWidget *progress_window; |
571 | - GtkWidget *window_vbox; |
572 | - guint active_infos; |
573 | - |
574 | - gboolean notification_supports_persistence; |
575 | - NotifyNotification *progress_notification; |
576 | - GtkStatusIcon *status_icon; |
577 | -#ifdef HAVE_UNITY |
578 | - MarlinQuicklistHandler *unity_quicklist_handler; |
579 | -#endif |
580 | -}; |
581 | - |
582 | -G_DEFINE_TYPE (MarlinProgressUIHandler, marlin_progress_ui_handler, G_TYPE_OBJECT); |
583 | - |
584 | -/* Our policy for showing progress notification is the following: |
585 | - * - file operations that end within two seconds do not get notified in any way |
586 | - * - if no file operations are running, and one passes the two seconds |
587 | - * timeout, a window is displayed with the progress |
588 | - * - if the window is closed, we show a resident notification, or a status icon, depending on |
589 | - * the capabilities of the notification daemon running in the session |
590 | - * - if some file operations are running, and another one passes the two seconds |
591 | - * timeout, and the window is showing, we add it to the window directly |
592 | - * - in the same case, but when the window is not showing, we update the resident |
593 | - * notification, changing its message, or the status icon's tooltip |
594 | - * - when one file operation finishes, if it's not the last one, we only update the |
595 | - * resident notification's message, or the status icon's tooltip |
596 | - * - in the same case, if it's the last one, we close the resident notification, |
597 | - * or the status icon, and trigger a transient one |
598 | - * - in the same case, but the window was showing, we just hide the window |
599 | - */ |
600 | - |
601 | -#define ACTION_DETAILS "details" |
602 | - |
603 | -static void |
604 | -status_icon_activate_cb (GtkStatusIcon *icon, |
605 | - MarlinProgressUIHandler *self) |
606 | -{ |
607 | - gtk_status_icon_set_visible (icon, FALSE); |
608 | - gtk_window_present (GTK_WINDOW (self->priv->progress_window)); |
609 | -} |
610 | - |
611 | -static void |
612 | -notification_show_details_cb (NotifyNotification *notification, |
613 | - char *action_name, |
614 | - gpointer user_data) |
615 | -{ |
616 | - MarlinProgressUIHandler *self = user_data; |
617 | - |
618 | - |
619 | - if (g_strcmp0 (action_name, ACTION_DETAILS) != 0) { |
620 | - return; |
621 | - } |
622 | - |
623 | - notify_notification_close (self->priv->progress_notification, NULL); |
624 | - gtk_window_present (GTK_WINDOW (self->priv->progress_window)); |
625 | -} |
626 | - |
627 | -static void |
628 | -progress_ui_handler_ensure_notification (MarlinProgressUIHandler *self) |
629 | -{ |
630 | - NotifyNotification *notify; |
631 | - |
632 | - if (self->priv->progress_notification) { |
633 | - return; |
634 | - } |
635 | - |
636 | - notify = notify_notification_new (_("File Operations"), |
637 | - NULL, NULL); |
638 | - self->priv->progress_notification = notify; |
639 | - |
640 | - notify_notification_set_category (notify, "transfer"); |
641 | - notify_notification_set_hint (notify, "resident", |
642 | - g_variant_new_boolean (TRUE)); |
643 | - |
644 | - notify_notification_add_action (notify, ACTION_DETAILS, |
645 | - _("Show Details"), |
646 | - notification_show_details_cb, |
647 | - self, |
648 | - NULL); |
649 | -} |
650 | - |
651 | -static void |
652 | -progress_ui_handler_ensure_status_icon (MarlinProgressUIHandler *self) |
653 | -{ |
654 | - GIcon *icon; |
655 | - GtkStatusIcon *status_icon; |
656 | - |
657 | - if (self->priv->status_icon != NULL) { |
658 | - return; |
659 | - } |
660 | - |
661 | - icon = g_themed_icon_new_with_default_fallbacks ("system-file-manager-symbolic"); |
662 | - status_icon = gtk_status_icon_new_from_gicon (icon); |
663 | - g_signal_connect (status_icon, "activate", |
664 | - (GCallback) status_icon_activate_cb, |
665 | - self); |
666 | - |
667 | - gtk_status_icon_set_visible (status_icon, FALSE); |
668 | - g_object_unref (icon); |
669 | - |
670 | - self->priv->status_icon = status_icon; |
671 | -} |
672 | - |
673 | -static void |
674 | -progress_ui_handler_update_notification (MarlinProgressUIHandler *self) |
675 | -{ |
676 | - gchar *body; |
677 | - |
678 | - progress_ui_handler_ensure_notification (self); |
679 | - |
680 | - body = g_strdup_printf (ngettext ("%'d file operation active", |
681 | - "%'d file operations active", |
682 | - self->priv->active_infos), |
683 | - self->priv->active_infos); |
684 | - |
685 | - notify_notification_update (self->priv->progress_notification, |
686 | - _("File Operations"), |
687 | - body, |
688 | - NULL); |
689 | - |
690 | - notify_notification_show (self->priv->progress_notification, NULL); |
691 | - |
692 | - g_free (body); |
693 | -} |
694 | - |
695 | -static void |
696 | -progress_ui_handler_update_status_icon (MarlinProgressUIHandler *self) |
697 | -{ |
698 | - gchar *tooltip; |
699 | - |
700 | - progress_ui_handler_ensure_status_icon (self); |
701 | - |
702 | - tooltip = g_strdup_printf (ngettext ("%'d file operation active", |
703 | - "%'d file operations active", |
704 | - self->priv->active_infos), |
705 | - self->priv->active_infos); |
706 | - gtk_status_icon_set_tooltip_text (self->priv->status_icon, tooltip); |
707 | - g_free (tooltip); |
708 | - |
709 | - gtk_status_icon_set_visible (self->priv->status_icon, TRUE); |
710 | -} |
711 | - |
712 | -#ifdef HAVE_UNITY |
713 | - |
714 | -static void |
715 | -progress_ui_handler_unity_progress_changed (MarlinProgressInfo *info, |
716 | - MarlinProgressUIHandler *self) |
717 | -{ |
718 | - g_return_if_fail (self); |
719 | - g_return_if_fail (self->priv->unity_quicklist_handler); |
720 | - g_return_if_fail (self->priv->manager); |
721 | - |
722 | - GList *infos, *l; |
723 | - double progress = 0; |
724 | - double c, current = 0; |
725 | - double t, total = 0; |
726 | - |
727 | - infos = marlin_progress_info_manager_get_all_infos (self->priv->manager); |
728 | - |
729 | - for (l = infos; l; l = l->next) { |
730 | - MarlinProgressInfo *i = l->data; |
731 | - c = marlin_progress_info_get_current (i); |
732 | - t = marlin_progress_info_get_total (i); |
733 | - |
734 | - if (c < 0) c = 0; |
735 | - if (t <= 0) continue; |
736 | - |
737 | - total += t; |
738 | - current += c; |
739 | - } |
740 | - |
741 | - if (current >= 0 && total > 0) |
742 | - progress = current / total; |
743 | - |
744 | - if (progress > 1.0) |
745 | - progress = 1.0; |
746 | - |
747 | - for (l = marlin_quicklist_handler_get_launcher_entries (self->priv->unity_quicklist_handler); l; l = l->next) { |
748 | - UnityLauncherEntry *entry = marlin_quicklist_handler_get_launcher_entry (l); |
749 | - unity_launcher_entry_set_progress (entry, progress); |
750 | - } |
751 | -} |
752 | - |
753 | -static gboolean |
754 | -progress_ui_handler_disable_unity_urgency (UnityLauncherEntry *entry) |
755 | -{ |
756 | - g_return_if_fail (entry); |
757 | - |
758 | - unity_launcher_entry_set_urgent (entry, FALSE); |
759 | - return FALSE; |
760 | -} |
761 | - |
762 | -static void |
763 | -progress_ui_handler_unity_quicklist_show_activated (DbusmenuMenuitem *menu, |
764 | - guint timestamp, |
765 | - MarlinProgressUIHandler *self) |
766 | -{ |
767 | - g_return_if_fail (self); |
768 | - |
769 | - if (!gtk_widget_get_visible (self->priv->progress_window)) { |
770 | - gtk_window_present (GTK_WINDOW (self->priv->progress_window)); |
771 | - } else { |
772 | - gtk_window_set_keep_above (GTK_WINDOW (self->priv->progress_window), TRUE); |
773 | - gtk_window_set_keep_above (GTK_WINDOW (self->priv->progress_window), FALSE); |
774 | - } |
775 | -} |
776 | - |
777 | -static void |
778 | -progress_ui_handler_unity_quicklist_cancel_activated (DbusmenuMenuitem *menu, |
779 | - guint timestamp, |
780 | - MarlinProgressUIHandler *self) |
781 | -{ |
782 | - g_return_if_fail (self); |
783 | - g_return_if_fail (self->priv->manager); |
784 | - |
785 | - GList *infos, *l; |
786 | - infos = marlin_progress_info_manager_get_all_infos (self->priv->manager); |
787 | - |
788 | - for (l = infos; l; l = l->next) { |
789 | - MarlinProgressInfo *info = l->data; |
790 | - marlin_progress_info_cancel (info); |
791 | - } |
792 | -} |
793 | - |
794 | -static void |
795 | -progress_ui_handler_build_unity_quicklist (MarlinProgressUIHandler *self) |
796 | -{ |
797 | - g_return_if_fail (self); |
798 | - GList *l; |
799 | - |
800 | - for (l = marlin_quicklist_handler_get_launcher_entries (self->priv->unity_quicklist_handler); l; l = l->next) { |
801 | - MarlinLauncherEntry *lentry = l->data; |
802 | - UnityLauncherEntry *entry = marlin_quicklist_handler_get_launcher_entry (l); |
803 | - DbusmenuMenuitem *ql = unity_launcher_entry_get_quicklist (entry); |
804 | - |
805 | - DbusmenuMenuitem *quickmenu = dbusmenu_menuitem_new (); |
806 | - dbusmenu_menuitem_property_set (quickmenu, |
807 | - DBUSMENU_MENUITEM_PROP_LABEL, |
808 | - _("Show Copy Dialog")); |
809 | - dbusmenu_menuitem_property_set_bool (quickmenu, |
810 | - DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); |
811 | - dbusmenu_menuitem_child_add_position (ql, quickmenu, -1); |
812 | - lentry->progress_quicklists = g_list_prepend (lentry->progress_quicklists, quickmenu); |
813 | - g_signal_connect (quickmenu, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
814 | - (GCallback) progress_ui_handler_unity_quicklist_show_activated, |
815 | - self); |
816 | - |
817 | - quickmenu = dbusmenu_menuitem_new (); |
818 | - dbusmenu_menuitem_property_set (quickmenu, |
819 | - DBUSMENU_MENUITEM_PROP_LABEL, |
820 | - _("Cancel All In-progress Actions")); |
821 | - dbusmenu_menuitem_property_set_bool (quickmenu, |
822 | - DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); |
823 | - dbusmenu_menuitem_child_add_position (ql, quickmenu, -1); |
824 | - lentry->progress_quicklists = g_list_prepend (lentry->progress_quicklists, quickmenu); |
825 | - g_signal_connect (quickmenu, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
826 | - (GCallback) progress_ui_handler_unity_quicklist_cancel_activated, |
827 | - self); |
828 | - } |
829 | -} |
830 | - |
831 | -static void |
832 | -progress_ui_handler_show_unity_quicklist (MarlinProgressUIHandler *self, |
833 | - MarlinLauncherEntry *lentry, |
834 | - gboolean show) |
835 | -{ |
836 | - g_return_if_fail (self); |
837 | - g_return_if_fail (lentry); |
838 | - |
839 | - GList *l; |
840 | - |
841 | - for (l = lentry->progress_quicklists; l; l = l->next) { |
842 | - dbusmenu_menuitem_property_set_bool(l->data, |
843 | - DBUSMENU_MENUITEM_PROP_VISIBLE, show); |
844 | - } |
845 | -} |
846 | - |
847 | -static void |
848 | -progress_ui_handler_update_unity_launcher_entry (MarlinProgressUIHandler *self, |
849 | - MarlinProgressInfo *info, |
850 | - MarlinLauncherEntry *lentry) |
851 | -{ |
852 | - UnityLauncherEntry *entry = lentry->entry; |
853 | - |
854 | - g_return_if_fail (self); |
855 | - g_return_if_fail (entry); |
856 | - |
857 | - if (self->priv->active_infos > 0) { |
858 | - unity_launcher_entry_set_progress_visible (entry, TRUE); |
859 | - progress_ui_handler_show_unity_quicklist (self, lentry, TRUE); |
860 | - progress_ui_handler_unity_progress_changed (NULL, self); |
861 | - } else { |
862 | - unity_launcher_entry_set_progress_visible (entry, FALSE); |
863 | - unity_launcher_entry_set_progress (entry, 0.0); |
864 | - unity_launcher_entry_set_count_visible (entry, FALSE); |
865 | - progress_ui_handler_show_unity_quicklist (self, lentry, FALSE); |
866 | - GCancellable *pc = marlin_progress_info_get_cancellable (info); |
867 | - |
868 | - if (!g_cancellable_is_cancelled (pc)) { |
869 | - unity_launcher_entry_set_urgent (entry, TRUE); |
870 | - |
871 | - g_timeout_add_seconds (2, (GSourceFunc) |
872 | - progress_ui_handler_disable_unity_urgency, |
873 | - entry); |
874 | - } |
875 | - } |
876 | -} |
877 | - |
878 | -static void |
879 | -progress_ui_handler_update_unity_launcher (MarlinProgressUIHandler *self, |
880 | - MarlinProgressInfo *info, |
881 | - gboolean added) |
882 | -{ |
883 | - g_return_if_fail (self); |
884 | - GList *l; |
885 | - |
886 | - if (!self->priv->unity_quicklist_handler) { |
887 | - self->priv->unity_quicklist_handler = marlin_quicklist_handler_get_singleton (); |
888 | - if (!self->priv->unity_quicklist_handler) |
889 | - return; |
890 | - |
891 | - progress_ui_handler_build_unity_quicklist (self); |
892 | - } |
893 | - |
894 | - for (l = marlin_quicklist_handler_get_launcher_entries (self->priv->unity_quicklist_handler); l; l = l->next) { |
895 | - MarlinLauncherEntry *lentry = l->data; |
896 | - UnityLauncherEntry *entry = marlin_quicklist_handler_get_launcher_entry (l); |
897 | - progress_ui_handler_update_unity_launcher_entry (self, info, lentry); |
898 | - } |
899 | - |
900 | - if (added) { |
901 | - g_signal_connect (info, "progress-changed", |
902 | - (GCallback) progress_ui_handler_unity_progress_changed, |
903 | - self); |
904 | - } |
905 | -} |
906 | -#endif |
907 | - |
908 | - |
909 | -static gboolean |
910 | -progress_window_delete_event (GtkWidget *widget, |
911 | - GdkEvent *event, |
912 | - MarlinProgressUIHandler *self) |
913 | -{ |
914 | - gtk_widget_hide (widget); |
915 | - |
916 | - if (self->priv->notification_supports_persistence) { |
917 | - progress_ui_handler_update_notification (self); |
918 | - } else { |
919 | - progress_ui_handler_update_status_icon (self); |
920 | - } |
921 | - |
922 | - return TRUE; |
923 | -} |
924 | - |
925 | -static void |
926 | -progress_ui_handler_ensure_window (MarlinProgressUIHandler *self) |
927 | -{ |
928 | - GtkWidget *vbox, *progress_window; |
929 | - |
930 | - if (self->priv->progress_window != NULL) { |
931 | - return; |
932 | - } |
933 | - |
934 | - progress_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); |
935 | - self->priv->progress_window = progress_window; |
936 | - gtk_window_set_resizable (GTK_WINDOW (progress_window), |
937 | - FALSE); |
938 | - gtk_container_set_border_width (GTK_CONTAINER (progress_window), 10); |
939 | - |
940 | - gtk_window_set_title (GTK_WINDOW (progress_window), |
941 | - _("File Operations")); |
942 | - gtk_window_set_wmclass (GTK_WINDOW (progress_window), |
943 | - "file_progress", "Marlin"); |
944 | - gtk_window_set_position (GTK_WINDOW (progress_window), |
945 | - GTK_WIN_POS_CENTER); |
946 | - gtk_window_set_icon_name (GTK_WINDOW (progress_window), |
947 | - "system-file-manager"); |
948 | - |
949 | - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); |
950 | - gtk_box_set_spacing (GTK_BOX (vbox), 5); |
951 | - gtk_container_add (GTK_CONTAINER (progress_window), |
952 | - vbox); |
953 | - self->priv->window_vbox = vbox; |
954 | - gtk_widget_show (vbox); |
955 | - |
956 | - g_signal_connect (progress_window, |
957 | - "delete-event", |
958 | - (GCallback) progress_window_delete_event, self); |
959 | -} |
960 | - |
961 | -static void |
962 | -progress_ui_handler_update_notification_or_status (MarlinProgressUIHandler *self) |
963 | -{ |
964 | - if (self->priv->notification_supports_persistence) { |
965 | - progress_ui_handler_update_notification (self); |
966 | - } else { |
967 | - progress_ui_handler_update_status_icon (self); |
968 | - } |
969 | -} |
970 | - |
971 | -static void |
972 | -progress_ui_handler_add_to_window (MarlinProgressUIHandler *self, |
973 | - MarlinProgressInfo *info) |
974 | -{ |
975 | - GtkWidget *progress; |
976 | - |
977 | - progress = marlin_progress_info_widget_new (info); |
978 | - progress_ui_handler_ensure_window (self); |
979 | - |
980 | - gtk_box_pack_start (GTK_BOX (self->priv->window_vbox), |
981 | - progress, |
982 | - FALSE, FALSE, 6); |
983 | - |
984 | - gtk_widget_show (progress); |
985 | -} |
986 | - |
987 | -static void |
988 | -progress_ui_handler_show_complete_notification (MarlinProgressUIHandler *self) |
989 | -{ |
990 | - NotifyNotification *complete_notification; |
991 | - |
992 | - /* don't display the notification if we'd be using a status icon */ |
993 | - if (!self->priv->notification_supports_persistence) { |
994 | - return; |
995 | - } |
996 | - |
997 | - complete_notification = notify_notification_new (_("File Operations"), |
998 | - _("All file operations have been successfully completed"), |
999 | - NULL); |
1000 | - notify_notification_show (complete_notification, NULL); |
1001 | - |
1002 | - g_object_unref (complete_notification); |
1003 | -} |
1004 | - |
1005 | -static void |
1006 | -progress_ui_handler_hide_notification_or_status (MarlinProgressUIHandler *self) |
1007 | -{ |
1008 | - if (self->priv->status_icon != NULL) { |
1009 | - gtk_status_icon_set_visible (self->priv->status_icon, FALSE); |
1010 | - } |
1011 | - |
1012 | - if (self->priv->progress_notification != NULL) { |
1013 | - notify_notification_close (self->priv->progress_notification, NULL); |
1014 | - g_clear_object (&self->priv->progress_notification); |
1015 | - } |
1016 | -} |
1017 | - |
1018 | -static void |
1019 | -progress_info_finished_cb (MarlinProgressInfo *info, |
1020 | - MarlinProgressUIHandler *self) |
1021 | -{ |
1022 | - self->priv->active_infos--; |
1023 | - |
1024 | - if (self->priv->active_infos > 0) { |
1025 | - if (!gtk_widget_get_visible (self->priv->progress_window)) { |
1026 | - progress_ui_handler_update_notification_or_status (self); |
1027 | - } |
1028 | - } else { |
1029 | - if (gtk_widget_get_visible (self->priv->progress_window)) { |
1030 | - gtk_widget_hide (self->priv->progress_window); |
1031 | - } else { |
1032 | - progress_ui_handler_hide_notification_or_status (self); |
1033 | - progress_ui_handler_show_complete_notification (self); |
1034 | - } |
1035 | - } |
1036 | - |
1037 | -#ifdef HAVE_UNITY |
1038 | - progress_ui_handler_update_unity_launcher (self, info, FALSE); |
1039 | -#endif |
1040 | -} |
1041 | - |
1042 | -static void |
1043 | -handle_new_progress_info (MarlinProgressUIHandler *self, |
1044 | - MarlinProgressInfo *info) |
1045 | -{ |
1046 | - g_signal_connect (info, "finished", |
1047 | - G_CALLBACK (progress_info_finished_cb), self); |
1048 | - |
1049 | - self->priv->active_infos++; |
1050 | - |
1051 | - if (self->priv->active_infos == 1) { |
1052 | - /* this is the only active operation, present the window */ |
1053 | - progress_ui_handler_add_to_window (self, info); |
1054 | - gtk_window_present (GTK_WINDOW (self->priv->progress_window)); |
1055 | - } else { |
1056 | - if (gtk_widget_get_visible (self->priv->progress_window)) { |
1057 | - progress_ui_handler_add_to_window (self, info); |
1058 | - } else { |
1059 | - progress_ui_handler_update_notification_or_status (self); |
1060 | - } |
1061 | - } |
1062 | - |
1063 | -#ifdef HAVE_UNITY |
1064 | - progress_ui_handler_update_unity_launcher (self, info, TRUE); |
1065 | -#endif |
1066 | -} |
1067 | - |
1068 | -typedef struct { |
1069 | - MarlinProgressInfo *info; |
1070 | - MarlinProgressUIHandler *self; |
1071 | -} TimeoutData; |
1072 | - |
1073 | -static void |
1074 | -timeout_data_free (TimeoutData *data) |
1075 | -{ |
1076 | - g_clear_object (&data->self); |
1077 | - g_clear_object (&data->info); |
1078 | - |
1079 | - g_slice_free (TimeoutData, data); |
1080 | -} |
1081 | - |
1082 | -static TimeoutData * |
1083 | -timeout_data_new (MarlinProgressUIHandler *self, |
1084 | - MarlinProgressInfo *info) |
1085 | -{ |
1086 | - TimeoutData *retval; |
1087 | - |
1088 | - retval = g_slice_new0 (TimeoutData); |
1089 | - retval->self = g_object_ref (self); |
1090 | - retval->info = g_object_ref (info); |
1091 | - |
1092 | - return retval; |
1093 | -} |
1094 | - |
1095 | -static gboolean |
1096 | -new_op_started_timeout (TimeoutData *data) |
1097 | -{ |
1098 | - MarlinProgressInfo *info = data->info; |
1099 | - MarlinProgressUIHandler *self = data->self; |
1100 | - |
1101 | - if (marlin_progress_info_get_is_paused (info)) { |
1102 | - return TRUE; |
1103 | - } |
1104 | - |
1105 | - if (!marlin_progress_info_get_is_finished (info)) { |
1106 | - handle_new_progress_info (self, info); |
1107 | - } |
1108 | - |
1109 | - timeout_data_free (data); |
1110 | - |
1111 | - return FALSE; |
1112 | -} |
1113 | - |
1114 | -static void |
1115 | -release_application (MarlinProgressInfo *info, |
1116 | - MarlinProgressUIHandler *self) |
1117 | -{ |
1118 | - MarlinApplication *app; |
1119 | - |
1120 | - /* release the GApplication hold we acquired */ |
1121 | - app = marlin_application_get (); |
1122 | - g_application_release (G_APPLICATION (app)); |
1123 | - |
1124 | - //amtest |
1125 | - g_message ("%s", G_STRFUNC); |
1126 | -} |
1127 | - |
1128 | -static void |
1129 | -progress_info_started_cb (MarlinProgressInfo *info, |
1130 | - MarlinProgressUIHandler *self) |
1131 | -{ |
1132 | - MarlinApplication *app; |
1133 | - TimeoutData *data; |
1134 | - |
1135 | - /* hold GApplication so we never quit while there's an operation pending */ |
1136 | - app = marlin_application_get (); |
1137 | - g_application_hold (G_APPLICATION (app)); |
1138 | - |
1139 | - g_signal_connect (info, "finished", |
1140 | - G_CALLBACK (release_application), self); |
1141 | - |
1142 | - data = timeout_data_new (self, info); |
1143 | - |
1144 | - /* timeout for the progress window to appear */ |
1145 | - g_timeout_add_seconds (2, |
1146 | - (GSourceFunc) new_op_started_timeout, |
1147 | - data); |
1148 | -} |
1149 | - |
1150 | -static void |
1151 | -new_progress_info_cb (MarlinProgressInfoManager *manager, |
1152 | - MarlinProgressInfo *info, |
1153 | - MarlinProgressUIHandler *self) |
1154 | -{ |
1155 | - g_signal_connect (info, "started", |
1156 | - G_CALLBACK (progress_info_started_cb), self); |
1157 | -} |
1158 | - |
1159 | -static void |
1160 | -marlin_progress_ui_handler_dispose (GObject *obj) |
1161 | -{ |
1162 | - MarlinProgressUIHandler *self = MARLIN_PROGRESS_UI_HANDLER (obj); |
1163 | - |
1164 | - g_clear_object (&self->priv->manager); |
1165 | - |
1166 | - G_OBJECT_CLASS (marlin_progress_ui_handler_parent_class)->dispose (obj); |
1167 | -} |
1168 | - |
1169 | -static gboolean |
1170 | -server_has_persistence (void) |
1171 | -{ |
1172 | - gboolean retval; |
1173 | - GList *caps, *l; |
1174 | - |
1175 | - caps = notify_get_server_caps (); |
1176 | - if (caps == NULL) { |
1177 | - return FALSE; |
1178 | - } |
1179 | - |
1180 | - l = g_list_find_custom (caps, "persistence", (GCompareFunc) g_strcmp0); |
1181 | - retval = (l != NULL); |
1182 | - |
1183 | - g_list_free_full (caps, g_free); |
1184 | - |
1185 | - return retval; |
1186 | -} |
1187 | - |
1188 | -static void |
1189 | -marlin_progress_ui_handler_init (MarlinProgressUIHandler *self) |
1190 | -{ |
1191 | - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MARLIN_TYPE_PROGRESS_UI_HANDLER, |
1192 | - MarlinProgressUIHandlerPriv); |
1193 | - |
1194 | - self->priv->manager = marlin_progress_info_manager_new (); |
1195 | - g_signal_connect (self->priv->manager, "new-progress-info", |
1196 | - G_CALLBACK (new_progress_info_cb), self); |
1197 | - |
1198 | - self->priv->notification_supports_persistence = server_has_persistence (); |
1199 | -} |
1200 | - |
1201 | -static void |
1202 | -marlin_progress_ui_handler_class_init (MarlinProgressUIHandlerClass *klass) |
1203 | -{ |
1204 | - GObjectClass *oclass; |
1205 | - |
1206 | - oclass = G_OBJECT_CLASS (klass); |
1207 | - oclass->dispose = marlin_progress_ui_handler_dispose; |
1208 | - |
1209 | - g_type_class_add_private (klass, sizeof (MarlinProgressUIHandlerPriv)); |
1210 | -} |
1211 | - |
1212 | -MarlinProgressUIHandler * |
1213 | -marlin_progress_ui_handler_new (void) |
1214 | -{ |
1215 | - return g_object_new (MARLIN_TYPE_PROGRESS_UI_HANDLER, NULL); |
1216 | -} |
1217 | |
1218 | === removed file 'src/marlin-progress-ui-handler.h' |
1219 | --- src/marlin-progress-ui-handler.h 2011-07-27 10:29:20 +0000 |
1220 | +++ src/marlin-progress-ui-handler.h 1970-01-01 00:00:00 +0000 |
1221 | @@ -1,64 +0,0 @@ |
1222 | -/* |
1223 | - * marlin-progress-ui-handler.h: file operation progress user interface. |
1224 | - * |
1225 | - * Copyright (C) 2007, 2011 Red Hat, Inc. |
1226 | - * |
1227 | - * This program is free software; you can redistribute it and/or |
1228 | - * modify it under the terms of the GNU General Public License as |
1229 | - * published by the Free Software Foundation; either version 2 of the |
1230 | - * License, or (at your option) any later version. |
1231 | - * |
1232 | - * This program is distributed in the hope that it will be useful, |
1233 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1234 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1235 | - * General Public License for more details. |
1236 | - * |
1237 | - * You should have received a copy of the GNU General Public |
1238 | - * License along with this program; if not, write to the |
1239 | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
1240 | - * Boston, MA 02111-1307, USA. |
1241 | - * |
1242 | - * Authors: Alexander Larsson <alexl@redhat.com> |
1243 | - * Cosimo Cecchi <cosimoc@redhat.com> |
1244 | - * |
1245 | - */ |
1246 | - |
1247 | -#ifndef __MARLIN_PROGRESS_UI_HANDLER_H__ |
1248 | -#define __MARLIN_PROGRESS_UI_HANDLER_H__ |
1249 | - |
1250 | -#include <glib-object.h> |
1251 | - |
1252 | -G_BEGIN_DECLS |
1253 | - |
1254 | -#define MARLIN_TYPE_PROGRESS_UI_HANDLER marlin_progress_ui_handler_get_type() |
1255 | -#define MARLIN_PROGRESS_UI_HANDLER(obj) \ |
1256 | - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MARLIN_TYPE_PROGRESS_UI_HANDLER, MarlinProgressUIHandler)) |
1257 | -#define MARLIN_PROGRESS_UI_HANDLER_CLASS(klass) \ |
1258 | - (G_TYPE_CHECK_CLASS_CAST ((klass), MARLIN_TYPE_PROGRESS_UI_HANDLER, MarlinProgressUIHandlerClass)) |
1259 | -#define MARLIN_IS_PROGRESS_UI_HANDLER(obj) \ |
1260 | - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MARLIN_TYPE_PROGRESS_UI_HANDLER)) |
1261 | -#define MARLIN_IS_PROGRESS_UI_HANDLER_CLASS(klass) \ |
1262 | - (G_TYPE_CHECK_CLASS_TYPE ((klass), MARLIN_TYPE_PROGRESS_UI_HANDLER)) |
1263 | -#define MARLIN_PROGRESS_UI_HANDLER_GET_CLASS(obj) \ |
1264 | - (G_TYPE_INSTANCE_GET_CLASS ((obj), MARLIN_TYPE_PROGRESS_UI_HANDLER, MarlinProgressUIHandlerClass)) |
1265 | - |
1266 | -typedef struct _MarlinProgressUIHandlerPriv MarlinProgressUIHandlerPriv; |
1267 | - |
1268 | -typedef struct { |
1269 | - GObject parent; |
1270 | - |
1271 | - /* private */ |
1272 | - MarlinProgressUIHandlerPriv *priv; |
1273 | -} MarlinProgressUIHandler; |
1274 | - |
1275 | -typedef struct { |
1276 | - GObjectClass parent_class; |
1277 | -} MarlinProgressUIHandlerClass; |
1278 | - |
1279 | -GType marlin_progress_ui_handler_get_type (void); |
1280 | - |
1281 | -MarlinProgressUIHandler * marlin_progress_ui_handler_new (void); |
1282 | - |
1283 | -G_END_DECLS |
1284 | - |
1285 | -#endif /* __MARLIN_PROGRESS_UI_HANDLER_H__ */ |
1286 | |
1287 | === modified file 'src/marlin.vapi' |
1288 | --- src/marlin.vapi 2013-08-16 22:51:52 +0000 |
1289 | +++ src/marlin.vapi 2013-08-16 22:51:52 +0000 |
1290 | @@ -56,7 +56,7 @@ |
1291 | public class Thumbnailer : Object { |
1292 | public static Thumbnailer get(); |
1293 | public bool queue_file(GOF.File file, int? request, bool large); |
1294 | - |
1295 | + |
1296 | } |
1297 | [CCode (cheader_filename = "marlin-bookmark.h")] |
1298 | public class Bookmark : Object { |
1299 | @@ -118,11 +118,8 @@ |
1300 | [CCode (cheader_filename = "marlin-file-operations.h")] |
1301 | public void new_folder_with_name_recursive(Gtk.Widget? parent_view, Gdk.Point? target_point, File file, string name, void* callback, void* data_callback); |
1302 | } |
1303 | - [CCode (cprefix = "MarlinProgress", lower_case_cprefix = "marlin_progress_")] |
1304 | - namespace Progress { |
1305 | - [CCode (cheader_filename = "marlin-progress-ui-handler.h")] |
1306 | - public class UIHandler : Object { |
1307 | - public UIHandler (); |
1308 | - } |
1309 | + [CCode (cheader_filename = "marlin-progress-info-widget.h")] |
1310 | + public class Progress.InfoWidget : Gtk.Box { |
1311 | + public InfoWidget (Marlin.Progress.Info info); |
1312 | } |
1313 | } |
Testing went normally.