Merge lp:~jeremywootten/appcenter/restructuring-part1 into lp:~elementary-apps/appcenter/appcenter
- restructuring-part1
- Merge into appcenter
Proposed by
Jeremy Wootten
Status: | Merged |
---|---|
Approved by: | Adam Bieńkowski |
Approved revision: | 281 |
Merged at revision: | 283 |
Proposed branch: | lp:~jeremywootten/appcenter/restructuring-part1 |
Merge into: | lp:~elementary-apps/appcenter/appcenter |
Diff against target: |
519 lines (+176/-161) 5 files modified
src/Core/ChangeInformation.vala (+32/-18) src/Core/Package.vala (+111/-94) src/Views/AppInfoView.vala (+8/-21) src/Views/AppListView.vala (+18/-12) src/Widgets/PackageRow.vala (+7/-16) |
To merge this branch: | bzr merge lp:~jeremywootten/appcenter/restructuring-part1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Adam Bieńkowski (community) | code / testing | Approve | |
Review via email: mp+303492@code.launchpad.net |
Commit message
Restructure Package.vala and ChangeInformati
Description of the change
This branch restructures the code in Package.vala and ChangeInformati
This branch is not intended to fix bugs but to prepare for later bug fixing branches.
To post a comment you must log in.
Revision history for this message
Adam Bieńkowski (donadigo) wrote : | # |
review:
Needs Fixing
(code / function)
- 280. By Jeremy Wootten
-
Stop AppListView sort while updating
- 281. By Jeremy Wootten
-
Remove whitespace; codestyle changes
Revision history for this message
Adam Bieńkowski (donadigo) wrote : | # |
Thanks for fixing my issues! The sorting works great now, although I'm not sure about the "OS Updates" entry staying under the "updated" header. However I'm gonna approve this, it's a great cleanup.
review:
Approve
(code / testing)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/Core/ChangeInformation.vala' |
2 | --- src/Core/ChangeInformation.vala 2016-07-19 20:41:00 +0000 |
3 | +++ src/Core/ChangeInformation.vala 2016-08-25 09:09:18 +0000 |
4 | @@ -25,27 +25,23 @@ |
5 | public Gee.TreeSet<Pk.Package> changes { public get; private set; } |
6 | public Gee.TreeSet<Pk.Details> details { public get; private set; } |
7 | public bool can_cancel { public get; private set; default=true; } |
8 | - public Pk.Status status; |
9 | + public Pk.Status status { public get; private set; } |
10 | private Gee.HashMap<string, double?> change_progress; |
11 | - private double progress; |
12 | + public double progress { public get; private set; } |
13 | |
14 | construct { |
15 | changes = new Gee.TreeSet<Pk.Package> (); |
16 | details = new Gee.TreeSet<Pk.Details> (); |
17 | change_progress = new Gee.HashMap<string, double?> (); |
18 | status = Pk.Status.SETUP; |
19 | - progress = 1.0f; |
20 | + progress = 0.0f; |
21 | } |
22 | |
23 | public bool has_changes () { |
24 | return changes.size > 0; |
25 | } |
26 | |
27 | - public double get_progress () { |
28 | - return progress; |
29 | - } |
30 | - |
31 | - public string get_status () { |
32 | + public string get_status_string () { |
33 | switch (status) { |
34 | case Pk.Status.SETUP: |
35 | return _("Starting"); |
36 | @@ -131,18 +127,36 @@ |
37 | return size; |
38 | } |
39 | |
40 | - public void clear () { |
41 | - changes.clear (); |
42 | - details.clear (); |
43 | - reset (); |
44 | - } |
45 | - |
46 | - public void reset () { |
47 | + public void start () { |
48 | + progress = 0.0f; |
49 | + progress_changed (); |
50 | + status = Pk.Status.WAIT; |
51 | + status_changed (); |
52 | + } |
53 | + |
54 | + public void complete () { |
55 | + status = Pk.Status.FINISHED; |
56 | + status_changed (); |
57 | + reset_progress (); |
58 | + } |
59 | + |
60 | + public void cancel () { |
61 | + progress = 0.0f; |
62 | + progress_changed (); |
63 | + status = Pk.Status.CANCEL; |
64 | + status_changed (); |
65 | + reset_progress (); |
66 | + } |
67 | + |
68 | + public void clear_update_info () { |
69 | + changes.clear (); |
70 | + details.clear (); |
71 | + } |
72 | + |
73 | + public void reset_progress () { |
74 | change_progress.clear (); |
75 | status = Pk.Status.SETUP; |
76 | - status_changed (); |
77 | - progress = 1.0f; |
78 | - progress_changed (); |
79 | + progress = 0.0f; |
80 | } |
81 | |
82 | public void ProgressCallback (Pk.Progress progress, Pk.ProgressType type) { |
83 | |
84 | === modified file 'src/Core/Package.vala' |
85 | --- src/Core/Package.vala 2016-07-08 20:54:44 +0000 |
86 | +++ src/Core/Package.vala 2016-08-25 09:09:18 +0000 |
87 | @@ -6,12 +6,12 @@ |
88 | * it under the terms of the GNU General Public License as published by |
89 | * the Free Software Foundation, either version 3 of the License, or |
90 | * (at your option) any later version. |
91 | - * |
92 | + * |
93 | * This program is distributed in the hope that it will be useful, |
94 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
95 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
96 | * GNU General Public License for more details. |
97 | - * |
98 | + * |
99 | * You should have received a copy of the GNU General Public License |
100 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
101 | * |
102 | @@ -19,6 +19,7 @@ |
103 | */ |
104 | |
105 | public class AppCenterCore.Package : Object { |
106 | + |
107 | public enum State { |
108 | NOT_INSTALLED, |
109 | INSTALLED, |
110 | @@ -37,6 +38,12 @@ |
111 | public bool changing { public get; private set; default = false; } |
112 | public State state { public get; private set; default = State.NOT_INSTALLED; } |
113 | |
114 | + public double progress { |
115 | + get { |
116 | + return change_information.progress; |
117 | + } |
118 | + } |
119 | + |
120 | public bool installed { |
121 | get { |
122 | return !installed_packages.is_empty || component.get_id () == OS_UPDATES_ID; |
123 | @@ -45,9 +52,21 @@ |
124 | |
125 | public bool update_available { |
126 | get { |
127 | - return installed && change_information.has_changes (); |
128 | - } |
129 | - } |
130 | + return state == State.UPDATE_AVAILABLE; |
131 | + } |
132 | + } |
133 | + |
134 | + public bool is_updating { |
135 | + get { |
136 | + return state == State.UPDATING; |
137 | + } |
138 | + } |
139 | + |
140 | + public bool is_os_updates { |
141 | + get { |
142 | + return component.id == "xxx-os-updates"; |
143 | + } |
144 | + } |
145 | |
146 | public Package (AppStream.Component component) { |
147 | this.component = component; |
148 | @@ -58,106 +77,100 @@ |
149 | |
150 | public void update_state () { |
151 | if (installed) { |
152 | - if (update_available) { |
153 | + if (change_information.has_changes ()) { |
154 | state = State.UPDATE_AVAILABLE; |
155 | } else { |
156 | state = State.INSTALLED; |
157 | } |
158 | } else { |
159 | state = State.NOT_INSTALLED; |
160 | - } |
161 | - } |
162 | - |
163 | - public async void update () throws GLib.Error { |
164 | - action_cancellable.reset (); |
165 | - changing = true; |
166 | - |
167 | - var previous_state = state; |
168 | - state = State.UPDATING; |
169 | - try { |
170 | - var exit_status = yield AppCenterCore.Client.get_default ().update_package (this, (progress, type) => {change_information.ProgressCallback (progress, type);}, action_cancellable); |
171 | - installed_packages.add_all (change_information.changes); |
172 | - change_information.clear (); |
173 | - |
174 | - if (exit_status == Pk.Exit.SUCCESS) { |
175 | - state = State.INSTALLED; |
176 | - } else { |
177 | - state = previous_state; |
178 | - } |
179 | - |
180 | - changing = false; |
181 | - } catch (Error e) { |
182 | - change_information.reset (); |
183 | - changing = false; |
184 | - state = previous_state; |
185 | - throw e; |
186 | - } |
187 | - } |
188 | - |
189 | - public async void install () throws GLib.Error { |
190 | - action_cancellable.reset (); |
191 | - changing = true; |
192 | - |
193 | - var previous_state = state; |
194 | - state = State.INSTALLING; |
195 | - try { |
196 | + } |
197 | + } |
198 | + |
199 | + public async bool update () { |
200 | + if (state != State.UPDATE_AVAILABLE) { |
201 | + return false; |
202 | + } |
203 | + return yield perform_operation (State.UPDATING, State.INSTALLED, State.UPDATE_AVAILABLE); |
204 | + } |
205 | + |
206 | + public async bool install () { |
207 | + if (state != State.UPDATE_AVAILABLE) { |
208 | + return false; |
209 | + } |
210 | + if (yield perform_operation (State.INSTALLING, State.INSTALLED, State.NOT_INSTALLED)) { |
211 | + /* TODO: Move this to a higher level */ |
212 | var application = (Gtk.Application)Application.get_default (); |
213 | var window = application.get_active_window ().get_window (); |
214 | - |
215 | - var exit_status = yield AppCenterCore.Client.get_default ().install_package (this, (progress, type) => {change_information.ProgressCallback (progress, type);}, action_cancellable); |
216 | - installed_packages.add_all (change_information.changes); |
217 | - change_information.clear (); |
218 | - |
219 | - if (exit_status == Pk.Exit.SUCCESS) { |
220 | - state = State.INSTALLED; |
221 | - |
222 | - if ((window.get_state () & Gdk.WindowState.FOCUSED) == 0) { |
223 | - var notification = new Notification (_("Application installed")); |
224 | - notification.set_body (_("%s has been successfully installed").printf (get_name ())); |
225 | - notification.set_icon (new ThemedIcon ("system-software-install")); |
226 | - notification.set_default_action ("app.open-application"); |
227 | - |
228 | - application.send_notification ("installed", notification); |
229 | - } |
230 | - } else { |
231 | - state = previous_state; |
232 | + if ((window.get_state () & Gdk.WindowState.FOCUSED) == 0) { |
233 | + var notification = new Notification (_("Application installed")); |
234 | + notification.set_body (_("%s has been successfully installed").printf (get_name ())); |
235 | + notification.set_icon (new ThemedIcon ("system-software-install")); |
236 | + notification.set_default_action ("app.open-application"); |
237 | + |
238 | + application.send_notification ("installed", notification); |
239 | } |
240 | - |
241 | - changing = false; |
242 | - } catch (Error e) { |
243 | - change_information.reset (); |
244 | - changing = false; |
245 | - state = previous_state; |
246 | - throw e; |
247 | - } |
248 | - } |
249 | - |
250 | - public async void uninstall () throws GLib.Error { |
251 | + return true; |
252 | + } |
253 | + |
254 | + return false; |
255 | + } |
256 | + public async bool uninstall () { |
257 | + if (state != State.INSTALLED) { |
258 | + return false; |
259 | + } |
260 | + return yield perform_operation (State.REMOVING, State.NOT_INSTALLED, State.INSTALLED); |
261 | + } |
262 | + |
263 | + private async bool perform_operation (State performing, State after_success, State after_fail) { |
264 | + var exit_status = Pk.Exit.UNKNOWN; |
265 | + prepare_package_operation (performing); |
266 | + try { |
267 | + exit_status = yield perform_package_operation (); |
268 | + } catch (GLib.Error e) { |
269 | + critical ("Operation failed for package %s - %s", get_name (), e.message); |
270 | + } finally { |
271 | + clean_up_package_operation (exit_status, after_success, after_fail); |
272 | + } |
273 | + return (exit_status == Pk.Exit.SUCCESS); |
274 | + } |
275 | + |
276 | + private void prepare_package_operation (State initial_state) { |
277 | + changing = true; |
278 | + |
279 | action_cancellable.reset (); |
280 | - changing = true; |
281 | - |
282 | - var previous_state = state; |
283 | - state = State.REMOVING; |
284 | - try { |
285 | - var exit_status = yield AppCenterCore.Client.get_default ().remove_package (this, (progress, type) => {change_information.ProgressCallback (progress, type);}, action_cancellable); |
286 | - installed_packages.clear (); |
287 | - change_information.clear (); |
288 | - |
289 | - if (exit_status == Pk.Exit.SUCCESS) { |
290 | - state = State.NOT_INSTALLED; |
291 | - } else { |
292 | - state = previous_state; |
293 | - } |
294 | - |
295 | - changing = false; |
296 | - } catch (Error e) { |
297 | - change_information.reset (); |
298 | - changing = false; |
299 | - state = previous_state; |
300 | - throw e; |
301 | + change_information.start (); |
302 | + state = initial_state; |
303 | + } |
304 | + |
305 | + private async Pk.Exit perform_package_operation () throws GLib.Error { |
306 | + Pk.ProgressCallback cb = change_information.ProgressCallback; |
307 | + var client = AppCenterCore.Client.get_default (); |
308 | + switch (state) { |
309 | + case State.UPDATING: |
310 | + return yield client.update_package (this, cb, action_cancellable); |
311 | + case State.INSTALLING: |
312 | + return yield client.install_package (this, cb, action_cancellable); |
313 | + case State.REMOVING: |
314 | + return yield client.remove_package (this, cb, action_cancellable); |
315 | + default: |
316 | + return Pk.Exit.UNKNOWN; |
317 | } |
318 | } |
319 | |
320 | + private void clean_up_package_operation (Pk.Exit exit_status, State success_state, State fail_state) { |
321 | + changing = false; |
322 | + |
323 | + installed_packages.add_all (change_information.changes); |
324 | + if (exit_status == Pk.Exit.SUCCESS) { |
325 | + change_information.complete (); |
326 | + state = success_state; |
327 | + } else { |
328 | + state = fail_state; |
329 | + change_information.cancel (); |
330 | + } |
331 | + } |
332 | + |
333 | public string? get_name () { |
334 | var _name = component.get_name (); |
335 | if (_name != null) { |
336 | @@ -186,6 +199,10 @@ |
337 | return null; |
338 | } |
339 | |
340 | + public string get_progress_description () { |
341 | + return change_information.get_status_string (); |
342 | + } |
343 | + |
344 | public GLib.Icon get_icon (uint size = 32) { |
345 | GLib.Icon? icon = null; |
346 | uint current_size = 0; |
347 | @@ -194,7 +211,7 @@ |
348 | component.get_icons ().foreach ((_icon) => { |
349 | if (is_stock) { |
350 | return; |
351 | - } |
352 | + } |
353 | |
354 | switch (_icon.get_kind ()) { |
355 | case AppStream.IconKind.STOCK: |
356 | @@ -202,7 +219,7 @@ |
357 | is_stock = true; |
358 | icon = new ThemedIcon (_icon.get_name ()); |
359 | } |
360 | - |
361 | + |
362 | break; |
363 | case AppStream.IconKind.CACHED: |
364 | case AppStream.IconKind.LOCAL: |
365 | |
366 | === modified file 'src/Views/AppInfoView.vala' |
367 | --- src/Views/AppInfoView.vala 2016-07-04 20:31:29 +0000 |
368 | +++ src/Views/AppInfoView.vala 2016-08-25 09:09:18 +0000 |
369 | @@ -246,14 +246,11 @@ |
370 | } |
371 | |
372 | private void update_progress_status () { |
373 | - progress_bar.text = package.change_information.get_status (); |
374 | + progress_bar.text = package.get_progress_description (); |
375 | } |
376 | |
377 | private void update_progress () { |
378 | - double progress = package.change_information.get_progress (); |
379 | - if (progress < 1.0f) { |
380 | - progress_bar.fraction = progress; |
381 | - } |
382 | + progress_bar.fraction = package.progress; |
383 | } |
384 | |
385 | private void update_state () { |
386 | @@ -299,28 +296,18 @@ |
387 | } |
388 | |
389 | private async void action_clicked () { |
390 | - try { |
391 | - if (package.update_available) { |
392 | - yield package.update (); |
393 | - } else { |
394 | - yield package.install (); |
395 | - |
396 | - // Add this app to the Installed Apps View |
397 | - MainWindow.installed_view.add_app.begin (package); |
398 | - } |
399 | - } catch (Error e) { |
400 | - critical (e.message); |
401 | + if (package.update_available) { |
402 | + yield package.update (); |
403 | + } else if (yield package.install ()) { |
404 | + // Add this app to the Installed Apps View |
405 | + MainWindow.installed_view.add_app.begin (package); |
406 | } |
407 | } |
408 | |
409 | private async void uninstall_clicked () { |
410 | - try { |
411 | - yield package.uninstall (); |
412 | - |
413 | + if (yield package.uninstall ()) { |
414 | // Remove this app from the Installed Apps View |
415 | MainWindow.installed_view.remove_app.begin (package); |
416 | - } catch (Error e) { |
417 | - critical (e.message); |
418 | } |
419 | } |
420 | |
421 | |
422 | === modified file 'src/Views/AppListView.vala' |
423 | --- src/Views/AppListView.vala 2016-07-20 13:48:28 +0000 |
424 | +++ src/Views/AppListView.vala 2016-08-25 09:09:18 +0000 |
425 | @@ -111,16 +111,20 @@ |
426 | private int package_row_compare (Widgets.PackageRow row1, Widgets.PackageRow row2) { |
427 | unowned Package package_a = row1.package; |
428 | unowned Package package_b = row2.package; |
429 | - if (updates_on_top) { |
430 | + |
431 | + bool a_update = package_a.update_available || package_a.is_updating; |
432 | + bool b_update = package_b.update_available || package_b.is_updating; |
433 | + |
434 | + if (updates_on_top) { |
435 | if (package_a.component.id == "xxx-os-updates") { |
436 | return -1; |
437 | } else if (package_b.component.id == "xxx-os-updates") { |
438 | return 1; |
439 | } |
440 | |
441 | - if (package_a.update_available && !package_b.update_available) { |
442 | + if (a_update && !b_update) { |
443 | return -1; |
444 | - } else if (!package_a.update_available && package_b.update_available) { |
445 | + } else if (!a_update && b_update) { |
446 | return 1; |
447 | } |
448 | } |
449 | @@ -130,15 +134,17 @@ |
450 | |
451 | [CCode (instance_pos = -1)] |
452 | private void package_row_update_header (Widgets.PackageRow row, Widgets.PackageRow? before) { |
453 | - bool update_available = row.package.update_available; |
454 | - if (before == null && update_available) { |
455 | - var updates_grid = get_updates_grid (); |
456 | - row.set_header (updates_grid); |
457 | - } else if ((before == null && !update_available) || update_available != before.package.update_available) { |
458 | - var updated_grid = get_updated_grid (); |
459 | - row.set_header (updated_grid); |
460 | - } else { |
461 | - row.set_header (null); |
462 | + if (!row.package.is_updating && (before == null || !before.package.is_updating)) { |
463 | + bool update_available = row.package.update_available; |
464 | + if (before == null && update_available) { |
465 | + var updates_grid = get_updates_grid (); |
466 | + row.set_header (updates_grid); |
467 | + } else if ((before == null && !update_available) || update_available != before.package.update_available) { |
468 | + var updated_grid = get_updated_grid (); |
469 | + row.set_header (updated_grid); |
470 | + } else { |
471 | + row.set_header (null); |
472 | + } |
473 | } |
474 | } |
475 | |
476 | |
477 | === modified file 'src/Widgets/PackageRow.vala' |
478 | --- src/Widgets/PackageRow.vala 2016-07-05 21:30:40 +0000 |
479 | +++ src/Widgets/PackageRow.vala 2016-08-25 09:09:18 +0000 |
480 | @@ -110,14 +110,11 @@ |
481 | } |
482 | |
483 | private void update_progress_status () { |
484 | - progress_bar.text = package.change_information.get_status (); |
485 | + progress_bar.text = package.get_progress_description (); |
486 | } |
487 | |
488 | private void update_progress () { |
489 | - double progress = package.change_information.get_progress (); |
490 | - if (progress < 1.0f) { |
491 | - progress_bar.fraction = progress; |
492 | - } |
493 | + progress_bar.fraction = package.progress; |
494 | } |
495 | |
496 | private void update_state () { |
497 | @@ -166,17 +163,11 @@ |
498 | } |
499 | |
500 | private async void action_clicked () { |
501 | - try { |
502 | - if (package.update_available) { |
503 | - yield package.update (); |
504 | - } else { |
505 | - yield package.install (); |
506 | - |
507 | - // Add this app to the Installed Apps View |
508 | - MainWindow.installed_view.add_app.begin (package); |
509 | - } |
510 | - } catch (Error e) { |
511 | - critical (e.message); |
512 | + if (package.update_available) { |
513 | + yield package.update (); |
514 | + } else if (yield package.install ()) { |
515 | + // Add this app to the Installed Apps View |
516 | + MainWindow.installed_view.add_app.begin (package); |
517 | } |
518 | } |
519 | } |
Great cleanup, although I still have some issues with sorting apps to their right header. An example of this would be to click "update" in the OS updates entry, it would create a new "up to date" header at the top and add the OS updates entry to it like that:
Up to date:
OS Updates
Available updates:
...
Up to date:
...
Also if you click "update" on the normal app it is sorted immediately to up to date header, before I even authorize. Is that intentional, or maybe it's fixed in your next branches?
I did comment on the diff for a few code style issues, but it's not something really important.