Merge lp:~jeremywootten/pantheon-files/transfer-popover-with-pie-progress into lp:~elementary-apps/pantheon-files/trunk
- transfer-popover-with-pie-progress
- Merge into trunk
Status: | Superseded | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Proposed branch: | lp:~jeremywootten/pantheon-files/transfer-popover-with-pie-progress | ||||||||||||
Merge into: | lp:~elementary-apps/pantheon-files/trunk | ||||||||||||
Diff against target: |
2642 lines (+1397/-452) 28 files modified
CMakeLists.txt (+3/-2) data/CMakeLists.txt (+5/-2) data/pantheon-files.db.service.cmake (+4/-0) data/pantheon-files.ql.service.cmake (+4/-0) data/pantheon-files.service.cmake (+1/-0) libcore/Enums.vala (+9/-0) libcore/gof-directory-async.vala (+1/-0) libcore/marlin-file-operations.c (+89/-34) libcore/marlin-progress-info.c (+190/-2) libcore/marlin-progress-info.h (+18/-0) libcore/pantheon-files-core-C.vapi (+7/-0) libwidgets/CMakeLists.txt (+3/-0) pantheon-files-daemon/CMakeLists.txt (+48/-17) pantheon-files-daemon/ProgressHandlerQuicklistInterface.vala (+31/-0) pantheon-files-daemon/QuicklistHandler.vala (+217/-43) pantheon-files-daemon/main.vala (+68/-0) pantheon-files-daemon/marlind-tagging.vala (+0/-58) pantheon-files-daemon/pantheon-files-daemon.vapi (+28/-0) src/Application.vala (+57/-9) src/CMakeLists.txt (+10/-13) src/ProgressUIHandler.vala (+107/-169) src/View/Slot.vala (+1/-1) src/View/Widgets/ProgressIndicator.vala (+105/-0) src/View/Widgets/ProgressIndicatorWithPopover.vala (+121/-0) src/View/Widgets/ProgressInfoListRow.vala (+238/-0) src/View/Widgets/ProgressInfoWidget.vala (+0/-102) src/View/Widgets/TopMenu.vala (+20/-0) src/View/Window.vala (+12/-0) |
||||||||||||
To merge this branch: | bzr merge lp:~jeremywootten/pantheon-files/transfer-popover-with-pie-progress | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Zisu Andrei | Pending | ||
Danielle Foré | Pending | ||
Review via email: mp+311349@code.launchpad.net |
This proposal supersedes a proposal from 2016-03-10.
Commit message
Description of the change
This branch transfers handling of unity launcher quicklist and progress indicator to pantheon-files daemon.
It also refactors the progress UI handling, replacing the dialog window with a pie (doughnut) shaped progress indicator in the headerbar associated with a popover to show details.
Danielle Foré (danrabbit) wrote : Posted in a previous version of this proposal | # |
Danielle Foré (danrabbit) wrote : Posted in a previous version of this proposal | # |
I don't really like that it warns you about closing the window now. That seems like a regression. Users should be able to close a window without worry and the process just continue to run in the background.
I also get notifications when moving things to the trash from an external disk. That seems unnecessary.
I get a notification on starting a transfer. Again, it seems unnecessary to notify me of things that I'm doing.
Jeremy Wootten (jeremywootten) wrote : Posted in a previous version of this proposal | # |
OK, thanks for your comments. I'll work on that.
Jeremy Wootten (jeremywootten) wrote : Posted in a previous version of this proposal | # |
The stop process button is now more clearly associated with the progress bar (not a close popover button) and is not symbolic - the red color warning that it has an irreversible effect (is confirmation required?). This follows comments on Google+.
Danielle Foré (danrabbit) wrote : Posted in a previous version of this proposal | # |
No, I don't think confirmation is required. It is quite reversible. Just start another transfer :p
Notifications don't seen to have an icon. Probably should use the Files icon so it's clear which app this is coming from.
"File operation completed" is pretty vague. Can we get a little more specific? "5 files copied to Foo" for example?
I seem to always get the HTML mime. I'm guessing this is hardcoded?
Can the gradient on the progressbar go from top to bottom instead of around the doughnut? Looks kinda weird and doesn't really make sense. I'm not sure how the light would have to be to produce that effect :p
I'm thinking maybe we shouldn't group files into a single row. I have two rows that say "Copying foo files to bar". It's hard to remember what exactly each one is.
I'm not sure why you're creating constants for icon names, especially if you're only using it once. Seems like it makes the code less legible.
Any reason you're subclassing gtk.box here instead of using ListBox and ListBoxRow?
Margins on the popover seem oddly huge. Margins on dialogs and popovers should be 12px.
I think it would be helpful to name "ProgressInfoWi
You should use gtk.grid instead of nesting boxes
Jeremy Wootten (jeremywootten) wrote : Posted in a previous version of this proposal | # |
The completion notification is "All file operations have been completed" and only appears when the last of the file operations finishes - there are no notifications for individual notifications for file operations. So your suggestion would only work if there was only one file operation (which, admittedly there usually is). Otherwise you would have to list each operation? And whether or not they were successful or failed? Or notify the ending of each operation individually?
Zisu Andrei (matzipan) wrote : Posted in a previous version of this proposal | # |
Tested it. Works nicely, although the pie needs a bit of visual improvements to better match the mockup (https:/
Diff comments attached to this message.
- 2044. By Jeremy Wootten
-
Merge trunk to r2444 and resolve conflicts
- 2045. By Jeremy Wootten
-
Move Progress widgets to src/View/Widgets
- 2046. By Jeremy Wootten
-
Define MarlinFileOpera
tionType in marlin- progress- info.h not Enums.vala to avoid conflicts with testing branches - 2047. By Jeremy Wootten
-
Merge trunk to r2470
Unmerged revisions
- 2047. By Jeremy Wootten
-
Merge trunk to r2470
- 2046. By Jeremy Wootten
-
Define MarlinFileOpera
tionType in marlin- progress- info.h not Enums.vala to avoid conflicts with testing branches - 2045. By Jeremy Wootten
-
Move Progress widgets to src/View/Widgets
- 2044. By Jeremy Wootten
-
Merge trunk to r2444 and resolve conflicts
- 2043. By Jeremy Wootten
-
Merge trunk to r2382 and resolve conflicts
- 2042. By Jeremy Wootten
-
Merge trunk to r2229 and resolve conflicts. Make prefix for APP_ID, .desktop files, dbus service files, dbus service addresses, settings schemas consistently org.pantheon.files
- 2041. By Jeremy Wootten
-
Change total_files to total_file_count
- 2040. By Jeremy Wootten
-
Change remaining_files to remaining_
file_count - 2039. By Jeremy Wootten
-
Rename info->no_files
- 2038. By Jeremy Wootten
-
Initialise info->current_
filename; return empty string if null
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-12-16 10:09:11 +0000 |
3 | +++ CMakeLists.txt 2017-01-14 12:39:17 +0000 |
4 | @@ -2,6 +2,7 @@ |
5 | |
6 | cmake_minimum_required (VERSION 2.8) |
7 | cmake_policy (VERSION 2.8) |
8 | +cmake_policy (SET CMP0015 OLD) |
9 | project (pantheon-files C) |
10 | enable_testing () |
11 | |
12 | @@ -35,9 +36,9 @@ |
13 | ELSE () |
14 | add_subdirectory (src) |
15 | add_subdirectory (data) |
16 | + add_subdirectory (libcore) |
17 | + add_subdirectory (libwidgets) |
18 | add_subdirectory (pantheon-files-daemon) |
19 | - add_subdirectory (libcore) |
20 | - add_subdirectory (libwidgets) |
21 | add_subdirectory (plugins) |
22 | add_subdirectory (filechooser-module) |
23 | add_subdirectory (po) |
24 | |
25 | === modified file 'data/CMakeLists.txt' |
26 | --- data/CMakeLists.txt 2016-08-01 23:47:17 +0000 |
27 | +++ data/CMakeLists.txt 2017-01-14 12:39:17 +0000 |
28 | @@ -1,6 +1,8 @@ |
29 | include (Translations) |
30 | |
31 | -configure_file(pantheon-files.service.cmake ${CMAKE_CURRENT_BINARY_DIR}/pantheon-files.service) |
32 | +configure_file(pantheon-files.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/org.pantheon.files.desktop) |
33 | +configure_file(pantheon-files.db.service.cmake ${CMAKE_CURRENT_BINARY_DIR}/org.pantheon.files.db.service) |
34 | +configure_file(pantheon-files.ql.service.cmake ${CMAKE_CURRENT_BINARY_DIR}/org.pantheon.files.ql.service) |
35 | configure_file(pantheon-files-pkexec.cmake ${CMAKE_CURRENT_BINARY_DIR}/pantheon-files-pkexec) |
36 | configure_file(net.launchpad.pantheon-files.policy.cmake ${CMAKE_CURRENT_BINARY_DIR}/net.launchpad.pantheon-files.policy) |
37 | |
38 | @@ -9,7 +11,8 @@ |
39 | |
40 | install (FILES ${CMAKE_CURRENT_BINARY_DIR}/org.pantheon.files.appdata.xml DESTINATION share/appdata) |
41 | install (FILES ${CMAKE_CURRENT_BINARY_DIR}/org.pantheon.files.desktop DESTINATION share/applications) |
42 | -install (FILES ${CMAKE_CURRENT_BINARY_DIR}/pantheon-files.service DESTINATION share/dbus-1/services/) |
43 | +install (FILES ${CMAKE_CURRENT_BINARY_DIR}/org.pantheon.files.db.service DESTINATION share/dbus-1/services/) |
44 | +install (FILES ${CMAKE_CURRENT_BINARY_DIR}/org.pantheon.files.ql.service DESTINATION share/dbus-1/services/) |
45 | install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/pantheon-files-pkexec DESTINATION bin) |
46 | install (FILES ${CMAKE_CURRENT_BINARY_DIR}/net.launchpad.pantheon-files.policy DESTINATION share/polkit-1/actions/) |
47 | |
48 | |
49 | === added file 'data/pantheon-files.db.service.cmake' |
50 | --- data/pantheon-files.db.service.cmake 1970-01-01 00:00:00 +0000 |
51 | +++ data/pantheon-files.db.service.cmake 2017-01-14 12:39:17 +0000 |
52 | @@ -0,0 +1,4 @@ |
53 | +[D-BUS Service] |
54 | +Name=org.pantheon.files.db |
55 | +Exec=@CMAKE_INSTALL_PREFIX@/bin/pantheon-files-daemon |
56 | + |
57 | |
58 | === added file 'data/pantheon-files.ql.service.cmake' |
59 | --- data/pantheon-files.ql.service.cmake 1970-01-01 00:00:00 +0000 |
60 | +++ data/pantheon-files.ql.service.cmake 2017-01-14 12:39:17 +0000 |
61 | @@ -0,0 +1,4 @@ |
62 | +[D-BUS Service] |
63 | +Name=org.pantheon.files.ql |
64 | +Exec=@CMAKE_INSTALL_PREFIX@/bin/pantheon-files-daemon |
65 | + |
66 | |
67 | === modified file 'data/pantheon-files.service.cmake' |
68 | --- data/pantheon-files.service.cmake 2016-06-18 11:25:11 +0000 |
69 | +++ data/pantheon-files.service.cmake 2017-01-14 12:39:17 +0000 |
70 | @@ -1,3 +1,4 @@ |
71 | [D-BUS Service] |
72 | Name=org.pantheon.files.db |
73 | Exec=@CMAKE_INSTALL_PREFIX@/bin/pantheon-files-daemon |
74 | + |
75 | |
76 | === modified file 'libcore/Enums.vala' |
77 | --- libcore/Enums.vala 2016-12-31 19:42:09 +0000 |
78 | +++ libcore/Enums.vala 2017-01-14 12:39:17 +0000 |
79 | @@ -149,4 +149,13 @@ |
80 | XDND_DIRECT_SAVE0, |
81 | NETSCAPE_URL |
82 | } |
83 | + |
84 | + public enum FileOperationType { |
85 | + COPY, |
86 | + MOVE, |
87 | + TRASH, |
88 | + DELETE, |
89 | + LINK, |
90 | + INVALID |
91 | + } |
92 | } |
93 | |
94 | === modified file 'libcore/gof-directory-async.vala' |
95 | --- libcore/gof-directory-async.vala 2017-01-04 13:40:56 +0000 |
96 | +++ libcore/gof-directory-async.vala 2017-01-14 12:39:17 +0000 |
97 | @@ -555,6 +555,7 @@ |
98 | } |
99 | state = State.LOADED; |
100 | } catch (Error err) { |
101 | + cancel_timeout (ref load_timeout_id); |
102 | warning ("Listing directory error: %s %s", err.message, file.uri); |
103 | can_load = false; |
104 | if (err is IOError.NOT_FOUND || err is IOError.NOT_DIRECTORY) { |
105 | |
106 | === modified file 'libcore/marlin-file-operations.c' |
107 | --- libcore/marlin-file-operations.c 2016-10-16 18:35:01 +0000 |
108 | +++ libcore/marlin-file-operations.c 2017-01-14 12:39:17 +0000 |
109 | @@ -2066,6 +2066,11 @@ |
110 | #ifdef ENABLE_TASKVIEW |
111 | taskview_generic_set_state (TASKVIEW_GENERIC (job->common.tv_io), TASKVIEW_RUNNING); |
112 | #else |
113 | + if (job->try_trash) { |
114 | + marlin_progress_info_set_optype (common->progress, MARLIN_FILE_OPERATION_TYPE_TRASH); |
115 | + } else { |
116 | + marlin_progress_info_set_optype (common->progress, MARLIN_FILE_OPERATION_TYPE_DELETE); |
117 | + } |
118 | marlin_progress_info_start (job->common.progress); |
119 | #endif |
120 | |
121 | @@ -2649,8 +2654,10 @@ |
122 | static void |
123 | count_file (GFileInfo *info, |
124 | CommonJob *job, |
125 | - SourceInfo *source_info) |
126 | + SourceInfo *source_info, |
127 | + const char *lastctype) |
128 | { |
129 | + const char *ctype; |
130 | source_info->num_files += 1; |
131 | source_info->num_bytes += g_file_info_get_size (info); |
132 | |
133 | @@ -2658,6 +2665,16 @@ |
134 | report_count_progress (job, source_info); |
135 | source_info->num_files_since_progress = 0; |
136 | } |
137 | + |
138 | + if (info != NULL) { |
139 | + ctype = g_file_info_get_content_type (info); |
140 | + |
141 | + if (source_info->num_files == 1) { |
142 | + marlin_progress_info_set_ctype (job->progress, ctype); |
143 | + } else if (strcmp (ctype, lastctype) != 0) { |
144 | + marlin_progress_info_set_ctype (job->progress, ""); |
145 | + } |
146 | + } |
147 | } |
148 | |
149 | static char * |
150 | @@ -2697,6 +2714,7 @@ |
151 | enumerator = g_file_enumerate_children (dir, |
152 | G_FILE_ATTRIBUTE_STANDARD_NAME"," |
153 | G_FILE_ATTRIBUTE_STANDARD_TYPE"," |
154 | + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"," |
155 | G_FILE_ATTRIBUTE_STANDARD_SIZE, |
156 | G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, |
157 | job->cancellable, |
158 | @@ -2704,7 +2722,7 @@ |
159 | if (enumerator) { |
160 | error = NULL; |
161 | while ((info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL) { |
162 | - count_file (info, job, source_info); |
163 | + count_file (info, job, source_info, ""); |
164 | |
165 | if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { |
166 | subdir = g_file_get_child (dir, |
167 | @@ -2713,8 +2731,6 @@ |
168 | /* Push to head, since we want depth-first */ |
169 | g_queue_push_head (dirs, subdir); |
170 | } |
171 | - |
172 | - g_object_unref (info); |
173 | } |
174 | g_file_enumerator_close (enumerator, job->cancellable, NULL); |
175 | g_object_unref (enumerator); |
176 | @@ -2799,10 +2815,11 @@ |
177 | } |
178 | } |
179 | |
180 | -static void |
181 | +static const char* |
182 | scan_file (GFile *file, |
183 | SourceInfo *source_info, |
184 | - CommonJob *job) |
185 | + CommonJob *job, |
186 | + const char* lastctype) |
187 | { |
188 | GFileInfo *info; |
189 | GError *error; |
190 | @@ -2817,20 +2834,20 @@ |
191 | retry: |
192 | error = NULL; |
193 | info = g_file_query_info (file, |
194 | + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME"," |
195 | G_FILE_ATTRIBUTE_STANDARD_TYPE"," |
196 | + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"," |
197 | G_FILE_ATTRIBUTE_STANDARD_SIZE, |
198 | G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, |
199 | job->cancellable, |
200 | &error); |
201 | |
202 | if (info) { |
203 | - count_file (info, job, source_info); |
204 | + count_file (info, job, source_info,lastctype); |
205 | |
206 | if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { |
207 | g_queue_push_head (dirs, g_object_ref (file)); |
208 | } |
209 | - |
210 | - g_object_unref (info); |
211 | } else if (job->skip_all_error) { |
212 | g_error_free (error); |
213 | skip_file (job, file); |
214 | @@ -2883,6 +2900,17 @@ |
215 | /* Free all from queue if we exited early */ |
216 | g_queue_foreach (dirs, (GFunc)g_object_unref, NULL); |
217 | g_queue_free (dirs); |
218 | + |
219 | + |
220 | + const char* res; |
221 | + if (info) { |
222 | + res = g_strdup (g_file_info_get_content_type (info)); |
223 | + g_object_unref (info); |
224 | + } else { |
225 | + res = ""; |
226 | + } |
227 | + |
228 | + return res; |
229 | } |
230 | |
231 | static void |
232 | @@ -2893,6 +2921,8 @@ |
233 | { |
234 | GList *l; |
235 | GFile *file; |
236 | + const char *lastctype; |
237 | + |
238 | |
239 | memset (source_info, 0, sizeof (SourceInfo)); |
240 | source_info->op = kind; |
241 | @@ -2902,11 +2932,12 @@ |
242 | for (l = files; l != NULL && !job_aborted (job); l = l->next) { |
243 | file = l->data; |
244 | |
245 | - scan_file (file, |
246 | - source_info, |
247 | - job); |
248 | + lastctype = scan_file (file, |
249 | + source_info, |
250 | + job, |
251 | + lastctype); |
252 | } |
253 | - |
254 | + g_free (lastctype); |
255 | /* Make sure we report the final count */ |
256 | report_count_progress (job, source_info); |
257 | } |
258 | @@ -3076,6 +3107,7 @@ |
259 | CommonJob *job; |
260 | gboolean is_move; |
261 | int files_left; |
262 | + int nth_file; |
263 | #ifndef ENABLE_TASKVIEW |
264 | goffset total_size; |
265 | double elapsed, transfer_rate; |
266 | @@ -3104,15 +3136,15 @@ |
267 | files_left = 1; |
268 | } |
269 | |
270 | + nth_file = source_info->num_files - files_left + 1; /*nominal number of file currently being transferred */ |
271 | + |
272 | if (files_left != transfer_info->last_reported_files_left || |
273 | transfer_info->last_reported_files_left == 0) { |
274 | /* Avoid changing this unless files_left changed since last time */ |
275 | transfer_info->last_reported_files_left = files_left; |
276 | - |
277 | if (source_info->num_files == 1) { |
278 | if (copy_job->destination != NULL) { |
279 | - s = f (is_move ? _("Moving \"%B\" to \"%B\"") : |
280 | - _("Copying \"%B\" to \"%B\""), |
281 | + s = f (is_move ? _("Moving \"%B\" to \"%B\"") : _("Copying \"%B\" to \"%B\""), |
282 | (GFile *)copy_job->files->data, |
283 | copy_job->destination); |
284 | } else { |
285 | @@ -3120,20 +3152,22 @@ |
286 | } |
287 | } else if (copy_job->files != NULL && copy_job->files->next == NULL) { |
288 | if (copy_job->destination != NULL) { |
289 | - s = f (is_move ? ngettext ("Moving %'d file (in \"%B\") to \"%B\"", |
290 | - "Moving %'d files (in \"%B\") to \"%B\"", |
291 | - files_left) : |
292 | - ngettext ("Copying %'d file (in \"%B\") to \"%B\"", |
293 | - "Copying %'d files (in \"%B\") to \"%B\"", |
294 | - files_left), |
295 | - files_left, |
296 | + /* TRANSLATORS: The first %'d represents the (nominal) number of the file currently being transferred and should not be translated. |
297 | + * The second %'d represents the (nominal) total number of files in the transfer operation and should not be translated. |
298 | + * The \"%B\" 's represent the paths of the source and destination folders respectively and should not be translated. */ |
299 | + s = f (is_move ? _("Moving file %'d of %'d (in \"%B\") to \"%B\". ") |
300 | + : _("Copying file %'d of %'d (in \"%B\") to \"%B\". "), |
301 | + nth_file, |
302 | + source_info->num_files, |
303 | (GFile *)copy_job->files->data, |
304 | copy_job->destination); |
305 | } else { |
306 | - s = f (ngettext ("Duplicating %'d file (in \"%B\")", |
307 | - "Duplicating %'d files (in \"%B\")", |
308 | - files_left), |
309 | - files_left, |
310 | + /* TRANSLATORS: The first %'d represents the (nominal) number of the file currently being transferred and should not be translated. |
311 | + * The second %'d represents the (nominal) total number of files in the transfer operation and should not be translated. |
312 | + * The \"%B\" represents the path of the source and should not be translated. */ |
313 | + s = f ("Duplicating file %'d of %'d (in \"%B\")", |
314 | + nth_file, |
315 | + source_info->num_files, |
316 | (GFile *)copy_job->files->data); |
317 | } |
318 | } else { |
319 | @@ -4344,6 +4378,17 @@ |
320 | pdata.source_info = source_info; |
321 | pdata.transfer_info = transfer_info; |
322 | |
323 | + GFileInfo *info; |
324 | + info = g_file_query_info (src, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, |
325 | + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, |
326 | + job->cancellable, |
327 | + NULL); |
328 | + |
329 | + marlin_progress_info_set_current_filename (job->progress, g_file_info_get_display_name (info)); |
330 | + marlin_progress_info_decrement_remaining_file_count (job->progress); |
331 | + |
332 | + g_object_unref (info); |
333 | + |
334 | if (copy_job->is_move) { |
335 | res = g_file_move (src, dest, |
336 | flags, |
337 | @@ -4352,6 +4397,7 @@ |
338 | &pdata, |
339 | &error); |
340 | } else { |
341 | + |
342 | res = g_file_copy (src, dest, |
343 | flags, |
344 | job->cancellable, |
345 | @@ -4747,6 +4793,8 @@ |
346 | #ifdef ENABLE_TASKVIEW |
347 | g_object_set (job->common.tv_io, "state", TASKVIEW_RUNNING, NULL); |
348 | #else |
349 | + marlin_progress_info_set_optype (common->progress, MARLIN_FILE_OPERATION_TYPE_COPY); |
350 | + marlin_progress_info_set_destination_uri (common->progress, g_file_get_uri (job->destination)); |
351 | marlin_progress_info_start (job->common.progress); |
352 | #endif |
353 | |
354 | @@ -4754,10 +4802,13 @@ |
355 | &source_info, |
356 | common, |
357 | OP_KIND_COPY); |
358 | + |
359 | if (job_aborted (common)) { |
360 | goto aborted; |
361 | } |
362 | |
363 | + marlin_progress_info_set_remaining_file_count (common->progress, source_info.num_files); |
364 | + |
365 | if (job->destination) { |
366 | dest = g_object_ref (job->destination); |
367 | } else { |
368 | @@ -4855,7 +4906,6 @@ |
369 | NULL); |
370 | g_free (s); |
371 | #else |
372 | - marlin_progress_info_take_status (job->progress, s); |
373 | marlin_progress_info_take_details (job->progress, |
374 | f (ngettext ("Preparing to move %'d file", |
375 | "Preparing to move %'d files", |
376 | @@ -5284,6 +5334,8 @@ |
377 | #ifdef ENABLE_TASKVIEW |
378 | g_object_set (job->common.tv_io, "state", TASKVIEW_RUNNING, NULL); |
379 | #else |
380 | + marlin_progress_info_set_optype (common->progress, MARLIN_FILE_OPERATION_TYPE_MOVE); |
381 | + marlin_progress_info_set_destination_uri (common->progress, g_file_get_uri (job->destination)); |
382 | marlin_progress_info_start (job->common.progress); |
383 | #endif |
384 | |
385 | @@ -5297,6 +5349,7 @@ |
386 | |
387 | /* This moves all files that we can do without copy + delete */ |
388 | move_files_prepare (job, dest_fs_id, &dest_fs_type, &fallbacks); |
389 | + |
390 | if (job_aborted (common)) { |
391 | goto aborted; |
392 | } |
393 | @@ -5310,6 +5363,8 @@ |
394 | common, |
395 | OP_KIND_MOVE); |
396 | |
397 | + marlin_progress_info_set_remaining_file_count (common->progress, source_info.num_files); |
398 | + |
399 | g_list_free (fallback_files); |
400 | |
401 | if (job_aborted (common)) { |
402 | @@ -5320,6 +5375,7 @@ |
403 | job->destination, |
404 | NULL, |
405 | source_info.num_bytes); |
406 | + |
407 | if (job_aborted (common)) { |
408 | goto aborted; |
409 | } |
410 | @@ -5616,8 +5672,6 @@ |
411 | { |
412 | CopyMoveJob *job; |
413 | CommonJob *common; |
414 | - GList *copy_files; |
415 | - GArray *copy_positions; |
416 | GFile *src; |
417 | GdkPoint *point; |
418 | char *dest_fs_type; |
419 | @@ -5629,14 +5683,15 @@ |
420 | common = &job->common; |
421 | common->io_job = io_job; |
422 | |
423 | - copy_files = NULL; |
424 | - copy_positions = NULL; |
425 | - |
426 | dest_fs_type = NULL; |
427 | + total = left = g_list_length (job->files); |
428 | |
429 | #ifdef ENABLE_TASKVIEW |
430 | g_object_set (job->common.tv_io, "state", TASKVIEW_RUNNING, NULL); |
431 | #else |
432 | + marlin_progress_info_set_optype (common->progress, MARLIN_FILE_OPERATION_TYPE_LINK); |
433 | + marlin_progress_info_set_destination_uri (common->progress, g_file_get_uri (job->destination)); |
434 | + marlin_progress_info_set_remaining_file_count (common->progress, total); |
435 | marlin_progress_info_start (job->common.progress); |
436 | #endif |
437 | |
438 | @@ -5648,7 +5703,7 @@ |
439 | goto aborted; |
440 | } |
441 | |
442 | - total = left = g_list_length (job->files); |
443 | + |
444 | |
445 | report_link_progress (job, total, left); |
446 | |
447 | |
448 | === modified file 'libcore/marlin-progress-info.c' |
449 | --- libcore/marlin-progress-info.c 2016-06-24 18:59:29 +0000 |
450 | +++ libcore/marlin-progress-info.c 2017-01-14 12:39:17 +0000 |
451 | @@ -49,9 +49,15 @@ |
452 | char *title; |
453 | char *status; |
454 | char *details; |
455 | + char *ctype; |
456 | + char *destination; |
457 | + MarlinFileOperationType optype; |
458 | + char *current_filename; |
459 | double progress; |
460 | - double current; |
461 | - double total; |
462 | + double current; /* Current number of bytes that have been copied/moved/deleted */ |
463 | + double total; /* Total number of bytes to be copied/moved/deleted */ |
464 | + int file_count; /* Current number of files that have been copied/moved/deleted */ |
465 | + int total_file_count; /* Total number of files to be copied/moved/deleted */ |
466 | gboolean activity_mode; |
467 | gboolean started; |
468 | gboolean finished; |
469 | @@ -85,6 +91,9 @@ |
470 | g_free (info->title); |
471 | g_free (info->status); |
472 | g_free (info->details); |
473 | + g_free (info->ctype); |
474 | + g_free (info->destination); |
475 | + g_free (info->current_filename); |
476 | g_object_unref (info->cancellable); |
477 | |
478 | if (G_OBJECT_CLASS (marlin_progress_info_parent_class)->finalize) { |
479 | @@ -160,6 +169,13 @@ |
480 | MarlinProgressInfoManager *manager; |
481 | |
482 | info->cancellable = g_cancellable_new (); |
483 | + info->title = NULL; |
484 | + info->status = NULL; |
485 | + info->ctype = NULL; |
486 | + info->destination = NULL; |
487 | + info->current_filename = NULL; |
488 | + info->total_file_count = -1; |
489 | + info->file_count = -1; |
490 | |
491 | info->title = NULL; |
492 | |
493 | @@ -296,6 +312,10 @@ |
494 | g_cancellable_cancel (info->cancellable); |
495 | |
496 | G_UNLOCK (progress_info); |
497 | + /* Call finish now for responsiveness of interface, as it may take some tiime for the |
498 | + * marlin file operation to actually finish. |
499 | + */ |
500 | + marlin_progress_info_finish (info); |
501 | } |
502 | |
503 | GCancellable * |
504 | @@ -509,12 +529,177 @@ |
505 | G_UNLOCK (progress_info); |
506 | } |
507 | |
508 | +char * |
509 | +marlin_progress_info_get_destination_uri (MarlinProgressInfo *info) |
510 | +{ |
511 | + char *uri; |
512 | + G_LOCK (progress_info); |
513 | + |
514 | + uri = g_strdup (info->destination); |
515 | + |
516 | + G_UNLOCK (progress_info); |
517 | + |
518 | + return uri; |
519 | +} |
520 | + |
521 | +char * |
522 | +marlin_progress_info_get_ctype (MarlinProgressInfo *info) |
523 | +{ |
524 | + char *ct; |
525 | + G_LOCK (progress_info); |
526 | + |
527 | + ct = g_strdup (info->ctype); |
528 | + |
529 | + G_UNLOCK (progress_info); |
530 | + |
531 | + return ct; |
532 | +} |
533 | + |
534 | +MarlinFileOperationType |
535 | +marlin_progress_info_get_optype (MarlinProgressInfo *info) |
536 | +{ |
537 | + MarlinFileOperationType ot; |
538 | + G_LOCK (progress_info); |
539 | + |
540 | + ot = info->optype; |
541 | + |
542 | + G_UNLOCK (progress_info); |
543 | + |
544 | + return ot; |
545 | +} |
546 | + |
547 | +char * |
548 | +marlin_progress_info_get_current_filename (MarlinProgressInfo *info) |
549 | +{ |
550 | + char *cfn; |
551 | + G_LOCK (progress_info); |
552 | + |
553 | + if (info->current_filename) { |
554 | + cfn = g_strdup (info->current_filename); |
555 | + } else { |
556 | + cfn = ""; |
557 | + } |
558 | + |
559 | + G_UNLOCK (progress_info); |
560 | + |
561 | + return cfn; |
562 | +} |
563 | + |
564 | +int |
565 | +marlin_progress_info_get_remaining_file_count (MarlinProgressInfo *info) |
566 | +{ |
567 | + uint rf; |
568 | + |
569 | + G_LOCK (progress_info); |
570 | + |
571 | + rf = info->file_count; |
572 | + |
573 | + G_UNLOCK (progress_info); |
574 | + |
575 | + return rf; |
576 | +} |
577 | + |
578 | +int |
579 | +marlin_progress_info_get_total_file_count (MarlinProgressInfo *info) |
580 | +{ |
581 | + uint tf; |
582 | + |
583 | + G_LOCK (progress_info); |
584 | + |
585 | + tf = info->total_file_count; |
586 | + |
587 | + G_UNLOCK (progress_info); |
588 | + |
589 | + return tf; |
590 | +} |
591 | + |
592 | +void |
593 | +marlin_progress_info_set_destination_uri (MarlinProgressInfo *info, |
594 | + const char *uri) |
595 | +{ |
596 | + G_LOCK (progress_info); |
597 | + |
598 | + if (info->destination) { |
599 | + g_free (info->destination); |
600 | + } |
601 | + info->destination = g_strdup (uri); |
602 | + |
603 | + G_UNLOCK (progress_info); |
604 | +} |
605 | + |
606 | +void |
607 | +marlin_progress_info_set_ctype (MarlinProgressInfo *info, |
608 | + const char *ctype) |
609 | +{ |
610 | + G_LOCK (progress_info); |
611 | + |
612 | + if (info->ctype) { |
613 | + g_free (info->ctype); |
614 | + } |
615 | + info->ctype = g_strdup (ctype); |
616 | + |
617 | + G_UNLOCK (progress_info); |
618 | +} |
619 | + |
620 | +void |
621 | +marlin_progress_info_set_current_filename (MarlinProgressInfo *info, |
622 | + char *current_filename) |
623 | +{ |
624 | + G_LOCK (progress_info); |
625 | + |
626 | + if (info->current_filename) { |
627 | + g_free (info->current_filename); |
628 | + } |
629 | + info->current_filename = g_strdup (current_filename); |
630 | + |
631 | + G_UNLOCK (progress_info); |
632 | +} |
633 | + |
634 | +void |
635 | +marlin_progress_info_set_optype (MarlinProgressInfo *info, |
636 | + MarlinFileOperationType optype) |
637 | +{ |
638 | + G_LOCK (progress_info); |
639 | + /* Should only be set once */ |
640 | + |
641 | + info->optype = optype; |
642 | + |
643 | + G_UNLOCK (progress_info); |
644 | +} |
645 | + |
646 | +void |
647 | +marlin_progress_info_set_remaining_file_count (MarlinProgressInfo *info, |
648 | + int file_count) |
649 | +{ |
650 | + G_LOCK (progress_info); |
651 | + |
652 | + info->file_count = file_count; |
653 | + if (info->total_file_count < 0) { /* Initialized as -1 */ |
654 | + info->total_file_count = file_count; |
655 | + } |
656 | + |
657 | + G_UNLOCK (progress_info); |
658 | +} |
659 | + |
660 | +void |
661 | +marlin_progress_info_decrement_remaining_file_count (MarlinProgressInfo *info) |
662 | +{ |
663 | + G_LOCK (progress_info); |
664 | + |
665 | + info->file_count = info->file_count - 1; |
666 | + |
667 | + G_UNLOCK (progress_info); |
668 | +} |
669 | + |
670 | void |
671 | marlin_progress_info_take_status (MarlinProgressInfo *info, |
672 | char *status) |
673 | { |
674 | G_LOCK (progress_info); |
675 | |
676 | + if (info->title == NULL) { |
677 | + info->title = g_strdup (status); |
678 | + } |
679 | if (eel_strcmp (info->status, status) != 0) { |
680 | g_free (info->status); |
681 | info->status = status; |
682 | @@ -534,6 +719,9 @@ |
683 | { |
684 | G_LOCK (progress_info); |
685 | |
686 | + if (info->title == NULL) { |
687 | + info->title = g_strdup (status); |
688 | + } |
689 | if (eel_strcmp (info->status, status) != 0) { |
690 | g_free (info->status); |
691 | info->status = g_strdup (status); |
692 | |
693 | === modified file 'libcore/marlin-progress-info.h' |
694 | --- libcore/marlin-progress-info.h 2016-06-24 18:59:29 +0000 |
695 | +++ libcore/marlin-progress-info.h 2017-01-14 12:39:17 +0000 |
696 | @@ -26,6 +26,7 @@ |
697 | |
698 | #include <glib-object.h> |
699 | #include <gio/gio.h> |
700 | +#include "pantheon-files-core.h" |
701 | |
702 | /* Match .vapi class Marlin.Progress.Info */ |
703 | #define MARLIN_PROGRESS_TYPE_INFO (marlin_progress_info_get_type ()) |
704 | @@ -81,6 +82,23 @@ |
705 | void marlin_progress_info_set_progress (MarlinProgressInfo *info, |
706 | double current, |
707 | double total); |
708 | +void marlin_progress_info_set_ctype (MarlinProgressInfo *info, |
709 | + const char *ctype); |
710 | +char* marlin_progress_info_get_ctype (MarlinProgressInfo *info); |
711 | +void marlin_progress_info_set_destination_uri (MarlinProgressInfo *info, |
712 | + const char *ctype); |
713 | +char* marlin_progress_info_get_destination_uri (MarlinProgressInfo *info); |
714 | +void marlin_progress_info_set_optype (MarlinProgressInfo *info, |
715 | + MarlinFileOperationType optype); |
716 | +MarlinFileOperationType marlin_progress_info_get_optype (MarlinProgressInfo *info); |
717 | +void marlin_progress_info_set_current_filename (MarlinProgressInfo *info, |
718 | + char *filename); |
719 | +char* marlin_progress_info_get_current_filename (MarlinProgressInfo *info); |
720 | +void marlin_progress_info_set_remaining_file_count (MarlinProgressInfo *info, |
721 | + int no_files); |
722 | +void marlin_progress_info_decrement_remaining_file_count (MarlinProgressInfo *info); |
723 | +int marlin_progress_info_get_remaining_file_count (MarlinProgressInfo *info); |
724 | +int marlin_progress_info_get_total_files (MarlinProgressInfo *info); |
725 | void marlin_progress_info_pulse_progress (MarlinProgressInfo *info); |
726 | |
727 | |
728 | |
729 | === modified file 'libcore/pantheon-files-core-C.vapi' |
730 | --- libcore/pantheon-files-core-C.vapi 2016-12-23 14:29:30 +0000 |
731 | +++ libcore/pantheon-files-core-C.vapi 2017-01-14 12:39:17 +0000 |
732 | @@ -208,6 +208,13 @@ |
733 | public bool get_is_finished (); |
734 | public bool get_is_paused (); |
735 | public GLib.Cancellable get_cancellable (); |
736 | +// public string get_title (); |
737 | + public string get_ctype (); |
738 | + public string get_destination_uri (); |
739 | + public FileOperationType get_optype (); |
740 | + public string get_current_filename (); |
741 | + public int get_remaining_file_count (); |
742 | + public int get_total_file_count (); |
743 | } |
744 | |
745 | [CCode (cheader_filename = "marlin-progress-info-manager.h")] |
746 | |
747 | === modified file 'libwidgets/CMakeLists.txt' |
748 | --- libwidgets/CMakeLists.txt 2016-12-27 18:19:20 +0000 |
749 | +++ libwidgets/CMakeLists.txt 2017-01-14 12:39:17 +0000 |
750 | @@ -37,6 +37,9 @@ |
751 | Chrome/BreadcrumbIconList.vala |
752 | Chrome/ButtonWithMenu.vala |
753 | Chrome/ImgEventBox.vala |
754 | + #~ Chrome/ProgressIndicator.vala |
755 | + #~ Chrome/ProgressIndicatorWithPopover.vala |
756 | + #~ Chrome/ProgressInfoListRow.vala |
757 | View/SearchResults.vala |
758 | Interfaces/SearchableInterface.vala |
759 | Chrome/ViewSwitcher.vala |
760 | |
761 | === modified file 'pantheon-files-daemon/CMakeLists.txt' |
762 | --- pantheon-files-daemon/CMakeLists.txt 2014-08-05 18:18:49 +0000 |
763 | +++ pantheon-files-daemon/CMakeLists.txt 2017-01-14 12:39:17 +0000 |
764 | @@ -1,11 +1,25 @@ |
765 | # Vala stuff |
766 | |
767 | -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) |
768 | -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
769 | -include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
770 | -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../libcore/) |
771 | -include_directories(${CMAKE_CURRENT_BINARY_DIR}/../libwidgets/) |
772 | +set (PKGNAME pantheon-files-daemon) |
773 | + |
774 | +include_directories (${CMAKE_SOURCE_DIR}/libcore/) |
775 | +include_directories (${CMAKE_BINARY_DIR}/libcore/) |
776 | +include_directories (${CMAKE_SOURCE_DIR}/libwidgets/) |
777 | +include_directories (${CMAKE_BINARY_DIR}/libwidgets/) |
778 | + |
779 | find_package(PkgConfig) |
780 | +OPTION (WITH_UNITY "Add Unity launcher support" ON) |
781 | +pkg_check_modules (UNITY unity>=4.0.0) |
782 | +IF (WITH_UNITY AND UNITY_FOUND) |
783 | + set (UNITY_OPTIONS --define=HAVE_UNITY) |
784 | + set (UNITY_PKG unity) |
785 | + include_directories (${UNITY_INCLUDE_DIRS}) |
786 | + link_libraries (${UNITY_LIBRARIES}) |
787 | + link_directories (${UNITY_LIBRARY_DIRS}) |
788 | +ELSE (WITH_UNITY AND UNITY_FOUND) |
789 | + set (UNITY_PKG "") |
790 | +ENDIF (WITH_UNITY AND UNITY_FOUND) |
791 | + |
792 | pkg_check_modules(DEPS REQUIRED |
793 | glib-2.0>=2.29.0 |
794 | gthread-2.0 |
795 | @@ -16,26 +30,43 @@ |
796 | gee-0.8 |
797 | sqlite3 |
798 | dbus-glib-1 |
799 | - libnotify>=0.7.2) |
800 | -set(CFLAGS |
801 | - ${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER} |
802 | -) |
803 | -set(LIB_PATHS |
804 | - ${DEPS_LIBRARY_DIRS} |
805 | -) |
806 | + libnotify>=0.7.2 |
807 | + ${UNITY_PKG}) |
808 | + |
809 | +set(CFLAGS ${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER}) |
810 | +set(LIB_PATHS {DEPS_LIBRARY_DIRS} ${UNITY_LIBRARIES}) |
811 | link_directories(${LIB_PATHS}) |
812 | add_definitions(${CFLAGS}) |
813 | |
814 | -vala_precompile(VALA_C pantheon-files-daemon |
815 | +vala_precompile(VALA_C ${PKGNAME} |
816 | + main.vala |
817 | marlind-tagging.vala |
818 | + QuicklistHandler.vala |
819 | + ProgressHandlerQuicklistInterface.vala |
820 | PACKAGES |
821 | gtk+-3.0 |
822 | gio-2.0 |
823 | gee-0.8 |
824 | sqlite3 |
825 | + dbus-glib-1 |
826 | + libnotify |
827 | + pantheon-files-core |
828 | + pantheon-files-widgets |
829 | + pantheon-files-core-C |
830 | + ${UNITY_PKG} |
831 | OPTIONS |
832 | + --vapidir=${CMAKE_SOURCE_DIR}/libcore |
833 | + --vapidir=${CMAKE_BINARY_DIR}/libcore |
834 | --thread) |
835 | -add_executable(pantheon-files-daemon |
836 | - ${VALA_C} ) |
837 | -target_link_libraries(pantheon-files-daemon ${DEPS_LIBRARIES}) |
838 | -install(TARGETS pantheon-files-daemon RUNTIME DESTINATION bin) |
839 | + |
840 | +add_executable(${PKGNAME} ${VALA_C} ) |
841 | + |
842 | +add_dependencies (${PKGNAME} pantheon-files-core pantheon-files-widgets) |
843 | +target_link_libraries (pantheon-files-daemon pantheon-files-core) |
844 | + |
845 | +IF (WITH_UNITY AND UNITY_FOUND) |
846 | + target_link_libraries (pantheon-files-daemon pantheon-files-core ${UNITY_LIBRARIES}) |
847 | + add_definitions ("-DHAVE_UNITY=1") |
848 | +ENDIF (WITH_UNITY AND UNITY_FOUND) |
849 | + |
850 | +install(TARGETS ${PKGNAME} RUNTIME DESTINATION bin) |
851 | |
852 | === added file 'pantheon-files-daemon/ProgressHandlerQuicklistInterface.vala' |
853 | --- pantheon-files-daemon/ProgressHandlerQuicklistInterface.vala 1970-01-01 00:00:00 +0000 |
854 | +++ pantheon-files-daemon/ProgressHandlerQuicklistInterface.vala 2017-01-14 12:39:17 +0000 |
855 | @@ -0,0 +1,31 @@ |
856 | +/*** |
857 | + Copyright (C) 2015 elementary Developers |
858 | + |
859 | + This program is free software: you can redistribute it and/or modify it |
860 | + under the terms of the GNU Lesser General Public License version 3, as published |
861 | + by the Free Software Foundation. |
862 | + |
863 | + This program is distributed in the hope that it will be useful, but |
864 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
865 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
866 | + PURPOSE. See the GNU General Public License for more details. |
867 | + |
868 | + You should have received a copy of the GNU General Public License along |
869 | + with this program. If not, see <http://www.gnu.org/licenses/>. |
870 | + |
871 | + Authors : Jeremy Wootten <jeremy@elementaryos.org> |
872 | +***/ |
873 | + |
874 | +namespace Marlin { |
875 | + [DBus (name = "org.pantheon.files.ql")] |
876 | + public interface ProgressHandlerQuicklistInterface : Object { |
877 | + public signal void cancel_all_infos (); |
878 | + public signal void show_dialog (); |
879 | + public signal void show_error_message (string msg); /* For debugging use */ |
880 | + |
881 | + public abstract bool build_unity_quicklist () throws IOError; |
882 | + public abstract void update_unity_launcher_entries (bool infos_active, bool info_cancelled) throws IOError; |
883 | + public abstract void progress_changed (double progress) throws IOError; |
884 | + public abstract void initialize () throws IOError; |
885 | + } |
886 | +} |
887 | |
888 | === renamed file 'src/QuicklistHandler.vala' => 'pantheon-files-daemon/QuicklistHandler.vala' |
889 | --- src/QuicklistHandler.vala 2016-06-18 11:25:11 +0000 |
890 | +++ pantheon-files-daemon/QuicklistHandler.vala 2017-01-14 12:39:17 +0000 |
891 | @@ -13,6 +13,9 @@ |
892 | |
893 | You should have received a copy of the GNU General Public License along |
894 | with this program. If not, see <http://www.gnu.org/licenses/>. |
895 | + |
896 | + Authors: Julián Unrrein <junrrein@gmail.com> |
897 | + Jeremy Wootten <jeremy@elementaryos.org> |
898 | ***/ |
899 | |
900 | namespace Marlin { |
901 | @@ -23,27 +26,24 @@ |
902 | public List<Dbusmenu.Menuitem> progress_quicklists = null; |
903 | } |
904 | |
905 | - private QuicklistHandler quicklisthandler_singleton = null; |
906 | - |
907 | - public class QuicklistHandler : Object { |
908 | - |
909 | - public List<Marlin.LauncherEntry> launcher_entries = null; |
910 | - |
911 | - private QuicklistHandler () { |
912 | - this.entry_add (Marlin.APP_DESKTOP); |
913 | - |
914 | - if (this.launcher_entries.length () == 0) { |
915 | - error ("Couldn't find a valid Unity launcher entry."); |
916 | - } else { |
917 | - var bookmarks = Marlin.BookmarkList.get_instance (); |
918 | - |
919 | - bookmarks.contents_changed.connect (() => { |
920 | - debug ("Refreshing Unity dynamic bookmarks."); |
921 | - this.remove_bookmark_quicklists (); |
922 | - this.load_bookmarks (bookmarks); |
923 | - }); |
924 | - } |
925 | + [DBus (name = "org.pantheon.files.ql")] |
926 | + public class QuicklistHandler : Object, ProgressHandlerQuicklistInterface { |
927 | + |
928 | + private enum State { |
929 | + UNINITIALIZED, |
930 | + LOADING, |
931 | + LOADED |
932 | } |
933 | + /* NOTE This runs as a daemon and is started, if necessary, by DBus. Any warning messages |
934 | + * produced by it therefore would not normally appear in the terminal. Use "show_error_message" |
935 | + * signal to produce notifications */ |
936 | + |
937 | + private static QuicklistHandler quicklisthandler_singleton = null; |
938 | + private GLib.List<string> bookmark_list = null; |
939 | + private State state = State.UNINITIALIZED; |
940 | + public List<Marlin.LauncherEntry> launcher_entries; |
941 | + private GLib.File? bookmarks_file = null; |
942 | + private GLib.FileMonitor? bookmarks_monitor = null; |
943 | |
944 | public static unowned QuicklistHandler get_singleton () { |
945 | if (quicklisthandler_singleton == null) |
946 | @@ -52,18 +52,80 @@ |
947 | return quicklisthandler_singleton; |
948 | } |
949 | |
950 | + public void initialize () { |
951 | + if (state != State.UNINITIALIZED) { |
952 | + return; |
953 | + } |
954 | + state = State.LOADING; |
955 | + foreach (var marlin_lentry in launcher_entries) { |
956 | + marlin_lentry.entry.quicklist = null; |
957 | + marlin_lentry.bookmark_quicklists = null; |
958 | + marlin_lentry.progress_quicklists = null; |
959 | + } |
960 | + launcher_entries = null; |
961 | + |
962 | + this.entry_add (Marlin.APP_DESKTOP); |
963 | + |
964 | + load_bookmarks_file_async (); |
965 | + } |
966 | + |
967 | + private QuicklistHandler () { |
968 | + string filename = GLib.Path.build_filename (GLib.Environment.get_user_config_dir (), |
969 | + "gtk-3.0", |
970 | + "bookmarks", |
971 | + null); |
972 | + |
973 | + var file = GLib.File.new_for_path (filename); |
974 | + if (file.query_exists (null)) { |
975 | + bookmarks_file = file; |
976 | + try { |
977 | + bookmarks_monitor = bookmarks_file.monitor (GLib.FileMonitorFlags.SEND_MOVED, null); |
978 | + bookmarks_monitor.set_rate_limit (1000); |
979 | + bookmarks_monitor.changed.connect (on_bookmarks_file_changed); |
980 | + } |
981 | + catch (GLib.Error error) {} |
982 | + } |
983 | + } |
984 | + |
985 | + private void load_bookmarks_file_async () { |
986 | + if (bookmarks_file == null) { |
987 | + state = State.LOADED; |
988 | + return; |
989 | + } |
990 | + state = State.LOADED; |
991 | + bookmarks_file.load_contents_async.begin (null, (obj, res) => { |
992 | + try { |
993 | + uint8[] contents; |
994 | + bookmarks_file.load_contents_async.end (res, out contents, null); |
995 | + if (contents != null) { |
996 | + bookmark_list_from_string ((string)contents); |
997 | + load_bookmarks (); |
998 | + } |
999 | + } |
1000 | + catch (GLib.Error error) {} |
1001 | + }); |
1002 | + } |
1003 | + |
1004 | + private void bookmark_list_from_string (string contents) { |
1005 | + string [] lines = contents.split ("\n"); |
1006 | + foreach (string line in lines) { |
1007 | + if (line[0] == '\0' || line[0] == ' ') { |
1008 | + continue; /* ignore blank lines */ |
1009 | + } |
1010 | + /* Keep both the full uri and the custom label (if any) */ |
1011 | + bookmark_list.append (line); |
1012 | + } |
1013 | + } |
1014 | + |
1015 | private void entry_add (string entry_id) { |
1016 | var unity_lentry = Unity.LauncherEntry.get_for_desktop_id (entry_id); |
1017 | - |
1018 | if (unity_lentry != null) { |
1019 | var marlin_lentry = new Marlin.LauncherEntry (); |
1020 | marlin_lentry.entry = unity_lentry; |
1021 | |
1022 | this.launcher_entries.prepend (marlin_lentry); |
1023 | - |
1024 | /* Ensure dynamic quicklist exists */ |
1025 | Dbusmenu.Menuitem ql = unity_lentry.quicklist; |
1026 | - |
1027 | if (ql == null) { |
1028 | ql = new Dbusmenu.Menuitem (); |
1029 | unity_lentry.quicklist = ql; |
1030 | @@ -76,42 +138,154 @@ |
1031 | var unity_lentry = marlin_lentry.entry; |
1032 | Dbusmenu.Menuitem ql = unity_lentry.quicklist; |
1033 | |
1034 | - if (ql == null) |
1035 | - break; |
1036 | - |
1037 | - foreach (var menuitem in marlin_lentry.bookmark_quicklists) { |
1038 | - ql.child_delete (menuitem); |
1039 | + if (ql != null) { |
1040 | + foreach (var menuitem in marlin_lentry.bookmark_quicklists) { |
1041 | + ql.child_delete (menuitem); |
1042 | + } |
1043 | } |
1044 | |
1045 | marlin_lentry.bookmark_quicklists = null; |
1046 | + bookmark_list = null; |
1047 | } |
1048 | } |
1049 | |
1050 | - private void load_bookmarks (Marlin.BookmarkList bookmarks) { |
1051 | - var bookmark_count = bookmarks.length (); |
1052 | - |
1053 | - for (int index = 0; index < bookmark_count; index++) { |
1054 | - var bookmark = bookmarks.item_at (index); |
1055 | - |
1056 | - if (bookmark.uri_known_not_to_exist ()) |
1057 | - continue; |
1058 | - |
1059 | + private void load_bookmarks () { |
1060 | + int index = -1; |
1061 | + foreach (string line in bookmark_list) { |
1062 | + string [] parts = line.split (" ", 2); |
1063 | + /* First part is full uri and second part is the custom label */ |
1064 | + GLib.List<GLib.File> files = null; |
1065 | + GLib.File file = GLib.File.new_for_uri (parts[0]); |
1066 | + files.append (file); |
1067 | + string label = parts.length > 1 ? parts[1] : file.get_basename (); |
1068 | + index++; |
1069 | foreach (var marlin_lentry in this.launcher_entries) { |
1070 | var unity_lentry = marlin_lentry.entry; |
1071 | Dbusmenu.Menuitem ql = unity_lentry.quicklist; |
1072 | var menuitem = new Dbusmenu.Menuitem (); |
1073 | - |
1074 | - menuitem.property_set ("label", bookmark.label); |
1075 | + menuitem.property_set (Dbusmenu.MENUITEM_PROP_TYPE, |
1076 | + Dbusmenu.CLIENT_TYPES_DEFAULT); |
1077 | + menuitem.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
1078 | + label); |
1079 | menuitem.item_activated.connect (() => { |
1080 | - var location = bookmark.get_location (); |
1081 | - Marlin.Application.get ().create_window (location); |
1082 | + try { |
1083 | + var launcher = GLib.AppInfo.create_from_commandline ("pantheon-files", |
1084 | + null, |
1085 | + GLib.AppInfoCreateFlags.SUPPORTS_URIS); |
1086 | + launcher.launch (files, null); |
1087 | + } catch (GLib.Error e) {} |
1088 | }); |
1089 | |
1090 | ql.child_add_position (menuitem, index); |
1091 | marlin_lentry.bookmark_quicklists.prepend (menuitem); |
1092 | } |
1093 | } |
1094 | - } |
1095 | - |
1096 | + state = State.LOADED; |
1097 | + } |
1098 | + |
1099 | + private void on_bookmarks_file_changed (GLib.File file, GLib.File? other_file, GLib.FileMonitorEvent event_type) { |
1100 | + if (event_type != FileMonitorEvent.CREATED || state == State.LOADING) { |
1101 | + return; |
1102 | + } |
1103 | + |
1104 | + state = State.LOADING; |
1105 | + remove_bookmark_quicklists (); |
1106 | + |
1107 | + load_bookmarks_file_async (); |
1108 | + } |
1109 | + |
1110 | + public bool build_unity_quicklist () { |
1111 | + /* Create menu items for the quicklist */ |
1112 | + foreach (var marlin_lentry in this.launcher_entries) { |
1113 | + if (marlin_lentry.progress_quicklists != null) { |
1114 | + continue; |
1115 | + } |
1116 | + /* Separator between bookmarks and progress items */ |
1117 | + var separator = new Dbusmenu.Menuitem (); |
1118 | + |
1119 | + separator.property_set (Dbusmenu.MENUITEM_PROP_TYPE, |
1120 | + Dbusmenu.CLIENT_TYPES_SEPARATOR); |
1121 | + separator.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
1122 | + "Progress items separator"); |
1123 | + marlin_lentry.progress_quicklists.append (separator); |
1124 | + |
1125 | +#if 0 /* Now use popover but keep possibility of showing a dialog when Files window is closed */ |
1126 | + /* "Show progress window" menu item */ |
1127 | + var show_menuitem = new Dbusmenu.Menuitem (); |
1128 | + |
1129 | + show_menuitem.property_set (Dbusmenu.MENUITEM_PROP_TYPE, |
1130 | + Dbusmenu.CLIENT_TYPES_DEFAULT); |
1131 | + show_menuitem.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
1132 | + _("Show Copy Dialog")); |
1133 | + |
1134 | + show_menuitem.item_activated.connect (() => { |
1135 | + show_dialog (); |
1136 | + }); |
1137 | + |
1138 | + marlin_lentry.progress_quicklists.append (show_menuitem); |
1139 | + |
1140 | + /* "Cancel in-progress operations" menu item */ |
1141 | +#endif |
1142 | + var cancel_menuitem = new Dbusmenu.Menuitem (); |
1143 | + |
1144 | + cancel_menuitem.property_set (Dbusmenu.MENUITEM_PROP_TYPE, |
1145 | + Dbusmenu.CLIENT_TYPES_DEFAULT); |
1146 | + cancel_menuitem.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
1147 | + _("Cancel All In-progress Actions")); |
1148 | + |
1149 | + cancel_menuitem.item_activated.connect (() => { |
1150 | + cancel_all_infos (); |
1151 | + }); |
1152 | + |
1153 | + marlin_lentry.progress_quicklists.append (cancel_menuitem); |
1154 | + } |
1155 | + |
1156 | + return this.launcher_entries.length () > 0; |
1157 | + } |
1158 | + |
1159 | + public void update_unity_launcher_entries (bool infos_active, bool info_cancelled) { |
1160 | + foreach (var marlin_lentry in this.launcher_entries) { |
1161 | + Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
1162 | + |
1163 | + if (infos_active) { |
1164 | + unity_lentry.progress_visible = true; |
1165 | + show_progress_quicklist (marlin_lentry, true); |
1166 | + } else { |
1167 | + unity_lentry.progress_visible = false; |
1168 | + unity_lentry.progress = 0.0; |
1169 | + show_progress_quicklist (marlin_lentry, false); |
1170 | + if (info_cancelled) { |
1171 | + unity_lentry.urgent = true; |
1172 | + |
1173 | + Timeout.add_seconds (2, () => { |
1174 | + unity_lentry.urgent = false; |
1175 | + return false; |
1176 | + }); |
1177 | + } |
1178 | + } |
1179 | + } |
1180 | + } |
1181 | + |
1182 | + private void show_progress_quicklist (Marlin.LauncherEntry marlin_lentry, bool show) { |
1183 | + Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
1184 | + Dbusmenu.Menuitem quicklist = unity_lentry.quicklist; |
1185 | + |
1186 | + foreach (Dbusmenu.Menuitem menuitem in marlin_lentry.progress_quicklists) { |
1187 | + if (show) { |
1188 | + if (menuitem.get_parent () == null) { |
1189 | + quicklist.child_add_position (menuitem, -1); |
1190 | + } |
1191 | + } else { |
1192 | + quicklist.child_delete (menuitem); |
1193 | + } |
1194 | + } |
1195 | + } |
1196 | + |
1197 | + public void progress_changed (double progress) { |
1198 | + foreach (Marlin.LauncherEntry marlin_lentry in this.launcher_entries) { |
1199 | + Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
1200 | + unity_lentry.progress = progress; |
1201 | + } |
1202 | + } |
1203 | } |
1204 | } |
1205 | |
1206 | === added file 'pantheon-files-daemon/main.vala' |
1207 | --- pantheon-files-daemon/main.vala 1970-01-01 00:00:00 +0000 |
1208 | +++ pantheon-files-daemon/main.vala 2017-01-14 12:39:17 +0000 |
1209 | @@ -0,0 +1,68 @@ |
1210 | +/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */ |
1211 | +/* |
1212 | + * Copyright (C) 2010 Jordi Puigdellívol <jordi@gloobus.net> |
1213 | + * Copyright (C) 2015 Elementary Developers |
1214 | + * |
1215 | + * This library is free software; you can redistribute it and/or modify |
1216 | + * it under the terms of the GNU Lesser General Public License |
1217 | + * version 3.0 as published by the Free Software Foundation. |
1218 | + * |
1219 | + * This library is distributed in the hope that it will be useful, |
1220 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1221 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1222 | + * GNU Lesser General Public License version 3.0 for more details. |
1223 | + * |
1224 | + * You should have received a copy of the GNU Lesser General Public |
1225 | + * License along with this library. If not, see |
1226 | + * <http://www.gnu.org/licenses/>. |
1227 | + * |
1228 | + * Authors: Jordi Puigdellívol <jordi@gloobus.net> |
1229 | + * ammonkey <am.monkeyd@gmail.com> |
1230 | + * Jeremy Wootten <jeremy@elementaryos.org> |
1231 | +*/ |
1232 | + |
1233 | + |
1234 | + void on_bus_aquired (DBusConnection conn, string n) { |
1235 | + try { |
1236 | + string name = "/org/pantheon/files/db"; |
1237 | + var object = new MarlinTags (); |
1238 | + conn.register_object (name, object); |
1239 | + message ("MarlinTags object registered with dbus connection name %s", name); |
1240 | + } catch (IOError e) { |
1241 | + error ("Could not register service"); |
1242 | + } |
1243 | + } |
1244 | + void on_ql_bus_aquired (DBusConnection conn) { |
1245 | + uint conn_id = 0; |
1246 | + try { |
1247 | + string name = "/org/pantheon/files/ql"; |
1248 | + Marlin.ProgressHandlerQuicklistInterface object = Marlin.QuicklistHandler.get_singleton (); |
1249 | + conn_id = conn.register_object (name, object); |
1250 | + message ("QuicklistHandler object registered with dbus connection name %s", name); |
1251 | + object.initialize (); |
1252 | + } catch (IOError e) { |
1253 | + error ("Could not register service"); |
1254 | + } |
1255 | + } |
1256 | + |
1257 | + // Exit C function to quit the loop |
1258 | + extern void exit (int exit_code); |
1259 | + |
1260 | + void on_name_lost (DBusConnection connection, string name) { |
1261 | + critical ("Name %s was not acquired", name); |
1262 | + exit (-1); |
1263 | + } |
1264 | + |
1265 | + void main () { |
1266 | + Bus.own_name (BusType.SESSION, "org.pantheon.files.db", BusNameOwnerFlags.NONE, |
1267 | + on_bus_aquired, |
1268 | + () => {}, |
1269 | + on_name_lost); |
1270 | + |
1271 | + Bus.own_name (BusType.SESSION, "org.pantheon.files.ql", BusNameOwnerFlags.NONE, |
1272 | + on_ql_bus_aquired, |
1273 | + () => {}, |
1274 | + on_name_lost); |
1275 | + |
1276 | + new MainLoop ().run (); |
1277 | + } |
1278 | |
1279 | === modified file 'pantheon-files-daemon/marlind-tagging.vala' |
1280 | --- pantheon-files-daemon/marlind-tagging.vala 2016-06-18 11:25:11 +0000 |
1281 | +++ pantheon-files-daemon/marlind-tagging.vala 2017-01-14 12:39:17 +0000 |
1282 | @@ -113,14 +113,12 @@ |
1283 | var uri = escape(raw_uri); |
1284 | |
1285 | var sql = "INSERT OR REPLACE INTO tags (uri,content_type,modified_time) VALUES ('"+uri+"','"+content_type+"',"+modified_time.to_string()+");\n"; |
1286 | - //var c = "INSERT OR IGNORE INTO tags (uri,content_type,modified_time) VALUES ('"+uri+"','"+content_type+"',"+modified_time.to_string()+");\n"; |
1287 | |
1288 | int rc = db.exec (sql, null, null); |
1289 | if (rc != Sqlite.OK) { |
1290 | stderr.printf ("[record_uri: SQL error] %d, %s\n", rc, db.errmsg ()); |
1291 | return false; |
1292 | } |
1293 | - //stdout.printf("[Consult]: %s\n",c); |
1294 | |
1295 | return true; |
1296 | } |
1297 | @@ -143,7 +141,6 @@ |
1298 | stderr.printf ("[record_uri: SQL error] %d, %s\n", rc, db.errmsg ()); |
1299 | return false; |
1300 | } |
1301 | - //stdout.printf("[Consult]: %s\n",sql); |
1302 | |
1303 | return true; |
1304 | } |
1305 | @@ -163,7 +160,6 @@ |
1306 | -1, out stmt); |
1307 | assert (rc == Sqlite.OK); |
1308 | rc = stmt.step(); |
1309 | - |
1310 | vb.open (new VariantType ("as")); |
1311 | |
1312 | switch (rc) { |
1313 | @@ -209,7 +205,6 @@ |
1314 | case Sqlite.ROW: |
1315 | for (col = 0; col < cols; col++) { |
1316 | txt = stmt.column_text(col); |
1317 | - //print ("%s = %s\n", stmt.column_name (col), txt); |
1318 | } |
1319 | break; |
1320 | default: |
1321 | @@ -217,7 +212,6 @@ |
1322 | break; |
1323 | } |
1324 | } while (rc == Sqlite.ROW); |
1325 | - //stdout.printf("[getColor]: %s\n", txt); |
1326 | |
1327 | int ret = int.parse(txt); |
1328 | /* It appears that a db error return -1, we got to check the value just in case */ |
1329 | @@ -309,9 +303,6 @@ |
1330 | } |
1331 | |
1332 | private void upgrade_database () { |
1333 | - |
1334 | - // version 2 |
1335 | - |
1336 | if (!has_column("tags", "content_type")) { |
1337 | message("upgrade_database: adding content_type column to tags"); |
1338 | if (!add_column("tags", "content_type", "TEXT")) |
1339 | @@ -329,52 +320,3 @@ |
1340 | } |
1341 | } |
1342 | } |
1343 | - |
1344 | -/* =============== Main ==================== */ |
1345 | -/*void main (string[] args) { |
1346 | - |
1347 | - MarlinTags t = new MarlinTags(); |
1348 | - |
1349 | - t.openMarlinDB(); |
1350 | - |
1351 | - t.setColor("file:///home/jordi" ,MARLIN_RED); |
1352 | - t.setColor("file:///home/dev" ,MARLIN_YELLOW); |
1353 | - |
1354 | -//t.deleteEntry(File.new_for_path ("/home/dev")); //When deleting files |
1355 | -//t.deleteEntry("/home/documents"); |
1356 | - |
1357 | -//t.clearDB(); |
1358 | -t.showTable("tags"); |
1359 | - |
1360 | - |
1361 | -// DBUS Things |
1362 | -print("\n\nColor for file is %i\n", |
1363 | -t.getColor("file:///home/jordi")); |
1364 | -}*/ |
1365 | - |
1366 | - |
1367 | -void on_bus_aquired (DBusConnection conn) { |
1368 | - try { |
1369 | - conn.register_object ("/org/pantheon/files/db", new MarlinTags ()); |
1370 | - } catch (IOError e) { |
1371 | - error ("Could not register service"); |
1372 | - } |
1373 | -} |
1374 | - |
1375 | -// Exit C function to quit the loop |
1376 | -extern void exit (int exit_code); |
1377 | - |
1378 | -void on_bus_lost (DBusConnection connection, string name) { |
1379 | - critical ("Could not aquire name."); |
1380 | - exit (-1); |
1381 | -} |
1382 | - |
1383 | -void main () { |
1384 | - Bus.own_name (BusType.SESSION, "org.pantheon.files.db", BusNameOwnerFlags.NONE, |
1385 | - on_bus_aquired, |
1386 | - () => {}, |
1387 | - on_bus_lost); |
1388 | - |
1389 | - new MainLoop ().run (); |
1390 | -} |
1391 | - |
1392 | |
1393 | === added file 'pantheon-files-daemon/pantheon-files-daemon.vapi' |
1394 | --- pantheon-files-daemon/pantheon-files-daemon.vapi 1970-01-01 00:00:00 +0000 |
1395 | +++ pantheon-files-daemon/pantheon-files-daemon.vapi 2017-01-14 12:39:17 +0000 |
1396 | @@ -0,0 +1,28 @@ |
1397 | +/*** |
1398 | + Copyright (C) 2015 elementary Developers |
1399 | + |
1400 | + This program is free software: you can redistribute it and/or modify it |
1401 | + under the terms of the GNU Lesser General Public License version 3, as published |
1402 | + by the Free Software Foundation. |
1403 | + |
1404 | + This program is distributed in the hope that it will be useful, but |
1405 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
1406 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1407 | + PURPOSE. See the GNU General Public License for more details. |
1408 | + |
1409 | + You should have received a copy of the GNU General Public License along |
1410 | + with this program. If not, see <http://www.gnu.org/licenses/>. |
1411 | + |
1412 | + Authors : Jeremy Wootten <jeremy@elementaryos.org> |
1413 | +***/ |
1414 | + |
1415 | +[DBus (name = "org.pantheon.files.ql")] |
1416 | +interface ProgressHandlerQuicklistInterface : Object { |
1417 | + public signal void cancel_all_infos (); |
1418 | + public signal void show_dialog (); |
1419 | + |
1420 | + public abstract async bool build_unity_quicklist () throws IOError; |
1421 | + public abstract async void update_unity_launcher_entries (bool infos_active, bool info_cancelled) throws IOError; |
1422 | + public abstract async void progress_changed (double progress) throws IOError; |
1423 | + |
1424 | +} |
1425 | |
1426 | === modified file 'src/Application.vala' |
1427 | --- src/Application.vala 2016-12-31 19:42:09 +0000 |
1428 | +++ src/Application.vala 2017-01-14 12:39:17 +0000 |
1429 | @@ -26,10 +26,11 @@ |
1430 | public class Marlin.Application : Granite.Application { |
1431 | |
1432 | private VolumeMonitor volume_monitor; |
1433 | - private Marlin.Progress.UIHandler progress_handler; |
1434 | + public Marlin.Progress.UIHandler progress_handler {get; private set;} |
1435 | private Marlin.ClipboardManager clipboard; |
1436 | private Marlin.Thumbnailer thumbnailer; |
1437 | private Gtk.RecentManager recent; |
1438 | + private double current_progress = 0.0; |
1439 | |
1440 | private const int MARLIN_ACCEL_MAP_SAVE_DELAY = 15; |
1441 | private const uint MAX_WINDOWS = 25; |
1442 | @@ -88,12 +89,15 @@ |
1443 | Marlin.IconInfo.clear_caches (); |
1444 | }); |
1445 | |
1446 | - progress_handler = new Marlin.Progress.UIHandler (this); |
1447 | - |
1448 | this.clipboard = Marlin.ClipboardManager.get_for_display (); |
1449 | this.thumbnailer = Marlin.Thumbnailer.get (); |
1450 | this.recent = new Gtk.RecentManager (); |
1451 | |
1452 | + progress_handler = new Marlin.Progress.UIHandler (this); |
1453 | + progress_handler.new_progress_info.connect (on_uihandler_new_progress_info); |
1454 | + progress_handler.show_progress.connect (on_uihandler_show_progress); |
1455 | + progress_handler.overall_progress_changed.connect (on_uihandler_overall_progress_changed); |
1456 | + progress_handler.completed.connect (on_uihandler_completed); |
1457 | plugins = new Marlin.PluginManager (Config.PLUGIN_DIR); |
1458 | |
1459 | /**TODO** move the volume manager here? */ |
1460 | @@ -102,12 +106,27 @@ |
1461 | this.volume_monitor = VolumeMonitor.get (); |
1462 | this.volume_monitor.mount_removed.connect (mount_removed_callback); |
1463 | |
1464 | -#if HAVE_UNITY |
1465 | - QuicklistHandler.get_singleton (); |
1466 | -#endif |
1467 | - |
1468 | window_count = 0; |
1469 | - this.window_added.connect_after (() => {window_count++;}); |
1470 | + this.window_added.connect ((w) => { |
1471 | + window_count++; |
1472 | + if (progress_handler.get_active_info_count () > 0) { |
1473 | + /* Files window may previously have been closed, or a new window added with |
1474 | + * file operations ongoing. In this case, we need to show the progress indicator |
1475 | + * in the header bar. |
1476 | + */ |
1477 | + Timeout.add (200, () => { |
1478 | + /* Allow time for the top menu to be realized */ |
1479 | + var win = (Marlin.View.Window)w; |
1480 | + foreach (Marlin.Progress.Info info in progress_handler.get_active_info_list ()) { |
1481 | + win.add_progress_info (info); |
1482 | + } |
1483 | + win.show_progress (true); |
1484 | + win.overall_progress_changed (current_progress); |
1485 | + return false; |
1486 | + }); |
1487 | + } |
1488 | + }); |
1489 | + |
1490 | this.window_removed.connect (() => { |
1491 | window_count--; |
1492 | }); |
1493 | @@ -222,8 +241,9 @@ |
1494 | |
1495 | public new void quit () { |
1496 | /* Protect against holding Ctrl-Q down */ |
1497 | - if (quitting) |
1498 | + if (quitting) { |
1499 | return; |
1500 | + } |
1501 | |
1502 | quitting = true; |
1503 | unowned List<Gtk.Window> window_list = this.get_windows (); |
1504 | @@ -248,6 +268,34 @@ |
1505 | } |
1506 | } |
1507 | |
1508 | + private void on_uihandler_new_progress_info (Marlin.Progress.Info info) { |
1509 | + /* Notify each window */ |
1510 | + foreach (var window in this.get_windows ()) { |
1511 | + ((Marlin.View.Window)window).add_progress_info (info); |
1512 | + } |
1513 | + } |
1514 | + |
1515 | + private void on_uihandler_show_progress (bool show) { |
1516 | + /* Notify each window */ |
1517 | + foreach (var window in this.get_windows ()) { |
1518 | + ((Marlin.View.Window)window).show_progress (show); |
1519 | + } |
1520 | + } |
1521 | + |
1522 | + private void on_uihandler_overall_progress_changed (double progress) { |
1523 | + /* Notify each window */ |
1524 | + foreach (var window in this.get_windows ()) { |
1525 | + ((Marlin.View.Window)window).overall_progress_changed (progress); |
1526 | + } |
1527 | + current_progress = progress; |
1528 | + } |
1529 | + |
1530 | + private void on_uihandler_completed () { |
1531 | + if (get_windows () != null) { |
1532 | + current_progress = 0.0; |
1533 | + } |
1534 | + } |
1535 | + |
1536 | private void init_schemas () { |
1537 | /* GSettings parameters */ |
1538 | Preferences.settings = new Settings ("org.pantheon.files.preferences"); |
1539 | |
1540 | === modified file 'src/CMakeLists.txt' |
1541 | --- src/CMakeLists.txt 2016-12-27 18:19:20 +0000 |
1542 | +++ src/CMakeLists.txt 2017-01-14 12:39:17 +0000 |
1543 | @@ -58,14 +58,8 @@ |
1544 | set (PLANK_OPTIONS --define=HAVE_PLANK_0_11) |
1545 | endif () |
1546 | |
1547 | -set (CFLAGS |
1548 | - ${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER} |
1549 | -) |
1550 | - |
1551 | -set (LIB_PATHS |
1552 | - ${DEPS_LIBRARY_DIRS} |
1553 | -) |
1554 | - |
1555 | +set (CFLAGS ${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER}) |
1556 | +set (LIB_PATHS ${DEPS_LIBRARY_DIRS}) |
1557 | link_directories (${LIB_PATHS}) |
1558 | add_definitions (${CFLAGS} -O2) |
1559 | |
1560 | @@ -77,7 +71,6 @@ |
1561 | marlin-deep-count.vala |
1562 | ProgressUIHandler.vala |
1563 | TextRenderer.vala |
1564 | - QuicklistHandler.vala |
1565 | ClipboardManager.vala |
1566 | Dialogs/AbstractPropertiesDialog.vala |
1567 | Dialogs/ChooseAppDialog.vala |
1568 | @@ -98,6 +91,7 @@ |
1569 | View/Sidebar.vala |
1570 | View/Slot.vala |
1571 | View/Miller.vala |
1572 | + ${CMAKE_SOURCE_DIR}/pantheon-files-daemon/ProgressHandlerQuicklistInterface.vala |
1573 | View/Widgets/AbstractEditableLabel.vala |
1574 | View/Widgets/BreadcrumbsEntry.vala |
1575 | View/Widgets/DiskRenderer.vala |
1576 | @@ -106,10 +100,11 @@ |
1577 | View/Widgets/MultiLineEditableLabel.vala |
1578 | View/Widgets/OverlayBar.vala |
1579 | View/Widgets/PermissionButton.vala |
1580 | - View/Widgets/ProgressInfoWidget.vala |
1581 | View/Widgets/SingleLineEditableLabel.vala |
1582 | View/Widgets/TopMenu.vala |
1583 | - |
1584 | + View/Widgets/ProgressIndicator.vala |
1585 | + View/Widgets/ProgressIndicatorWithPopover.vala |
1586 | + View/Widgets/ProgressInfoListRow.vala |
1587 | PACKAGES |
1588 | gtk+-3.0 |
1589 | gio-2.0 |
1590 | @@ -162,6 +157,7 @@ |
1591 | View/Sidebar.vala |
1592 | View/Slot.vala |
1593 | View/Miller.vala |
1594 | + ${CMAKE_SOURCE_DIR}/pantheon-files-daemon/ProgressHandlerQuicklistInterface.vala |
1595 | View/Widgets/AbstractEditableLabel.vala |
1596 | View/Widgets/BreadcrumbsEntry.vala |
1597 | View/Widgets/DiskRenderer.vala |
1598 | @@ -170,10 +166,11 @@ |
1599 | View/Widgets/MultiLineEditableLabel.vala |
1600 | View/Widgets/OverlayBar.vala |
1601 | View/Widgets/PermissionButton.vala |
1602 | - View/Widgets/ProgressInfoWidget.vala |
1603 | View/Widgets/SingleLineEditableLabel.vala |
1604 | View/Widgets/TopMenu.vala |
1605 | - |
1606 | + View/Widgets/ProgressIndicator.vala |
1607 | + View/Widgets/ProgressIndicatorWithPopover.vala |
1608 | + View/Widgets/ProgressInfoListRow.vala |
1609 | PACKAGES |
1610 | gtk+-3.0 |
1611 | gio-2.0 |
1612 | |
1613 | === modified file 'src/ProgressUIHandler.vala' |
1614 | --- src/ProgressUIHandler.vala 2016-12-18 22:01:14 +0000 |
1615 | +++ src/ProgressUIHandler.vala 2017-01-14 12:39:17 +0000 |
1616 | @@ -20,27 +20,47 @@ |
1617 | Jeremy Wootten <jeremy@elementaryos.org> |
1618 | ***/ |
1619 | |
1620 | -/*** One instance of this class is owned by the application and handles UI for file transfers initiated by |
1621 | - * of the app windows. Feedback is provided by a dialog window which appears if a transfer takes longer than |
1622 | - * approximately 1 second. The unity launcher is also updated if present and a notification is sent of the |
1623 | - * completion of the operation unless it was cancelled by the user. |
1624 | -***/ |
1625 | +/** This class controls the UI relating to file operations in progress (Unity launchers, notifications and signals |
1626 | + * to progress indicators) but does not itself display any widgets. Displayed widgets are in libwidgets. |
1627 | + * **/ |
1628 | public class Marlin.Progress.UIHandler : Object { |
1629 | - |
1630 | private Marlin.Progress.InfoManager manager = null; |
1631 | -#if HAVE_UNITY |
1632 | - private Marlin.QuicklistHandler quicklist_handler = null; |
1633 | -#endif |
1634 | - private Gtk.Dialog progress_window = null; |
1635 | - private Gtk.Widget window_vbox = null; |
1636 | + private ProgressHandlerQuicklistInterface qldaemon; |
1637 | + private Marlin.Application application; |
1638 | + |
1639 | private uint active_infos = 0; |
1640 | - |
1641 | - private Marlin.Application application; |
1642 | + private bool updating_overall_progress = false; |
1643 | + |
1644 | + private const string ACTION_DETAILS = "details"; |
1645 | + private const string TITLE = _("File Manager Operations"); |
1646 | + private const string ICON_NAME = "system-file-manager"; |
1647 | + private const int ICON_SIZE = 64; |
1648 | + private const string CANCELLED_ICON_NAME = "dialog-warning"; |
1649 | + |
1650 | + public signal void overall_progress_changed (double progress); |
1651 | + public signal void show_progress (bool show); |
1652 | + public signal void new_progress_info (Marlin.Progress.Info info); |
1653 | + public signal void completed (); |
1654 | |
1655 | public UIHandler (Marlin.Application app) { |
1656 | this.manager = new Marlin.Progress.InfoManager (); |
1657 | this.application = app; |
1658 | |
1659 | + try { |
1660 | + qldaemon = Bus.get_proxy_sync (BusType.SESSION, "org.pantheon.files.ql", |
1661 | + "/org/pantheon/files/ql"); |
1662 | + qldaemon.cancel_all_infos.connect (() => { |
1663 | + cancel_all (); |
1664 | + }); |
1665 | + |
1666 | + qldaemon.show_error_message.connect (show_daemon_notification); |
1667 | + |
1668 | + qldaemon.initialize (); |
1669 | + |
1670 | + } catch (IOError e) { |
1671 | + stderr.printf ("%s\n", e.message); |
1672 | + } |
1673 | + |
1674 | manager.new_progress_info.connect ((info) => { |
1675 | info.started.connect (progress_info_started_cb); |
1676 | }); |
1677 | @@ -72,27 +92,25 @@ |
1678 | private void progress_info_started_cb (Marlin.Progress.Info info) { |
1679 | application.hold (); |
1680 | |
1681 | - if (info == null || !(info is Marlin.Progress.Info) || |
1682 | - info.get_is_finished () || info.get_cancellable ().is_cancelled ()) { |
1683 | - |
1684 | - return; |
1685 | - } |
1686 | - |
1687 | - this.active_infos++; |
1688 | - info.finished.connect (progress_info_finished_cb); |
1689 | - |
1690 | - var operation_running = false; |
1691 | + info.finished.connect (() => { |
1692 | + debug ("Release application"); |
1693 | + application.release (); |
1694 | + }); |
1695 | + |
1696 | + bool operation_running = false; |
1697 | + /* Do not create progress info widget until operation has been running for at least 1 seconds |
1698 | + * not including time while paused. |
1699 | + */ |
1700 | Timeout.add_full (GLib.Priority.LOW, 500, () => { |
1701 | if (info == null || !(info is Marlin.Progress.Info) || |
1702 | info.get_is_finished () || info.get_cancellable ().is_cancelled ()) { |
1703 | |
1704 | return false; |
1705 | } |
1706 | - |
1707 | if (info.get_is_paused ()) { |
1708 | return true; |
1709 | } else if (operation_running && !info.get_is_finished ()) { |
1710 | - add_progress_info_to_window (info); |
1711 | + handle_new_progress_info (info); |
1712 | return false; |
1713 | } else { |
1714 | operation_running = true; |
1715 | @@ -101,13 +119,13 @@ |
1716 | }); |
1717 | } |
1718 | |
1719 | - private void add_progress_info_to_window (Marlin.Progress.Info info) { |
1720 | - if (this.active_infos == 1) { |
1721 | - /* This is the only active operation, present the window */ |
1722 | - add_to_window (info); |
1723 | - (this.progress_window as Gtk.Window).present (); |
1724 | - } else if (this.progress_window.visible) { |
1725 | - add_to_window (info); |
1726 | + private void handle_new_progress_info (Marlin.Progress.Info info) { |
1727 | + this.active_infos++; |
1728 | + info.finished.connect (progress_info_finished_cb); |
1729 | + new_progress_info (info); |
1730 | + |
1731 | + if (this.active_infos > 0) { |
1732 | + show_progress (true); |
1733 | } |
1734 | |
1735 | #if HAVE_UNITY |
1736 | @@ -115,46 +133,7 @@ |
1737 | #endif |
1738 | } |
1739 | |
1740 | - private void add_to_window (Marlin.Progress.Info info) { |
1741 | - ensure_window (); |
1742 | - |
1743 | - var progress_widget = new Marlin.Progress.InfoWidget (info); |
1744 | - (this.window_vbox as Gtk.Box).pack_start (progress_widget, false, false, 6); |
1745 | - |
1746 | - progress_widget.show (); |
1747 | - if (this.progress_window.visible) { |
1748 | - (this.progress_window as Gtk.Window).present (); |
1749 | - } |
1750 | - } |
1751 | - |
1752 | - private void ensure_window () { |
1753 | - if (this.progress_window == null) { |
1754 | - /* This provides an undeletable, unminimisable window in which to show the info widgets */ |
1755 | - this.progress_window = new Gtk.Dialog (); |
1756 | - this.progress_window.resizable = false; |
1757 | - this.progress_window.deletable = false; |
1758 | - this.progress_window.title = _("File Operations"); |
1759 | - this.progress_window.set_wmclass ("file_progress", "Marlin"); |
1760 | - this.progress_window.icon_name = "system-file-manager"; |
1761 | - |
1762 | - this.window_vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 5); |
1763 | - |
1764 | - this.progress_window.get_content_area ().set_border_width (10); |
1765 | - this.progress_window.get_content_area ().add (this.window_vbox); |
1766 | - this.window_vbox.show (); |
1767 | - |
1768 | - this.progress_window.delete_event.connect ((widget, event) => { |
1769 | - widget.hide (); |
1770 | - return true; |
1771 | - }); |
1772 | - } |
1773 | - |
1774 | - progress_window.set_transient_for (application.get_active_window ()); |
1775 | - } |
1776 | - |
1777 | private void progress_info_finished_cb (Marlin.Progress.Info info) { |
1778 | - application.release (); |
1779 | - |
1780 | if (active_infos > 0) { |
1781 | this.active_infos--; |
1782 | /* Only notify if application is not focussed. Add a delay |
1783 | @@ -172,23 +151,26 @@ |
1784 | } else { |
1785 | warning ("Attempt to decrement zero active infos"); |
1786 | } |
1787 | - /* For rapid file transfers this can get called before progress window was been created */ |
1788 | - if (active_infos < 1 && progress_window != null && progress_window.visible) { |
1789 | - (this.progress_window as Gtk.Window).hide (); |
1790 | + |
1791 | + if (active_infos < 1) { |
1792 | + show_progress (false); |
1793 | } |
1794 | #if HAVE_UNITY |
1795 | update_unity_launcher (info, false); |
1796 | #endif |
1797 | + show_operation_complete_notification (info, active_infos < 1); |
1798 | } |
1799 | |
1800 | private void show_operation_complete_notification (Marlin.Progress.Info info, bool all_finished) { |
1801 | + /* Some operations may have been cancelled or not successful */ |
1802 | + string result; |
1803 | if (info.get_cancellable ().is_cancelled ()) { |
1804 | return; /* No notification of cancellation action required */ |
1805 | + } else { |
1806 | + /* TRANSLATORS: %s will be replaced by the title of the file operation */ |
1807 | + result = (_("Completed %s")).printf (info.get_title ()); |
1808 | } |
1809 | |
1810 | - /// TRANSLATORS: %s will be replaced by the title of the file operation |
1811 | - var result = (_("Completed %s")).printf (info.get_title ()); |
1812 | - |
1813 | if (all_finished) { |
1814 | result = result + "\n" + _("All file operations have ended"); |
1815 | } |
1816 | @@ -199,101 +181,48 @@ |
1817 | application.send_notification ("Pantheon Files Operation", complete_notification); |
1818 | } |
1819 | |
1820 | + private void show_daemon_notification (string msg) { |
1821 | + var notification = new GLib.Notification (_("QuicklistHandler message")); |
1822 | + notification.set_body (msg); |
1823 | + notification.set_icon (new GLib.ThemedIcon (Marlin.ICON_APP_LOGO)); |
1824 | + application.send_notification ("Pantheon Files Operation", notification); |
1825 | + } |
1826 | + |
1827 | #if HAVE_UNITY |
1828 | private void update_unity_launcher (Marlin.Progress.Info info, |
1829 | bool added) { |
1830 | |
1831 | - if (this.quicklist_handler == null) { |
1832 | - this.quicklist_handler = QuicklistHandler.get_singleton (); |
1833 | - |
1834 | - if (this.quicklist_handler == null) |
1835 | - return; |
1836 | - |
1837 | - build_unity_quicklist (); |
1838 | - } |
1839 | - |
1840 | - foreach (var marlin_lentry in this.quicklist_handler.launcher_entries) |
1841 | - update_unity_launcher_entry (info, marlin_lentry); |
1842 | - |
1843 | - if (added) |
1844 | - info.progress_changed.connect (unity_progress_changed); |
1845 | - } |
1846 | - |
1847 | - private void build_unity_quicklist () { |
1848 | - /* Create menu items for the quicklist */ |
1849 | - foreach (var marlin_lentry in this.quicklist_handler.launcher_entries) { |
1850 | - /* Separator between bookmarks and progress items */ |
1851 | - var separator = new Dbusmenu.Menuitem (); |
1852 | - |
1853 | - separator.property_set (Dbusmenu.MENUITEM_PROP_TYPE, |
1854 | - Dbusmenu.CLIENT_TYPES_SEPARATOR); |
1855 | - separator.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
1856 | - "Progress items separator"); |
1857 | - marlin_lentry.progress_quicklists.append (separator); |
1858 | - |
1859 | - /* "Show progress window" menu item */ |
1860 | - var show_menuitem = new Dbusmenu.Menuitem (); |
1861 | - |
1862 | - show_menuitem.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
1863 | - _("Show Copy Dialog")); |
1864 | - |
1865 | - show_menuitem.item_activated.connect (() => { |
1866 | - (this.progress_window as Gtk.Window).present (); |
1867 | - }); |
1868 | - |
1869 | - marlin_lentry.progress_quicklists.append (show_menuitem); |
1870 | - |
1871 | - /* "Cancel in-progress operations" menu item */ |
1872 | - var cancel_menuitem = new Dbusmenu.Menuitem (); |
1873 | - |
1874 | - cancel_menuitem.property_set (Dbusmenu.MENUITEM_PROP_LABEL, |
1875 | - _("Cancel All In-progress Actions")); |
1876 | - |
1877 | - cancel_menuitem.item_activated.connect (() => { |
1878 | - unowned List<Marlin.Progress.Info> infos = this.manager.get_all_infos (); |
1879 | - |
1880 | - foreach (var info in infos) |
1881 | - info.cancel (); |
1882 | - }); |
1883 | - |
1884 | - marlin_lentry.progress_quicklists.append (cancel_menuitem); |
1885 | - } |
1886 | - } |
1887 | - |
1888 | - private void update_unity_launcher_entry (Marlin.Progress.Info info, |
1889 | - Marlin.LauncherEntry marlin_lentry) { |
1890 | - Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
1891 | - |
1892 | - if (this.active_infos > 0) { |
1893 | - unity_lentry.progress_visible = true; |
1894 | - unity_progress_changed (); |
1895 | - show_unity_quicklist (marlin_lentry, true); |
1896 | - } else { |
1897 | - unity_lentry.progress_visible = false; |
1898 | - unity_lentry.progress = 0.0; |
1899 | - show_unity_quicklist (marlin_lentry, false); |
1900 | - } |
1901 | - } |
1902 | - |
1903 | - private void show_unity_quicklist (Marlin.LauncherEntry marlin_lentry, |
1904 | - bool show) { |
1905 | - |
1906 | - Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
1907 | - Dbusmenu.Menuitem quicklist = unity_lentry.quicklist; |
1908 | - |
1909 | - foreach (Dbusmenu.Menuitem menuitem in marlin_lentry.progress_quicklists) { |
1910 | - var parent = menuitem.get_parent (); |
1911 | - if (show) { |
1912 | - if (parent == null) { |
1913 | - quicklist.child_add_position (menuitem, -1); |
1914 | + if (this.qldaemon == null) { |
1915 | + return; |
1916 | + } |
1917 | + |
1918 | + /* Active_infos has already been decremented when info is finished or cancelled, |
1919 | + * or incremented when info has been added */ |
1920 | + try { |
1921 | + if (qldaemon.build_unity_quicklist ()) { |
1922 | + qldaemon.update_unity_launcher_entries (this.active_infos > 0, |
1923 | + info.get_cancellable ().is_cancelled ()); |
1924 | + if (active_infos > 0) { |
1925 | + update_overall_progress (); |
1926 | } |
1927 | - } else if (parent != null && parent == quicklist) { |
1928 | - quicklist.child_delete (menuitem); |
1929 | } |
1930 | + } catch (IOError e) { |
1931 | + warning ("ProgressUIHandler unable to create quicklist - %s", e.message); |
1932 | + } |
1933 | + |
1934 | + if (added) { |
1935 | + info.progress_changed.connect (update_overall_progress); |
1936 | } |
1937 | } |
1938 | - |
1939 | - private void unity_progress_changed () { |
1940 | +#endif |
1941 | + |
1942 | + private void update_overall_progress () { |
1943 | + /* Prevent re-entry */ |
1944 | + if (updating_overall_progress) { |
1945 | + return; |
1946 | + } |
1947 | + updating_overall_progress = true; |
1948 | + |
1949 | double progress = 0; |
1950 | double current = 0; |
1951 | double total = 0; |
1952 | @@ -319,11 +248,20 @@ |
1953 | if (progress > 1.0) |
1954 | progress = 1.0; |
1955 | |
1956 | - foreach (Marlin.LauncherEntry marlin_lentry in this.quicklist_handler.launcher_entries) { |
1957 | - Unity.LauncherEntry unity_lentry = marlin_lentry.entry; |
1958 | - unity_lentry.progress = progress; |
1959 | + overall_progress_changed (progress); |
1960 | + |
1961 | + /* Unity launcher shows a single progress bar which shows the overall progress of all the |
1962 | + * active file operations. |
1963 | + */ |
1964 | + |
1965 | +#if HAVE_UNITY |
1966 | + try { |
1967 | + qldaemon.progress_changed (progress); |
1968 | + } catch (GLib.IOError e) { |
1969 | + warning ("ProgressUIHandler unable to update Unity Launcher progress - %s", e.message); |
1970 | } |
1971 | +#endif |
1972 | + |
1973 | + updating_overall_progress = false; |
1974 | } |
1975 | -#endif |
1976 | - |
1977 | } |
1978 | |
1979 | === modified file 'src/View/Slot.vala' |
1980 | --- src/View/Slot.vala 2016-09-21 18:27:17 +0000 |
1981 | +++ src/View/Slot.vala 2017-01-14 12:39:17 +0000 |
1982 | @@ -426,7 +426,7 @@ |
1983 | } |
1984 | |
1985 | if (dir_view != null) { |
1986 | - dir_view.close (); |
1987 | + dir_view.close (); /* stop signal handlers running during destruction */ |
1988 | disconnect_dir_view_signals (); |
1989 | } |
1990 | } |
1991 | |
1992 | === added file 'src/View/Widgets/ProgressIndicator.vala' |
1993 | --- src/View/Widgets/ProgressIndicator.vala 1970-01-01 00:00:00 +0000 |
1994 | +++ src/View/Widgets/ProgressIndicator.vala 2017-01-14 12:39:17 +0000 |
1995 | @@ -0,0 +1,105 @@ |
1996 | +/*** |
1997 | + Copyright (C) 2015 ELementary Developers |
1998 | + |
1999 | + This program is free software: you can redistribute it and/or modify it |
2000 | + under the terms of the GNU Lesser General Public License version 3, as published |
2001 | + by the Free Software Foundation. |
2002 | + |
2003 | + This program is distributed in the hope that it will be useful, but |
2004 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
2005 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2006 | + PURPOSE. See the GNU General Public License for more details. |
2007 | + |
2008 | + You should have received a copy of the GNU General Public License along |
2009 | + with this program. If not, see <http://www.gnu.org/licenses/>. |
2010 | + |
2011 | + Authors : Jeremy Wootten <jeremy@elementaryos.org> |
2012 | +***/ |
2013 | + |
2014 | + |
2015 | +namespace Marlin.View.Chrome { |
2016 | + public class ProgressIndicator : Gtk.DrawingArea { |
2017 | + double fraction = 0.0; |
2018 | + double hole_fraction = 0.0; |
2019 | + |
2020 | + public ProgressIndicator (int height) { |
2021 | + set_size_request (height ,height); |
2022 | + |
2023 | + draw.connect (on_draw); |
2024 | + show (); |
2025 | + } |
2026 | + |
2027 | + public void set_fraction (double f) { |
2028 | + fraction = f.clamp (0.0, 1.0); |
2029 | + queue_draw (); |
2030 | + } |
2031 | + |
2032 | + public void set_hole_fraction (double f) { |
2033 | + hole_fraction = f.clamp (0.0, 1.0); |
2034 | + } |
2035 | + |
2036 | + public bool on_draw (Cairo.Context context) { |
2037 | + int height = get_allocated_height (); |
2038 | + int width = get_allocated_width (); |
2039 | + |
2040 | + double xc = width / 2.0; |
2041 | + double yc = height / 2.0; |
2042 | + |
2043 | + double outer_radius = yc - 1.0; |
2044 | + |
2045 | + draw_doughnut (context, xc, yc, outer_radius); |
2046 | + |
2047 | + return true; |
2048 | + } |
2049 | + |
2050 | + private void draw_doughnut (Cairo.Context cr, double center_x, double center_y, double outer_radius) { |
2051 | + |
2052 | + double hole_radius = outer_radius * hole_fraction; |
2053 | + double thickness = (outer_radius - hole_radius); |
2054 | + double middle_radius = hole_radius + thickness / 2.0; // middle radius |
2055 | + |
2056 | + double angle1 = - Math.PI / 2.0; // 12 o'clock |
2057 | + double angle2 = angle1 + 2*Math.PI; // full circle |
2058 | + double angle3 = angle1 + 2 * Math.PI * fraction; // progress angle |
2059 | + |
2060 | + Gdk.RGBA color = {}; |
2061 | + |
2062 | + cr.save (); |
2063 | + |
2064 | + Cairo.Pattern pat; |
2065 | + /* Draw trough */ |
2066 | + color = {0.96,0.96,0.96,1.0}; /* TODO Get color, gradient etc from gtk.css */ |
2067 | + var shade1 = 0.9; |
2068 | + var shade2 = 1.0; |
2069 | + pat = new Cairo.Pattern.linear (0.0, 0.0, 0.0, 2 * center_y); |
2070 | + pat.add_color_stop_rgb (0.0, color.red * shade1, color.green * shade1, color.blue * shade1); |
2071 | + pat.add_color_stop_rgb (1.0, color.red * shade2, color.green * shade2, color.blue * shade2); |
2072 | + cr.set_source (pat); |
2073 | + cr.arc (center_x, center_y, middle_radius, angle1, angle2); |
2074 | + cr.set_line_width (thickness - 2.0); |
2075 | + cr.stroke (); |
2076 | + |
2077 | + |
2078 | + /* Draw progress */ |
2079 | + color.parse ("#3d9bda"); /* TODO Get color, gradient etc from gtk.css */ |
2080 | + shade1 = 1.3; |
2081 | + shade2 = 1.08; |
2082 | + |
2083 | + pat = new Cairo.Pattern.linear (0.0, 0.0, 0.0, 2 * center_y); |
2084 | + pat.add_color_stop_rgb (0.0, 1.0, 1.0, 1.0); |
2085 | + pat.add_color_stop_rgb (0.1, color.red * shade1, color.green * shade1, color.blue * shade1); |
2086 | + pat.add_color_stop_rgb (1.0, color.red * shade2, color.green * shade2, color.blue * shade2); |
2087 | + |
2088 | + cr.set_source (pat); |
2089 | + cr.arc (center_x, center_y, middle_radius, angle1, angle3); |
2090 | + cr.set_line_width (thickness); |
2091 | + cr.stroke (); |
2092 | + |
2093 | + cr.restore (); |
2094 | + |
2095 | + } |
2096 | + } |
2097 | + |
2098 | + |
2099 | + |
2100 | +} |
2101 | |
2102 | === added file 'src/View/Widgets/ProgressIndicatorWithPopover.vala' |
2103 | --- src/View/Widgets/ProgressIndicatorWithPopover.vala 1970-01-01 00:00:00 +0000 |
2104 | +++ src/View/Widgets/ProgressIndicatorWithPopover.vala 2017-01-14 12:39:17 +0000 |
2105 | @@ -0,0 +1,121 @@ |
2106 | +/*** |
2107 | + Copyright (C) 2015 ELementary Developers |
2108 | + |
2109 | + This program is free software: you can redistribute it and/or modify it |
2110 | + under the terms of the GNU Lesser General Public License version 3, as published |
2111 | + by the Free Software Foundation. |
2112 | + |
2113 | + This program is distributed in the hope that it will be useful, but |
2114 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
2115 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2116 | + PURPOSE. See the GNU General Public License for more details. |
2117 | + |
2118 | + You should have received a copy of the GNU General Public License along |
2119 | + with this program. If not, see <http://www.gnu.org/licenses/>. |
2120 | + |
2121 | + Authors : Jeremy Wootten <jeremy@elementaryos.org> |
2122 | +***/ |
2123 | + |
2124 | + |
2125 | +namespace Marlin.View.Chrome { |
2126 | + |
2127 | + public class ProgressIndicatorWithPopover : Gtk.EventBox { |
2128 | + ProgressIndicator progress_indicator; |
2129 | + Gtk.Popover popover; |
2130 | + Gtk.ListBox content_box; |
2131 | + GLib.Mutex info_count_mutex; |
2132 | + |
2133 | + private uint _info_count = 0; |
2134 | + public uint info_count { |
2135 | + get { |
2136 | + return _info_count; |
2137 | + } |
2138 | + private set { |
2139 | + _info_count = value; |
2140 | + if (_info_count > 0) { |
2141 | + string tip_format = ngettext (_("%u file operation in progress"), _("%u file operations in progress"), _info_count); |
2142 | + set_tooltip_text (tip_format.printf (_info_count)); |
2143 | + } else { |
2144 | + set_tooltip_text (_("No operations in progress")); /* Should not be needed as widget hidden */ |
2145 | + } |
2146 | + } |
2147 | + } |
2148 | + |
2149 | + public ProgressIndicatorWithPopover () { |
2150 | + info_count_mutex = GLib.Mutex (); |
2151 | + |
2152 | + progress_indicator = new ProgressIndicator (28); |
2153 | + progress_indicator.set_valign (Gtk.Align.CENTER); |
2154 | + progress_indicator.set_hole_fraction (0.4); |
2155 | + |
2156 | + add (progress_indicator); |
2157 | + |
2158 | + popover = new Gtk.Popover (progress_indicator); |
2159 | + popover.set_position (Gtk.PositionType.BOTTOM); |
2160 | + |
2161 | + content_box = new Gtk.ListBox (); |
2162 | + content_box.margin_start = 6; |
2163 | + content_box.margin_end = 6; |
2164 | + content_box.margin_top = 6; |
2165 | + content_box.margin_bottom = 6; |
2166 | + popover.add (content_box); |
2167 | + |
2168 | + connect_events (); |
2169 | + |
2170 | + set_has_tooltip (true); |
2171 | + info_count = 0; |
2172 | + } |
2173 | + |
2174 | + private void connect_events () { |
2175 | + set_events (Gdk.EventMask.BUTTON_PRESS_MASK); |
2176 | + button_press_event.connect (on_button_press_event); |
2177 | + } |
2178 | + |
2179 | + private bool on_button_press_event () { |
2180 | + if (info_count > 0) { |
2181 | + popover.show_all (); |
2182 | + } |
2183 | + return true; |
2184 | + } |
2185 | + |
2186 | + public void set_overall_progress (double progress) { |
2187 | + progress_indicator.set_fraction (progress); |
2188 | + } |
2189 | + |
2190 | + public void add_progress_info (Marlin.Progress.Info info) { |
2191 | + var lbr = new Marlin.Progress.InfoListRow (info); |
2192 | + content_box.insert (lbr, -1); |
2193 | + |
2194 | + info_count_mutex.lock (); |
2195 | + info_count++; |
2196 | + info_count_mutex.unlock (); |
2197 | + |
2198 | + info.finished.connect (() => { |
2199 | + content_box.remove (lbr); |
2200 | + lbr.destroy (); |
2201 | + info_count_mutex.lock (); |
2202 | + info_count--; |
2203 | + info_count_mutex.unlock (); |
2204 | + }); |
2205 | + } |
2206 | + |
2207 | + public void close () { |
2208 | + popover.hide (); |
2209 | + this.hide (); |
2210 | + } |
2211 | + |
2212 | + public void hide_popover () { |
2213 | + popover.hide (); |
2214 | + } |
2215 | + |
2216 | + public void open () { |
2217 | + assert (info_count > 0); |
2218 | + popover.hide (); |
2219 | + this.set_visible (true); |
2220 | + } |
2221 | + |
2222 | + public void reset () { |
2223 | + progress_indicator.set_fraction (0.0); |
2224 | + } |
2225 | + } |
2226 | +} |
2227 | |
2228 | === added file 'src/View/Widgets/ProgressInfoListRow.vala' |
2229 | --- src/View/Widgets/ProgressInfoListRow.vala 1970-01-01 00:00:00 +0000 |
2230 | +++ src/View/Widgets/ProgressInfoListRow.vala 2017-01-14 12:39:17 +0000 |
2231 | @@ -0,0 +1,238 @@ |
2232 | +/*** |
2233 | + Copyright (c) 2007, 2011 Red Hat, Inc. |
2234 | + Copyright (c) 2013-2017 elementary LLC (http://launchpad.net/elementary) |
2235 | + |
2236 | + This program is free software: you can redistribute it and/or modify it |
2237 | + under the terms of the GNU Lesser General Public License version 3, as published |
2238 | + by the Free Software Foundation. |
2239 | + |
2240 | + This program is distributed in the hope that it will be useful, but |
2241 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
2242 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2243 | + PURPOSE. See the GNU General Public License for more details. |
2244 | + |
2245 | + You should have received a copy of the GNU General Public License along |
2246 | + with this program. If not, see <http://www.gnu.org/licenses/>. |
2247 | + |
2248 | + Authors: Alexander Larsson <alexl@redhat.com> |
2249 | + Cosimo Cecchi <cosimoc@redhat.com> |
2250 | + Julián Unrrein <junrrein@gmail.com> |
2251 | +***/ |
2252 | +public class Marlin.Progress.InfoListRow : Gtk.ListBoxRow { |
2253 | + |
2254 | + private Marlin.Progress.Info info; |
2255 | + |
2256 | + Gtk.Grid grid; |
2257 | + Gtk.Label status; |
2258 | + Gtk.Label details; |
2259 | + Gtk.ProgressBar progress_bar; |
2260 | + Gtk.Image progress_icon = null; |
2261 | + Gtk.Expander expander; |
2262 | + Gtk.TextView log; |
2263 | + |
2264 | + private int previous_remaining_file_count; |
2265 | + private int remaining_file_count; |
2266 | + private int total_file_count; |
2267 | + private Marlin.FileOperationType operation = Marlin.FileOperationType.INVALID; |
2268 | + private string dest_dir = ""; |
2269 | + private bool only_one_file = true; |
2270 | + |
2271 | + public InfoListRow (Marlin.Progress.Info info) { |
2272 | + this.info = info; |
2273 | + this.set_selectable (false); |
2274 | + this.set_activatable (false); |
2275 | + |
2276 | + operation = info.get_optype (); |
2277 | + dest_dir = PF.FileUtils.sanitize_path (info.get_destination_uri ()); |
2278 | + |
2279 | + total_file_count = info.get_total_file_count (); |
2280 | + only_one_file = total_file_count == 1; |
2281 | + |
2282 | + remaining_file_count = total_file_count; |
2283 | + previous_remaining_file_count = total_file_count; /* Ensure first line of details output */ |
2284 | + |
2285 | + build_and_show_widget (); |
2286 | + |
2287 | + update_data (); |
2288 | + update_progress (); |
2289 | + |
2290 | + info.changed.connect (update_data); |
2291 | + info.progress_changed.connect (update_progress); |
2292 | + } |
2293 | + |
2294 | + private void build_and_show_widget () { |
2295 | + grid = new Gtk.Grid (); |
2296 | + grid.set_column_spacing (6); |
2297 | + grid.set_row_spacing (6); |
2298 | + grid.set_column_homogeneous (false); |
2299 | + grid.set_row_homogeneous (false); |
2300 | + grid.margin_start = 6; |
2301 | + grid.margin_end = 6; |
2302 | + grid.margin_top = 6; |
2303 | + grid.margin_bottom = 6; |
2304 | + |
2305 | + var content_type = info.get_ctype (); |
2306 | + progress_icon = new Gtk.Image.from_gicon (GLib.ContentType.get_icon ("text/plain"), Gtk.IconSize.DIALOG); |
2307 | + if (content_type != null && content_type.length > 0) { |
2308 | + progress_icon = new Gtk.Image.from_gicon (GLib.ContentType.get_icon (content_type), Gtk.IconSize.DIALOG); |
2309 | + } |
2310 | + progress_icon.expand = true; |
2311 | + grid.attach (progress_icon, 0, 0, 1, 3); |
2312 | + |
2313 | + status = new Gtk.Label ("status"); |
2314 | + (status as Gtk.Label).set_line_wrap (true); |
2315 | + (status as Gtk.Label).set_line_wrap_mode (Pango.WrapMode.WORD_CHAR); |
2316 | + (status as Gtk.Misc).set_alignment ((float) 0.0, (float) 0.5); |
2317 | + grid.attach (status, 1, 0, 2, 1); |
2318 | + |
2319 | + progress_bar = new Gtk.ProgressBar (); |
2320 | + progress_bar.pulse_step = 0.05; |
2321 | + progress_bar.hexpand = true; |
2322 | + progress_bar.valign = Gtk.Align.CENTER; |
2323 | + progress_bar.set_size_request (700, -1); |
2324 | + grid.attach (progress_bar, 1, 1 , 1, 1); |
2325 | + |
2326 | + var button = new Gtk.Button.from_icon_name ("process-stop", Gtk.IconSize.BUTTON); |
2327 | + |
2328 | + /* Stop frame and dark background */ |
2329 | + button.set_relief (Gtk.ReliefStyle.NONE); |
2330 | + button.set_can_focus (false); |
2331 | + |
2332 | + button.valign = Gtk.Align.CENTER; |
2333 | + button.set_tooltip_text (_("Cancel this file operation")); |
2334 | + grid.attach (button, 3, 1, 1, 1); |
2335 | + |
2336 | + button.clicked.connect (() => { |
2337 | + info.cancel (); |
2338 | + button.sensitive = false; |
2339 | + }); |
2340 | + |
2341 | + details = new Gtk.Label (""); |
2342 | + (details as Gtk.Label).set_line_wrap (true); |
2343 | + (details as Gtk.Misc).set_alignment ((float) 0.0, (float) 0.5); |
2344 | + grid.attach (details, 1, 2, 1, 1); |
2345 | + |
2346 | + if (!only_one_file) { |
2347 | + expander = new Gtk.Expander ("<b>" + _("Details") + "</b>"); |
2348 | + expander.set_use_markup (true); |
2349 | + expander.margin_top = 6; |
2350 | + expander.margin_bottom = 6; |
2351 | + log = new Gtk.TextView (); |
2352 | + var sw = new Gtk.ScrolledWindow (null, null); |
2353 | + sw.set_size_request (-1, int.min (96, total_file_count * 16 + 24)); |
2354 | + sw.set_vexpand (false); |
2355 | + var exp_size = GLib.Value (typeof (int)); |
2356 | + var exp_spacing = GLib.Value (typeof (int)); |
2357 | + expander.style_get_property ("expander-size", ref exp_size); |
2358 | + expander.style_get_property ("expander-spacing", ref exp_spacing); |
2359 | + sw.margin_start = exp_size.get_int () + 2 * exp_spacing.get_int (); |
2360 | + sw.margin_bottom = 12; |
2361 | + sw.add (log); |
2362 | + expander.add (sw); |
2363 | + grid.attach (expander, 1,3, 1, 1); |
2364 | + |
2365 | + hide.connect (() => { |
2366 | + expander.set_expanded (false); |
2367 | + }); |
2368 | + } |
2369 | + add (grid); |
2370 | + show_all (); |
2371 | + } |
2372 | + |
2373 | + private void update_data () { |
2374 | + string? txt = info.get_status (); |
2375 | + (status as Gtk.Label).set_text (txt); |
2376 | + |
2377 | + txt = info.get_details (); |
2378 | + string markup = Markup.printf_escaped ("<span size='small'>%s</span>", txt); |
2379 | + (details as Gtk.Label).set_markup (markup); |
2380 | + |
2381 | + if (only_one_file) { |
2382 | + return; |
2383 | + } |
2384 | + |
2385 | + remaining_file_count = info.get_remaining_file_count (); |
2386 | + int diff = previous_remaining_file_count - remaining_file_count; |
2387 | + if (diff != 0) { |
2388 | + var buf = log.get_buffer (); |
2389 | + if (previous_remaining_file_count < total_file_count) { /* There was a previous line - complete it */ |
2390 | + /* TRANSLATORS: This is to indicate the completion of a file operation detailed on the same line */ |
2391 | + buf.insert_at_cursor (_(".... done") + "\n", -1); |
2392 | + } |
2393 | + |
2394 | + buf.insert_at_cursor (get_doing_string (operation, dest_dir, diff - 1) + "\n", -1); |
2395 | + |
2396 | + Gtk.TextMark mark = buf.get_insert (); |
2397 | + log.scroll_to_mark (mark, 0.0, true, 0.0, 0.0); |
2398 | + previous_remaining_file_count = remaining_file_count; |
2399 | + } |
2400 | + } |
2401 | + |
2402 | + private void update_progress () { |
2403 | + double progress = info.get_progress (); |
2404 | + |
2405 | + if (progress < 0) |
2406 | + (progress_bar as Gtk.ProgressBar).pulse (); |
2407 | + else |
2408 | + (progress_bar as Gtk.ProgressBar).set_fraction (progress); |
2409 | + } |
2410 | + |
2411 | + private string get_doing_string (Marlin.FileOperationType optype, string dest, uint others) { |
2412 | + var filename = info.get_current_filename (); |
2413 | + if (others > 0) { |
2414 | + return get_doing_several_string (optype, filename, dest, others); |
2415 | + } |
2416 | + |
2417 | + switch (optype) { |
2418 | + case Marlin.FileOperationType.COPY: |
2419 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path */ |
2420 | + return _("Copying %s to %s").printf (filename, dest); |
2421 | + case Marlin.FileOperationType.MOVE: |
2422 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path */ |
2423 | + return _("Moving %s to %s").printf (filename, dest); |
2424 | + case Marlin.FileOperationType.TRASH: |
2425 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path */ |
2426 | + return _("Moving %s to trash bin").printf (filename); |
2427 | + case Marlin.FileOperationType.DELETE: |
2428 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path */ |
2429 | + return _("Permanently deleting %s").printf (filename); |
2430 | + case Marlin.FileOperationType.LINK: |
2431 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path */ |
2432 | + return _("Linking %s to %s").printf (filename, dest); |
2433 | + default: |
2434 | + break; |
2435 | + } |
2436 | + |
2437 | + /* TRANSLATORS: %s will be replaced by a filename and should not be translated */ |
2438 | + return _("Operating on %s").printf (filename); /* Should not be reached */ |
2439 | + } |
2440 | + private string get_doing_several_string (Marlin.FileOperationType optype, string filename, string dest, uint others) { |
2441 | + switch (optype) { |
2442 | + case Marlin.FileOperationType.COPY: |
2443 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path. |
2444 | + %i will be replaced by a number */ |
2445 | + return _("Copying %s and %i more to %s").printf (filename, others, dest); |
2446 | + case Marlin.FileOperationType.MOVE: |
2447 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path. |
2448 | + %i will be replaced by a number */ |
2449 | + return _("Moving %s and %i more to %s").printf (filename, others, dest); |
2450 | + case Marlin.FileOperationType.TRASH: |
2451 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path. |
2452 | + %i will be replaced by a number */ |
2453 | + return _("Moving %s and %i more to trash bin").printf (filename, others); |
2454 | + case Marlin.FileOperationType.DELETE: |
2455 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path. |
2456 | + %i will be replaced by a number */ |
2457 | + return _("Permanently deleting %s and %i more").printf (filename, others); |
2458 | + case Marlin.FileOperationType.LINK: |
2459 | + /* TRANSLATORS: the first %s will be replaced by a filename, the second by destination path. |
2460 | + %i will be replaced by a number */ |
2461 | + return _("Linking %s and %i more to %s").printf (filename, others, dest); |
2462 | + default: |
2463 | + break; |
2464 | + } |
2465 | + |
2466 | + /* TRANSLATORS: %s will be replaced by a filename*/ |
2467 | + return _("Operating on %s and % more").printf (filename, others); /* Should not be reached */ |
2468 | + } |
2469 | +} |
2470 | |
2471 | === removed file 'src/View/Widgets/ProgressInfoWidget.vala' |
2472 | --- src/View/Widgets/ProgressInfoWidget.vala 2016-12-31 19:42:09 +0000 |
2473 | +++ src/View/Widgets/ProgressInfoWidget.vala 1970-01-01 00:00:00 +0000 |
2474 | @@ -1,102 +0,0 @@ |
2475 | -/*** |
2476 | - Copyright (c) 2007, 2011 Red Hat, Inc. |
2477 | - Copyright (c) 2013-2017 elementary LLC (http://launchpad.net/elementary) |
2478 | - |
2479 | - This program is free software: you can redistribute it and/or modify it |
2480 | - under the terms of the GNU Lesser General Public License version 3, as published |
2481 | - by the Free Software Foundation. |
2482 | - |
2483 | - This program is distributed in the hope that it will be useful, but |
2484 | - WITHOUT ANY WARRANTY; without even the implied warranties of |
2485 | - MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2486 | - PURPOSE. See the GNU General Public License for more details. |
2487 | - |
2488 | - You should have received a copy of the GNU General Public License along |
2489 | - with this program. If not, see <http://www.gnu.org/licenses/>. |
2490 | - |
2491 | - Authors: Alexander Larsson <alexl@redhat.com> |
2492 | - Cosimo Cecchi <cosimoc@redhat.com> |
2493 | - Julián Unrrein <junrrein@gmail.com> |
2494 | -***/ |
2495 | - |
2496 | -public class Marlin.Progress.InfoWidget : Gtk.Box { |
2497 | - |
2498 | - private Marlin.Progress.Info info; |
2499 | - |
2500 | - Gtk.Widget status; /* Gtk.Label */ |
2501 | - Gtk.Widget details; /* Gtk.Label */ |
2502 | - Gtk.Widget progress_bar; |
2503 | - |
2504 | - public InfoWidget (Marlin.Progress.Info info) { |
2505 | - this.info = info; |
2506 | - |
2507 | - build_and_show_widget (); |
2508 | - |
2509 | - update_data (); |
2510 | - update_progress (); |
2511 | - |
2512 | - this.info.changed.connect (update_data); |
2513 | - this.info.progress_changed.connect (update_progress); |
2514 | - |
2515 | - this.info.finished.connect (() => { |
2516 | - destroy (); |
2517 | - }); |
2518 | - } |
2519 | - |
2520 | - private void build_and_show_widget () { |
2521 | - this.orientation = Gtk.Orientation.VERTICAL; |
2522 | - this.homogeneous = false; |
2523 | - this.spacing = 5; |
2524 | - |
2525 | - this.status = new Gtk.Label ("status"); |
2526 | - (this.status as Gtk.Label).set_size_request (500, -1); |
2527 | - (this.status as Gtk.Label).set_line_wrap (true); |
2528 | - (this.status as Gtk.Label).set_line_wrap_mode (Pango.WrapMode.WORD_CHAR); |
2529 | - (this.status as Gtk.Misc).set_alignment ((float) 0.0, (float) 0.5); |
2530 | - pack_start (status, true, false, 0); |
2531 | - |
2532 | - var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 10); |
2533 | - var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); |
2534 | - |
2535 | - this.progress_bar = new Gtk.ProgressBar (); |
2536 | - (this.progress_bar as Gtk.ProgressBar).pulse_step = 0.05; |
2537 | - box.pack_start (this.progress_bar, true, false, 0); |
2538 | - hbox.pack_start (box, true, true, 0); |
2539 | - |
2540 | - var button = new Gtk.Button.from_icon_name ("process-stop-symbolic", Gtk.IconSize.BUTTON); |
2541 | - button.get_style_context ().add_class ("flat"); |
2542 | - button.clicked.connect (() => { |
2543 | - this.info.cancel (); |
2544 | - button.sensitive = false; |
2545 | - }); |
2546 | - |
2547 | - hbox.pack_start (button, false, false, 0); |
2548 | - |
2549 | - pack_start (hbox, false, false, 0); |
2550 | - |
2551 | - this.details = new Gtk.Label ("details"); |
2552 | - (this.details as Gtk.Label).set_line_wrap (true); |
2553 | - (this.details as Gtk.Misc).set_alignment ((float) 0.0, (float) 0.5); |
2554 | - pack_start (details, true, false, 0); |
2555 | - |
2556 | - show_all (); |
2557 | - } |
2558 | - |
2559 | - private void update_data () { |
2560 | - string status = this.info.get_status (); |
2561 | - (this.status as Gtk.Label).set_text (status); |
2562 | - |
2563 | - string details = this.info.get_details (); |
2564 | - string markup = Markup.printf_escaped ("<span size='small'>%s</span>", details); |
2565 | - (this.details as Gtk.Label).set_markup (markup); |
2566 | - } |
2567 | - |
2568 | - private void update_progress () { |
2569 | - double progress = this.info.get_progress (); |
2570 | - |
2571 | - if (progress < 0) |
2572 | - (this.progress_bar as Gtk.ProgressBar).pulse (); |
2573 | - else |
2574 | - (this.progress_bar as Gtk.ProgressBar).set_fraction (progress); |
2575 | - } |
2576 | -} |
2577 | |
2578 | === modified file 'src/View/Widgets/TopMenu.vala' |
2579 | --- src/View/Widgets/TopMenu.vala 2017-01-13 13:31:06 +0000 |
2580 | +++ src/View/Widgets/TopMenu.vala 2017-01-14 12:39:17 +0000 |
2581 | @@ -28,6 +28,7 @@ |
2582 | public LocationBar? location_bar; |
2583 | public Chrome.ButtonWithMenu button_forward; |
2584 | public Chrome.ButtonWithMenu button_back; |
2585 | + private ProgressIndicatorWithPopover progress_indicator; |
2586 | |
2587 | public bool locked_focus {get; private set; default = false;} |
2588 | |
2589 | @@ -88,6 +89,9 @@ |
2590 | location_bar.show_all (); |
2591 | pack_start (location_bar); |
2592 | |
2593 | + progress_indicator = new ProgressIndicatorWithPopover (); |
2594 | + pack_start (progress_indicator); |
2595 | + |
2596 | show (); |
2597 | } |
2598 | |
2599 | @@ -167,5 +171,21 @@ |
2600 | public void cancel () { |
2601 | location_bar.cancel (); |
2602 | } |
2603 | + |
2604 | + public void update_overall_progress (double progress) { |
2605 | + progress_indicator.set_overall_progress (progress); |
2606 | + } |
2607 | + |
2608 | + public void show_progress (bool show) { |
2609 | + if (show) { |
2610 | + progress_indicator.open (); |
2611 | + } else { |
2612 | + progress_indicator.close (); |
2613 | + } |
2614 | + } |
2615 | + |
2616 | + public void add_progress_info (Marlin.Progress.Info info) { |
2617 | + progress_indicator.add_progress_info (info); |
2618 | + } |
2619 | } |
2620 | } |
2621 | |
2622 | === modified file 'src/View/Window.vala' |
2623 | --- src/View/Window.vala 2017-01-13 13:31:06 +0000 |
2624 | +++ src/View/Window.vala 2017-01-14 12:39:17 +0000 |
2625 | @@ -1094,5 +1094,17 @@ |
2626 | application.set_accels_for_action ("win.info::HELP", {"F1"}); |
2627 | application.set_accels_for_action ("win.info::ABOUT", {"F3"}); |
2628 | } |
2629 | + |
2630 | + public void overall_progress_changed (double progress) { |
2631 | + top_menu.update_overall_progress (progress); |
2632 | + } |
2633 | + |
2634 | + public void show_progress (bool show) { |
2635 | + top_menu.show_progress (show); |
2636 | + } |
2637 | + |
2638 | + public void add_progress_info (Marlin.Progress.Info info) { |
2639 | + top_menu.add_progress_info (info); |
2640 | + } |
2641 | } |
2642 | } |
I don't think we need to send a notification when cancelling a transfer. That's something that I just did. There's no delay between me doing it and it happening and it's obvious that it happened because the file is removed from the popover. So it seems unnecessary to send a notification here.