Merge lp:~donadigo/appcenter/sorting-headers into lp:~elementary-apps/appcenter/appcenter

Proposed by Adam Bieńkowski
Status: Rejected
Rejected by: David Hewitt
Proposed branch: lp:~donadigo/appcenter/sorting-headers
Merge into: lp:~elementary-apps/appcenter/appcenter
Diff against target: 432 lines (+146/-213)
2 files modified
src/Views/AppListView.vala (+55/-68)
src/Widgets/UpdateHeaderRow.vala (+91/-145)
To merge this branch: bzr merge lp:~donadigo/appcenter/sorting-headers
Reviewer Review Type Date Requested Status
Felipe Escoto (community) Approve
Review via email: mp+317787@code.launchpad.net

Commit message

Simplify sorting headers and comparing rows

Description of the change

This branch simplifies header sorting and comparing rows to sort them also. The branch is a part of drivers-2 branch.

Header assigning is now done within Gtk's native header_func function, rather than having it in sorting rows.

To post a comment you must log in.
Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

I notice that, when running "Update all", "Searching for updates" and its spinner appear before installation of updates has completed, on a line below the applications being updated. Is this intended? It looks a bit odd.

Revision history for this message
Felipe Escoto (philip.scott) wrote :

The searching for updates still shows on master, so i'm merging it since it just shouldn't appear

review: Approve
Revision history for this message
RabbitBot (rabbitbot-a) wrote :

Attempt to merge into lp:appcenter failed due to conflicts:

text conflict in src/Views/AppListView.vala
text conflict in src/Widgets/UpdateHeaderRow.vala

Revision history for this message
David Hewitt (davidmhewitt) wrote :

This functionality has been merged into the GitHub repository of AppCenter. Closing.

Unmerged revisions

406. By Adam Bieńkowski

Do not remove the update button from the size group

405. By Adam Bieńkowski

