Merge lp:~jeremywootten/appcenter/restructuring-part1 into lp:~elementary-apps/appcenter/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
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 ChangeInformation.vala to reduce duplication and increase clarity and make a few consequent changes elsewhere

Description of the change

This branch restructures the code in Package.vala and ChangeInformation.vala to reduce duplication and increase clarity and makes a few consequent changes elsewhere.

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 :

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.

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 }

Subscribers

People subscribed via source and target branches