Simplify comparing rows and assigning headers for them

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/Views/AppListView.vala'
2--- src/Views/AppListView.vala 2017-02-15 18:02:21 +0000
3+++ src/Views/AppListView.vala 2017-02-20 17:20:45 +0000
4@@ -86,9 +86,7 @@
5 * Does not show Uninstall Button **/
6 public class AppListUpdateView : AbstractAppList {
7 private bool updates_on_top;
8- private Widgets.UpdateHeaderRow updates_header;
9- private Widgets.UpdateHeaderRow updated_header;
10- private Widgets.AppActionButton update_all_button;
11+ private Widgets.AppActionButton? update_all_button;
12 private bool updating_all_apps = false;
13 private bool apps_remaining_started = false;
14 private GLib.Mutex update_mutex;
15@@ -105,7 +103,7 @@
16 set {
17 if (_updating_cache != value) {
18 _updating_cache = value;
19- update_headers ();
20+ list_box.invalidate_headers ();
21 }
22 }
23 }
24@@ -113,19 +111,7 @@
25 construct {
26 updates_on_top = true;
27
28- update_all_button = new Widgets.AppActionButton (_("Update All"));
29- update_all_button.set_suggested_action_header ();
30- update_all_button.clicked.connect (on_update_all);
31- update_all_button.no_show_all = true;
32- action_button_group.add_widget (update_all_button);
33-
34- updates_header = new Widgets.UpdateHeaderRow.updates ();
35- updates_header.add_widget (update_all_button);
36-
37- updated_header = new Widgets.UpdateHeaderRow.updated ();
38-
39- list_box.add (updates_header);
40- list_box.add (updated_header);
41+ list_box.set_header_func ((Gtk.ListBoxUpdateHeaderFunc) row_update_header);
42
43 update_mutex = GLib.Mutex ();
44 apps_to_update = new Gee.LinkedList<AppCenterCore.Package> ();
45@@ -137,7 +123,7 @@
46 _updating_cache = true;
47 }
48
49- protected override void after_add_remove_change_row () {update_headers ();}
50+ protected override void after_add_remove_change_row () { list_box.invalidate_headers (); }
51
52 protected override Widgets.AppListRow make_row (AppCenterCore.Package package) {
53 return (Widgets.AppListRow)(new Widgets.PackageRow.installed (package, action_button_group, false));
54@@ -145,34 +131,72 @@
55
56 protected override void on_package_changing (AppCenterCore.Package package, bool is_changing) {
57 base.on_package_changing (package, is_changing);
58- update_all_button.sensitive = packages_changing == 0;
59+ if (update_all_button != null) {
60+ update_all_button.sensitive = packages_changing == 0;
61+ }
62 }
63
64 [CCode (instance_pos = -1)]
65 protected override int package_row_compare (Widgets.AppListRow row1, Widgets.AppListRow row2) {
66- bool a_is_header = !row1.has_package ();
67- bool b_is_header = !row2.has_package ();
68- bool a_has_updates = row1.get_update_available ();
69- bool b_has_updates = row2.get_update_available ();
70-
71- if (a_is_header) {
72- return (a_has_updates || !b_has_updates) ? -1 : 1;
73- } else if (b_is_header) {
74- return (b_has_updates || !a_has_updates) ? 1 : -1;
75- }
76-
77 bool a_is_os = row1.get_is_os_updates ();
78 bool b_is_os = row2.get_is_os_updates ();
79
80 if (a_is_os || b_is_os) { /* OS update row sorts ahead of other update rows */
81 return a_is_os ? -1 : 1;
82- } else if ((a_has_updates && !b_has_updates) || (!a_has_updates && b_has_updates)) { /* Updates rows sort ahead of updated rows */
83+ }
84+
85+ bool a_has_updates = row1.get_update_available ();
86+ bool b_has_updates = row2.get_update_available ();
87+
88+ if ((a_has_updates && !b_has_updates) || (!a_has_updates && b_has_updates)) { /* Updates rows sort ahead of updated rows */
89 return a_has_updates ? -1 : 1;
90 }
91
92 return row1.get_name_label ().collate (row2.get_name_label ()); /* Else sort in name order */
93 }
94
95+ [CCode (instance_pos = -1)]
96+ private void row_update_header (Widgets.AppListRow row, Widgets.AppListRow? before) {
97+ bool update_available = row.get_update_available ();
98+ if (before != null && update_available == before.get_update_available ()) {
99+ row.set_header (null);
100+ return;
101+ }
102+
103+ if (update_available) {
104+ var header = new Widgets.UpdatesGrid ();
105+
106+ uint update_numbers = 0U;
107+ uint64 update_real_size = 0ULL;
108+ foreach (var package in get_packages ()) {
109+ if (package.update_available) {
110+ update_numbers++;
111+ update_real_size += package.change_information.get_size ();
112+ }
113+ }
114+
115+ header.update (update_numbers, update_real_size, updating_cache);
116+
117+ // Unfortunately the update all button needs to be recreated everytime the header needs to be updated
118+ if (!updating_cache && update_numbers > 0) {
119+ update_all_button = new Widgets.AppActionButton (_("Update All"));
120+ update_all_button.set_suggested_action_header ();
121+ update_all_button.clicked.connect (on_update_all);
122+ action_button_group.add_widget (update_all_button);
123+
124+ header.add_widget (update_all_button);
125+ }
126+
127+ header.show_all ();
128+ row.set_header (header);
129+ } else {
130+ var header = new Widgets.UpdatedGrid ();
131+ header.update (0, 0, updating_cache);
132+ header.show_all ();
133+ row.set_header (header);
134+ }
135+ }
136+
137 private void on_update_all () {
138 perform_all_updates.begin ();
139 }
140@@ -278,42 +302,5 @@
141 return GLib.Source.REMOVE;
142 });
143 }
144-
145- private void update_headers () {
146- /* Do not repeatedly update headers while rapidly adding packages to list */
147- schedule_header_update ();
148- }
149-
150- uint grid_timeout_id = 0;
151- private void schedule_header_update () {
152- if (grid_timeout_id > 0) {
153- return;
154- }
155-
156- grid_timeout_id = GLib.Timeout.add (20, () => {
157- update_updates_grid ();
158- update_updated_grid ();
159- grid_timeout_id = 0;
160- return false;
161- });
162- }
163-
164- private void update_updates_grid () {
165- uint update_numbers = 0U;
166- uint64 update_real_size = 0ULL;
167- foreach (var package in get_packages ()) {
168- if (package.update_available) {
169- update_numbers++;
170- update_real_size += package.change_information.get_size ();
171- }
172- }
173-
174- updates_header.update (update_numbers, update_real_size, updating_cache);
175- update_all_button.visible = !updating_cache && update_numbers > 0;
176- }
177-
178- private void update_updated_grid () {
179- updated_header.update (0, 0, updating_cache);
180- }
181 }
182 }
183
184=== modified file 'src/Widgets/UpdateHeaderRow.vala'
185--- src/Widgets/UpdateHeaderRow.vala 2016-09-17 19:28:03 +0000
186+++ src/Widgets/UpdateHeaderRow.vala 2017-02-20 17:20:45 +0000
187@@ -19,153 +19,99 @@
188 */
189
190 namespace AppCenter.Widgets {
191- public class UpdateHeaderRow : Gtk.ListBoxRow, AppListRow {
192- AbstractHeaderGrid grid;
193- public bool is_updates_header {get; private set;}
194+ /** Base class for Grids in Header Rows **/
195+ public abstract class AbstractHeaderGrid : Gtk.Grid {
196+ public uint update_numbers {get; protected set; default = 0;}
197+ public uint64 update_real_size {get; protected set; default = 0;}
198+ public bool is_updating {get; protected set; default = false;}
199
200 construct {
201- set_activatable (false);
202- set_selectable (false);
203- }
204-
205- public UpdateHeaderRow.updates () {
206- grid = new UpdatesGrid ();
207- add (grid);
208- is_updates_header = true;
209- }
210-
211- public UpdateHeaderRow.updated () {
212- grid = new UpdatedGrid ();
213- add (grid);
214- is_updates_header = false;
215- }
216-
217- /** AppListRow Interface methods **/
218-
219- /** Updates header row reports it has updates in order to sort first in list **/
220- /** Updated header reports it has updates when updating in order to sort first in list **/
221- public bool get_update_available () {
222- return is_updates_header || grid.is_updating;
223- }
224-
225- public bool get_is_os_updates () {
226- critical ("Must not attempt to get is_os_update from header row");
227- assert_not_reached ();
228- }
229-
230- /* This indicates it is a header row, not a package row */
231- public bool has_package () {return false;}
232-
233- public AppCenterCore.Package? get_package () {
234- critical ("Must not attempt to get package from header row");
235- assert_not_reached ();
236- }
237-
238- public string get_name_label () {
239- critical ("Must not attempt to get package name from header row");
240- assert_not_reached ();
241+ margin = 12;
242+ column_spacing = 12;
243+ }
244+
245+ protected void store_data (uint _update_numbers, uint64 _update_real_size, bool _is_updating) {
246+ update_numbers = _update_numbers;
247+ update_real_size = _update_real_size;
248+ is_updating = _is_updating;
249 }
250
251 public void add_widget (Gtk.Widget widget) {
252- grid.add (widget);
253- }
254-
255- public void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) {
256- grid.update (_update_numbers, _update_real_size, _is_updating);
257- changed (); /* Triggers resort */
258- }
259- /** ---------------- **/
260-
261- /** Base class for Grids in Header Rows **/
262- private abstract class AbstractHeaderGrid : Gtk.Grid {
263- public uint update_numbers {get; protected set; default = 0;}
264- public uint64 update_real_size {get; protected set; default = 0;}
265- public bool is_updating {get; protected set; default = false;}
266-
267- construct {
268- margin = 12;
269- column_spacing = 12;
270- }
271-
272- protected void store_data (uint _update_numbers, uint64 _update_real_size, bool _is_updating) {
273- update_numbers = _update_numbers;
274- update_real_size = _update_real_size;
275- is_updating = _is_updating;
276- }
277-
278- public abstract void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating);
279- }
280-
281- /** Header to show at top of list if there are updates available **/
282- private class UpdatesGrid : AbstractHeaderGrid {
283- private Gtk.Label update_size_label;
284- private Gtk.Label updates_label;
285-
286- construct {
287- margin_top = 18;
288- updates_label = new Gtk.Label (null);
289- ((Gtk.Misc) updates_label).xalign = 0;
290- updates_label.get_style_context ().add_class ("h4");
291- updates_label.hexpand = true;
292-
293- update_size_label = new Gtk.Label (null);
294-
295- add (updates_label);
296- add (update_size_label);
297- }
298-
299- public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) {
300- store_data (_update_numbers, _update_real_size, _is_updating);
301-
302- if (!is_updating) {
303- updates_label.label = ngettext ("%u Update Available", "%u Updates Available", update_numbers).printf (update_numbers);
304- update_size_label.label = _("Size: %s").printf (GLib.format_size (update_real_size));
305- if (update_numbers > 0) {
306- show_all ();
307- } else {
308- hide ();
309- }
310- } else {
311- hide (); /* Updated header shows updating spinner and message */
312- }
313- }
314- }
315-
316- /** Header to show above first package that is up to date, or if the cache is updating **/
317- private class UpdatedGrid : AbstractHeaderGrid {
318- private Gtk.Label label;
319- private Gtk.Spinner spinner;
320-
321- construct {
322- label = new Gtk.Label (""); /* Should not be displayed before being updated */
323- label.hexpand = true;
324- ((Gtk.Misc)label).xalign = 0;
325-
326- spinner = new Gtk.Spinner ();
327-
328- add (label);
329- add (spinner);
330- }
331-
332- public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) {
333- store_data (_update_numbers, _update_real_size, _is_updating);
334-
335- if (is_updating) {
336- halign = Gtk.Align.CENTER;
337- spinner.start ();
338- spinner.no_show_all = false;
339- spinner.show ();
340- label.label = _("Searching for updates…");
341- label.get_style_context ().remove_class ("h4");
342- } else {
343- halign = Gtk.Align.START;
344- spinner.stop ();
345- spinner.no_show_all = true;
346- spinner.hide ();
347- label.label = _("Up to Date");
348- label.get_style_context ().add_class ("h4");
349- }
350- }
351- }
352- }
353-}
354+ add (widget);
355+ }
356+
357+ public abstract void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating);
358+ }
359+
360+ /** Header to show at top of list if there are updates available **/
361+ public class UpdatesGrid : AbstractHeaderGrid {
362+ private Gtk.Label update_size_label;
363+ private Gtk.Label updates_label;
364+
365+ construct {
366+ margin_top = 18;
367+ updates_label = new Gtk.Label (null);
368+ ((Gtk.Misc) updates_label).xalign = 0;
369+ updates_label.get_style_context ().add_class ("h4");
370+ updates_label.hexpand = true;
371+
372+ update_size_label = new Gtk.Label (null);
373+
374+ add (updates_label);
375+ add (update_size_label);
376+ }
377+
378+ public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) {
379+ store_data (_update_numbers, _update_real_size, _is_updating);
380+
381+ if (!is_updating) {
382+ updates_label.label = ngettext ("%u Update Available", "%u Updates Available", update_numbers).printf (update_numbers);
383+ update_size_label.label = _("Size: %s").printf (GLib.format_size (update_real_size));
384+ if (update_numbers > 0) {
385+ show_all ();
386+ } else {
387+ hide ();
388+ }
389+ } else {
390+ hide (); /* Updated header shows updating spinner and message */
391+ }
392+ }
393+ }
394+
395+ /** Header to show above first package that is up to date, or if the cache is updating **/
396+ public class UpdatedGrid : AbstractHeaderGrid {
397+ private Gtk.Label label;
398+ private Gtk.Spinner spinner;
399+
400+ construct {
401+ label = new Gtk.Label (""); /* Should not be displayed before being updated */
402+ label.hexpand = true;
403+ ((Gtk.Misc)label).xalign = 0;
404+
405+ spinner = new Gtk.Spinner ();
406+
407+ add (label);
408+ add (spinner);
409+ }
410+
411+ public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) {
412+ store_data (_update_numbers, _update_real_size, _is_updating);
413+
414+ if (is_updating) {
415+ halign = Gtk.Align.CENTER;
416+ spinner.start ();
417+ spinner.no_show_all = false;
418+ spinner.show ();
419+ label.label = _("Searching for updates…");
420+ label.get_style_context ().remove_class ("h4");
421+ } else {
422+ halign = Gtk.Align.START;
423+ spinner.stop ();
424+ spinner.no_show_all = true;
425+ spinner.hide ();
426+ label.label = _("Up to Date");
427+ label.get_style_context ().add_class ("h4");
428+ }
429+ }
430+ }
431+}
432\ No newline at end of file

Subscribers

People subscribed via source and target branches