Merge lp:~elementary-pantheon/switchboard/flowbox into lp:~elementary-pantheon/switchboard/switchboard

Proposed by Danielle Foré
Status: Merged
Approved by: Danielle Foré
Approved revision: 656
Merged at revision: 644
Proposed branch: lp:~elementary-pantheon/switchboard/flowbox
Merge into: lp:~elementary-pantheon/switchboard/switchboard
Diff against target: 847 lines (+290/-398)
6 files modified
schemas/org.pantheon.switchboard.gschema.xml (+2/-2)
src/CMakeLists.txt (+2/-0)
src/CategoryView.vala (+86/-380)
src/Switchboard.vala (+10/-16)
src/Widgets/CategoryFlowBox.vala (+139/-0)
src/Widgets/CategoryIcon.vala (+51/-0)
To merge this branch: bzr merge lp:~elementary-pantheon/switchboard/flowbox
Reviewer Review Type Date Requested Status
Adam Bieńkowski (community) testing Approve
Review via email: mp+294295@code.launchpad.net

Commit message

CategoryView.vala:
* Rewrite the icon views as FlowBoxes
* Update copyright header

Switchboard.vala:
* Code Style
* Update calls to icon views to FlowBoxes

Schemas:
* Update default window size to fit default plug icons

Widgets:
* Add CategoryFlowBox and CategoryIcon widgets

Description of the change

I've been staring at this code long enough to probably not realize if I'm doing dumb things. I have noticed two regressions, but I'm not sure what's causing them:

* Pressing down from search entry skips personal category
* [GLib] g_sequence_get: assertion '!is_end (iter)' failed

To post a comment you must log in.
655. By Danielle Foré

update default size to fit default plugs

656. By Danielle Foré

fix copyright dates in new widgets

Revision history for this message
Adam Bieńkowski (donadigo) wrote :

It works & looks great for me, besides those issues that are pointed out in the description.

review: Approve (testing)
Revision history for this message
Zisu Andrei (matzipan) wrote :
Download full text (3.9 KiB)

I personally don't like how it splits the distance equally between icons, it leads to a huge gap between them. Furthermore, it seems that even if there is enough space, the Wacom tablet icon in the Hardware flexbox is still saying on a separate line.

It seems if you have two rows of icons in "Personal", it only skips the first row, so it goes to the first icon in the second row. Maybe there's some overlap?

Below is the log of a gdb session where you can see the stacktrace of where that g_sequence_get assert failure is happening:

(gdb) bt
#0 0x00007ffff60063c0 in g_sequence_get (iter=0xc0c4c0)
    at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./glib/gsequence.c:1186
#1 0x0000000000411e48 in switchboard_category_has_child ()
#2 0x000000000040edd4 in switchboard_category_view_filter_plugs ()
#3 0x000000000040e793 in switchboard_category_view_add_plug ()
#4 0x000000000040e10b in __lambda11_ ()
#5 0x000000000040e15c in ___lambda11__gsource_func ()
#6 0x00007ffff5febfda in g_main_context_dispatch (context=0x666cb0)
    at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./glib/gmain.c:3154
#7 0x00007ffff5febfda in g_main_context_dispatch (context=context@entry=0x666cb0)
    at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./glib/gmain.c:3769
#8 0x00007ffff5fec380 in g_main_context_iterate (context=0x666cb0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./glib/gmain.c:3840
#9 0x00007ffff5fec6a2 in g_main_loop_run (loop=0xc96f40)
    at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./glib/gmain.c:4034
#10 0x00007ffff6a9f6f5 in gtk_main () at /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#11 0x0000000000407640 in _switchboard_switchboard_app_command_line ()
#12 0x0000000000406a62 in switchboard_switchboard_app_real_command_line ()
#13 0x00007ffff1c42e40 in ffi_call_unix64 () at /usr/lib/x86_64-linux-gnu/libffi.so.6
#14 0x00007ffff1c428ab in ffi_call () at /usr/lib/x86_64-linux-gnu/libffi.so.6
#15 0x00007ffff62c3cf5 in g_cclosure_marshal_generic_va (closure=0x70b480, return_value=0x7fffffffd9d0, instance=0xa8e150, args_list=<optimized out>, marshal_data=0x4069e4 <switchboard_switchboard_app_real_command_line>, n_params=1, param_types=0x70b4f0) at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./gobject/gclosure.c:1604
#16 0x00007ffff62c31d4 in _g_closure_invoke_va (closure=closure@entry=0x70b480, return_value=return_value@entry=0x7fffffffd9d0, instance=instance@entry=0xa8e150, args=args@entry=0x7fffffffdaa0, n_params=<optimized out>, param_types=0x70b4f0) at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./gobject/gclosure.c:867
#17 0x00007ffff62dd4b8 in g_signal_emit_valist (instance=0xa8e150, signal_id=<optimized out>, detail=0, var_args=var_args@entry=0x7fffffffdaa0) at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./gobject/gsignal.c:3294
#18 0x00007ffff62de08f in g_signal_emit (instance=instance@entry=0xa8e150, signal_id=<optimized out>, detail=detail@entry=0) at /build/glib2.0-t9oPgV/glib2.0-2.48.0/./gobject/gsignal.c:3441
#19 0x00007ffff65b1a13 in g_application_call_command_line (application=0xa8e150 [SwitchboardSwitchboardApp], arguments=<optimized out>, options=<optimized out>, exit_status=0x7fffffffdcd4)
    at /build/glib2.0-t9oPgV/gl...

Read more...

Revision history for this message
Danielle Foré (danrabbit) wrote :

Hm so it looks like it's throwing a fit over this line:
"foreach (unowned Gtk.Widget child in flowbox.get_children ())"

Revision history for this message
Cassidy James Blaede (cassidyjames) wrote :

Can confirm that this solves the HiDPI icon issues. Glorious, crispy icons. Under fairly normal window sizes, it appears to be working as I'd expect.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'schemas/org.pantheon.switchboard.gschema.xml'
2--- schemas/org.pantheon.switchboard.gschema.xml 2015-03-31 02:42:20 +0000
3+++ schemas/org.pantheon.switchboard.gschema.xml 2016-05-12 18:08:48 +0000
4@@ -11,12 +11,12 @@
5 <description>The saved state of the window.</description>
6 </key>
7 <key name="window-width" type="i">
8- <default>920</default>
9+ <default>950</default>
10 <summary>The saved width of the window.</summary>
11 <description>The saved width of the window. Must be greater than 700, or it will not take effect.</description>
12 </key>
13 <key name="window-height" type="i">
14- <default>640</default>
15+ <default>670</default>
16 <summary>The saved height of the window.</summary>
17 <description>The saved height of the window. Must be greater than 400, or it will not take effect.</description>
18 </key>
19
20=== modified file 'src/CMakeLists.txt'
21--- src/CMakeLists.txt 2016-05-04 01:43:34 +0000
22+++ src/CMakeLists.txt 2016-05-12 18:08:48 +0000
23@@ -3,6 +3,8 @@
24 CategoryView.vala
25 PlugsSearch.vala
26 NavigationButton.vala
27+ Widgets/CategoryFlowBox.vala
28+ Widgets/CategoryIcon.vala
29 )
30
31 vala_precompile (CLIENT_VALA_C ${CMAKE_PROJECT_NAME}
32
33=== modified file 'src/CategoryView.vala'
34--- src/CategoryView.vala 2016-05-04 01:43:34 +0000
35+++ src/CategoryView.vala 2016-05-12 18:08:48 +0000
36@@ -1,172 +1,54 @@
37-/***
38-BEGIN LICENSE
39-Copyright (C) 2011-2012 Avi Romanoff <aviromanoff@gmail.com>
40-This program is free software: you can redistribute it and/or modify it
41-under the terms of the GNU Lesser General Public License version 2.1, as published
42-by the Free Software Foundation.
43-
44-This program is distributed in the hope that it will be useful, but
45-WITHOUT ANY WARRANTY; without even the implied warranties of
46-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
47-PURPOSE. See the GNU General Public License for more details.
48-
49-You should have received a copy of the GNU General Public License along
50-with this program. If not, see <http://www.gnu.org/licenses/>.
51-END LICENSE
52-***/
53+/*
54+* Copyright (c) 2011-2016 elementary LLC (http://launchpad.net/switchboard)
55+*
56+* This program is free software; you can redistribute it and/or
57+* modify it under the terms of the GNU Lesser General Public
58+* License as published by the Free Software Foundation; either
59+* version 2.1 of the License, or (at your option) any later version.
60+*
61+* This program is distributed in the hope that it will be useful,
62+* but WITHOUT ANY WARRANTY; without even the implied warranty of
63+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
64+* General Public License for more details.
65+*
66+* You should have received a copy of the GNU General Public
67+* License along with this program; if not, write to the
68+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
69+* Boston, MA 02111-1307, USA.
70+*
71+* Authored by: Avi Romanoff <aviromanoff@gmail.com>
72+*/
73
74 namespace Switchboard {
75
76 public class CategoryView : Gtk.Grid {
77-
78- public enum Columns {
79- ICON,
80- TEXT,
81- DESCRIPTION,
82- VISIBLE,
83- PLUG,
84- N_COLUMNS
85- }
86-
87- const int ITEM_WIDTH = 96;
88-
89 public signal void plug_selected (Switchboard.Plug plug);
90
91- Gtk.IconTheme theme = Gtk.IconTheme.get_default ();
92- Gtk.Grid personal_grid;
93- Gtk.Grid hardware_grid;
94- Gtk.Grid network_grid;
95- Gtk.Grid system_grid;
96-
97- public Gtk.IconView personal_iconview;
98- public Gtk.IconView hardware_iconview;
99- public Gtk.IconView network_iconview;
100- public Gtk.IconView system_iconview;
101- public Gee.ArrayList<SearchEntry?> plug_search_result;
102+ public Gee.ArrayList <SearchEntry?> plug_search_result;
103+ public Switchboard.Category personal_category;
104+ public Switchboard.Category hardware_category;
105+ public Switchboard.Category network_category;
106+ public Switchboard.Category system_category;
107
108 private string? plug_to_open = null;
109- private PlugsSearch plug_search;
110-
111- public CategoryView (string? plug_to_open = null) {
112- this.plug_to_open = plug_to_open;
113- setup_category (Switchboard.Plug.Category.PERSONAL, 0);
114- setup_category (Switchboard.Plug.Category.HARDWARE, 1);
115- setup_category (Switchboard.Plug.Category.NETWORK, 2);
116- setup_category (Switchboard.Plug.Category.SYSTEM, 3);
117+ public PlugsSearch plug_search;
118+
119+ public CategoryView (string? plug = null) {
120+ orientation = Gtk.Orientation.VERTICAL;
121+ plug_to_open = plug;
122+
123+ personal_category = new Switchboard.Category (Switchboard.Plug.Category.PERSONAL);
124+ hardware_category = new Switchboard.Category (Switchboard.Plug.Category.HARDWARE);
125+ network_category = new Switchboard.Category (Switchboard.Plug.Category.NETWORK);
126+ system_category = new Switchboard.Category (Switchboard.Plug.Category.SYSTEM);
127+
128 plug_search = new PlugsSearch ();
129 plug_search_result = new Gee.ArrayList<SearchEntry?> ();
130- }
131-
132- private void setup_category (Switchboard.Plug.Category category, int i) {
133- var category_label = new Gtk.Label (get_category_name (category));
134- category_label.get_style_context ().add_class ("category-label");
135- category_label.halign = Gtk.Align.START;
136-
137- var category_plugs = setup_icon_view ();
138- category_plugs.get_style_context ().remove_class (Gtk.STYLE_CLASS_VIEW);
139-
140- var grid = new Gtk.Grid ();
141- grid.margin_start = 12;
142- grid.margin_end = 12;
143- grid.column_spacing = 6;
144-
145- // Always add a Seperator
146- var h_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL);
147- h_separator.set_hexpand (true);
148- grid.attach (category_label, 0, 0, 1, 1);
149- grid.attach (h_separator, 1, 0, 1, 1);
150-
151- grid.attach (category_plugs, 0, 1, 2, 1);
152- switch (category) {
153- case Switchboard.Plug.Category.PERSONAL:
154- personal_iconview = category_plugs;
155- personal_grid = grid;
156- break;
157- case Switchboard.Plug.Category.HARDWARE:
158- hardware_iconview = category_plugs;
159- hardware_grid = grid;
160- break;
161- case Switchboard.Plug.Category.NETWORK:
162- network_iconview = category_plugs;
163- network_grid = grid;
164- break;
165- case Switchboard.Plug.Category.SYSTEM:
166- system_iconview = category_plugs;
167- system_grid = grid;
168- break;
169- }
170-
171- category_plugs.focus_out_event.connect ((e) => {
172- category_plugs.unselect_all ();
173-
174- return false;
175- });
176-
177- category_plugs.focus_in_event.connect ((e) => {
178- Gtk.TreePath path;
179-
180- if (!category_plugs.get_cursor (out path, null)) {
181- path = new Gtk.TreePath.from_indices (0, -1);
182- }
183- category_plugs.select_path (path);
184-
185- return false;
186- });
187-
188- category_plugs.keynav_failed.connect ((direction) => {
189- Gtk.IconView new_view = null;
190- Gtk.TreePath path = null;
191- Gtk.TreePath selected_path = null;
192- int smallest_distance = 1000;
193- Gtk.TreeIter iter;
194- int distance;
195-
196- if (direction == Gtk.DirectionType.UP) {
197- new_view = get_prev_icon_view (category);
198- if (new_view != null && category_plugs.get_cursor (out path, null)) {
199- var current_column = category_plugs.get_item_column (path);
200- var model = new_view.get_model ();
201-
202- model.get_iter_first (out iter);
203- do {
204- path = model.get_path (iter);
205- var next_column = new_view.get_item_column (path);
206- distance = (next_column - current_column).abs ();
207- if (distance <= smallest_distance) {
208- selected_path = path;
209- smallest_distance = distance;
210- }
211- } while (model.iter_next (ref iter));
212- }
213- } else if (direction == Gtk.DirectionType.DOWN) {
214- new_view = get_next_icon_view (category);
215- if (new_view != null && category_plugs.get_cursor (out path, null)) {
216- var current_column = category_plugs.get_item_column (path);
217- var model = new_view.get_model ();
218-
219- model.get_iter_first (out iter);
220- do {
221- path = model.get_path (iter);
222- var next_column = new_view.get_item_column (path);
223- distance = (next_column - current_column).abs ();
224- if (distance < smallest_distance) {
225- selected_path = path;
226- smallest_distance = distance;
227- }
228- } while (model.iter_next (ref iter));
229- }
230- }
231-
232- if (new_view != null) {
233- new_view.set_cursor (selected_path, null, false);
234- new_view.grab_focus ();
235- return true;
236- }
237-
238- return false;
239- });
240-
241- attach (grid, 0, i, 1, 1);
242+
243+ add (personal_category);
244+ add (hardware_category);
245+ add (network_category);
246+ add (system_category);
247 }
248
249 public async void load_default_plugs () {
250@@ -188,32 +70,6 @@
251 });
252 }
253
254- private Gtk.IconView setup_icon_view () {
255- var store = new Gtk.ListStore (Columns.N_COLUMNS, typeof (Gdk.Pixbuf), typeof (string),
256- typeof(string), typeof(bool), typeof(Switchboard.Plug));
257- store.set_sort_column_id (1, Gtk.SortType.ASCENDING);
258- store.set_sort_column_id (1, Gtk.SortType.ASCENDING);
259-
260- var filtered = new Gtk.TreeModelFilter (store, null);
261- filtered.set_visible_column (3);
262- filtered.refilter ();
263-
264- var category_plugs = new Gtk.IconView.with_model (filtered);
265- category_plugs.set_item_width (ITEM_WIDTH);
266- category_plugs.set_text_column (Columns.TEXT);
267- category_plugs.set_pixbuf_column (Columns.ICON);
268- category_plugs.set_tooltip_column (Columns.DESCRIPTION);
269- category_plugs.set_hexpand (true);
270- category_plugs.set_selection_mode (Gtk.SelectionMode.SINGLE);
271- category_plugs.set_activate_on_single_click (true);
272-
273- category_plugs.item_activated.connect (on_item_activated);
274- var cellrenderer = (Gtk.CellRendererText)category_plugs.get_cells ().nth_data (0);
275- cellrenderer.wrap_mode = Pango.WrapMode.WORD_CHAR;
276-
277- return category_plugs;
278- }
279-
280 private void plug_visibility_changed (Switchboard.Plug plug) {
281 if (plug.can_show == true) {
282 add_plug (plug);
283@@ -221,45 +77,29 @@
284 }
285
286 public void add_plug (Switchboard.Plug plug) {
287- if (plug.can_show == false)
288+ if (plug.can_show == false) {
289 return;
290- Gtk.TreeIter root;
291- Gtk.TreeModelFilter model_filter;
292+ }
293+
294+ var icon = new Switchboard.CategoryIcon (plug);
295
296 switch (plug.category) {
297 case Switchboard.Plug.Category.PERSONAL:
298- model_filter = (Gtk.TreeModelFilter)personal_iconview.get_model ();
299- personal_grid.show_all ();
300+ personal_category.add (icon);
301 break;
302 case Switchboard.Plug.Category.HARDWARE:
303- model_filter = (Gtk.TreeModelFilter)hardware_iconview.get_model ();
304- hardware_grid.show_all ();
305+ hardware_category.add (icon);
306 break;
307 case Switchboard.Plug.Category.NETWORK:
308- model_filter = (Gtk.TreeModelFilter)network_iconview.get_model ();
309- network_grid.show_all ();
310+ network_category.add (icon);
311 break;
312 case Switchboard.Plug.Category.SYSTEM:
313- model_filter = (Gtk.TreeModelFilter)system_iconview.get_model ();
314- system_grid.show_all ();
315+ system_category.add (icon);
316 break;
317 default:
318 return;
319 }
320
321- var store = model_filter.child_model as Gtk.ListStore;
322- Gdk.Pixbuf icon_pixbuf = null;
323- try {
324- // FIXME: if we get no icon, we probably dont want that one…
325- icon_pixbuf = theme.load_icon (plug.icon, 32, Gtk.IconLookupFlags.GENERIC_FALLBACK);
326- } catch {
327- critical ("Unable to load plug %s's icon: %s", plug.display_name, plug.icon);
328- return;
329- }
330-
331- store.append (out root);
332- store.set (root, Columns.ICON, icon_pixbuf, Columns.TEXT, plug.display_name,
333- Columns.DESCRIPTION, plug.description, Columns.VISIBLE, true, Columns.PLUG, plug);
334 unowned SwitchboardApp app = (SwitchboardApp) GLib.Application.get_default ();
335 app.search_box.sensitive = true;
336 filter_plugs (app.search_box.get_text ());
337@@ -274,63 +114,51 @@
338 }
339 }
340
341-
342- // focus to first visible item
343 public void grab_focus_first_icon_view () {
344- Gtk.TreePath first_path = null;
345-
346- if (get_first_visible_path (personal_iconview, out first_path)) {
347- personal_iconview.grab_focus ();
348- } else if (get_first_visible_path (hardware_iconview, out first_path)) {
349- hardware_iconview.grab_focus ();
350- } else if (get_first_visible_path (network_iconview, out first_path)) {
351- network_iconview.grab_focus ();
352- } else if (get_first_visible_path (system_iconview, out first_path)) {
353- system_iconview.grab_focus ();
354- }
355+ if (personal_category.has_child ()) {
356+ personal_category.focus_first_child ();
357+ } else if (hardware_category.has_child ()) {
358+ hardware_category.focus_first_child ();
359+ } else if (network_category.has_child ()) {
360+ network_category.focus_first_child ();
361+ } else if (system_category.has_child ()) {
362+ system_category.focus_first_child ();
363+ }
364 }
365
366- // activate first visible item
367 public void activate_first_item () {
368- Gtk.TreePath first_path = null;
369-
370- if (get_first_visible_path (personal_iconview, out first_path)) {
371- personal_iconview.item_activated (first_path);
372- } else if (get_first_visible_path (hardware_iconview, out first_path)){
373- hardware_iconview.item_activated (first_path);
374- } else if (get_first_visible_path (network_iconview, out first_path)){
375- network_iconview.item_activated (first_path);
376- } else if (get_first_visible_path (system_iconview, out first_path)){
377- system_iconview.item_activated (first_path);
378- }
379- }
380-
381- private bool get_first_visible_path (Gtk.IconView iv, out Gtk.TreePath path) {
382- Gtk.TreePath end;
383-
384- return (iv.get_visible_range (out path, out end));
385+ if (personal_category.has_child ()) {
386+ personal_category.activate_first_child ();
387+ } else if (hardware_category.has_child ()) {
388+ hardware_category.activate_first_child ();
389+ } else if (network_category.has_child ()) {
390+ network_category.activate_first_child ();
391+ } else if (system_category.has_child ()) {
392+ system_category.activate_first_child ();
393+ }
394 }
395
396 public void filter_plugs (string filter) {
397-
398 var any_found = false;
399- var model_filter = (Gtk.TreeModelFilter) personal_iconview.get_model ();
400- if (search_by_category (filter, model_filter, personal_grid)) {
401- any_found = true;
402- }
403-
404- model_filter = (Gtk.TreeModelFilter) hardware_iconview.get_model ();
405- if (search_by_category (filter, model_filter, hardware_grid)) {
406- any_found = true;
407- }
408-
409- model_filter = (Gtk.TreeModelFilter) network_iconview.get_model ();
410- if (search_by_category (filter, model_filter, network_grid)) {
411- any_found = true;
412- }
413-
414- model_filter = (Gtk.TreeModelFilter) system_iconview.get_model ();
415- if (search_by_category (filter, model_filter, system_grid)) {
416+
417+ personal_category.filter ();
418+ hardware_category.filter ();
419+ network_category.filter ();
420+ system_category.filter ();
421+
422+ if (personal_category.has_child ()) {
423+ any_found = true;
424+ }
425+
426+ if (hardware_category.has_child ()) {
427+ any_found = true;
428+ }
429+
430+ if (network_category.has_child ()) {
431+ any_found = true;
432+ }
433+
434+ if (system_category.has_child ()) {
435 any_found = true;
436 }
437
438@@ -342,78 +170,6 @@
439 }
440 }
441
442- private void deep_search (string filter) {
443- if (plug_search.ready) {
444- plug_search_result.clear ();
445- foreach (var tmp in plug_search.search_entries) {
446- if (tmp.ui_elements.down ().contains (filter.down ())) {
447- plug_search_result.add (tmp);
448- }
449- }
450- }
451- }
452-
453- private bool search_by_category (string filter, Gtk.TreeModelFilter model_filter, Gtk.Widget grid) {
454-
455- deep_search (filter);
456- var store = model_filter.child_model as Gtk.ListStore;
457- int shown = 0;
458- store.foreach ((model, path, iter) => {
459- string title;
460-
461- store.get (iter, Columns.TEXT, out title);
462- bool show_element = false;
463- foreach (var tmp in plug_search_result) {
464- if (tmp.plug_name.down () in title.down ()) {
465- store.set_value (iter, Columns.VISIBLE, true);
466- shown++;
467- show_element = true;
468- }
469- }
470-
471- if (filter.down () in title.down ()) {
472- store.set_value (iter, Columns.VISIBLE, true);
473- shown++;
474- } else if (!show_element) {
475- store.set_value (iter, Columns.VISIBLE, false);
476- }
477-
478- return false;
479- });
480-
481- if (shown == 0) {
482- grid.hide ();
483- return false;
484- } else {
485- grid.show_all ();
486- return true;
487- }
488- }
489-
490- public void recalculate_columns () {
491- int columns = personal_iconview.get_columns ();
492- columns = int.max (columns, hardware_iconview.get_columns ());
493- columns = int.max (columns, network_iconview.get_columns ());
494- columns = int.max (columns, system_iconview.get_columns ());
495- personal_iconview.set_columns (columns);
496- hardware_iconview.set_columns (columns);
497- network_iconview.set_columns (columns);
498- system_iconview.set_columns (columns);
499- }
500-
501- private void on_item_activated (Gtk.IconView view, Gtk.TreePath path) {
502- GLib.Value plug;
503- Gtk.TreeIter selected_plug;
504- var store = view.get_model ();
505-
506- store.get_iter (out selected_plug, path);
507- store.get_value (selected_plug, Columns.PLUG, out plug);
508-
509- plug_selected ((Switchboard.Plug) plug.get_object ());
510-
511- view.unselect_path (path);
512- }
513-
514 public static string? get_category_name (Switchboard.Plug.Category category) {
515 switch (category) {
516 case Plug.Category.PERSONAL:
517@@ -428,55 +184,5 @@
518
519 return null;
520 }
521-
522- private Gtk.IconView? get_next_icon_view (Switchboard.Plug.Category category) {
523- if (category == Plug.Category.PERSONAL) {
524- if (hardware_iconview.is_visible ())
525- return hardware_iconview;
526- else
527- category = Plug.Category.HARDWARE;
528- }
529-
530- if (category == Plug.Category.HARDWARE) {
531- if (network_iconview.is_visible ())
532- return network_iconview;
533- else
534- category = Plug.Category.NETWORK;
535- }
536-
537- if (category == Plug.Category.NETWORK) {
538- if (system_iconview.is_visible ())
539- return system_iconview;
540- else
541- category = Plug.Category.SYSTEM;
542- }
543-
544- return null;
545- }
546-
547- private Gtk.IconView? get_prev_icon_view (Switchboard.Plug.Category category) {
548- if (category == Plug.Category.SYSTEM) {
549- if (network_iconview.is_visible ())
550- return network_iconview;
551- else
552- category = Plug.Category.NETWORK;
553- }
554-
555- if (category == Plug.Category.NETWORK) {
556- if (hardware_iconview.is_visible ())
557- return hardware_iconview;
558- else
559- category = Plug.Category.HARDWARE;
560- }
561-
562- if (category == Plug.Category.HARDWARE) {
563- if (personal_iconview.is_visible ())
564- return personal_iconview;
565- else
566- category = Plug.Category.SYSTEM;
567- }
568-
569- return null;
570- }
571 }
572 }
573
574=== modified file 'src/Switchboard.vala'
575--- src/Switchboard.vala 2016-05-04 13:49:32 +0000
576+++ src/Switchboard.vala 2016-05-12 18:08:48 +0000
577@@ -39,7 +39,7 @@
578 private Granite.Widgets.AlertView alert_view;
579 private Gtk.ScrolledWindow category_scrolled;
580 private Switchboard.NavigationButton navigation_button;
581- private Switchboard.CategoryView category_view;
582+ public Switchboard.CategoryView category_view;
583
584 private Gee.LinkedList <string> loaded_plugs;
585 private string all_settings_label = _("All Settings");
586@@ -310,9 +310,9 @@
587 navigation_button.hide ();
588
589 main_window.size_allocate.connect (() => {
590- if (opened_directly)
591+ if (opened_directly) {
592 search_box.sensitive = false;
593- category_view.recalculate_columns ();
594+ }
595 });
596
597 if (Switchboard.PlugsManager.get_default ().has_plugs () == false) {
598@@ -504,31 +504,27 @@
599 var category_item = new Dbusmenu.Menuitem ();
600 category_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, CategoryView.get_category_name (category));
601
602- Gtk.TreeModelFilter model_filter;
603+ var plugs = new Gee.ArrayList<Plug?> ();
604 switch (category) {
605 case Switchboard.Plug.Category.PERSONAL:
606- model_filter = (Gtk.TreeModelFilter)category_view.personal_iconview.get_model ();
607+ plugs = category_view.personal_category.get_plugs ();
608 break;
609 case Switchboard.Plug.Category.HARDWARE:
610- model_filter = (Gtk.TreeModelFilter)category_view.hardware_iconview.get_model ();
611+ plugs = category_view.hardware_category.get_plugs ();
612 break;
613 case Switchboard.Plug.Category.NETWORK:
614- model_filter = (Gtk.TreeModelFilter)category_view.network_iconview.get_model ();
615+ plugs = category_view.network_category.get_plugs ();
616 break;
617 case Switchboard.Plug.Category.SYSTEM:
618- model_filter = (Gtk.TreeModelFilter)category_view.system_iconview.get_model ();
619+ plugs = category_view.system_category.get_plugs ();
620 break;
621 default:
622 return null;
623 }
624
625- var category_store = model_filter.child_model as Gtk.ListStore;
626 bool empty = true;
627
628- category_store.foreach ((model, path, iter) => {
629- Switchboard.Plug plug;
630- category_store.get (iter, CategoryView.Columns.PLUG, out plug);
631-
632+ foreach (var plug in plugs) {
633 var item = new Dbusmenu.Menuitem ();
634 item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, plug.display_name);
635
636@@ -541,9 +537,7 @@
637 // Add item to correct category
638 category_item.child_append (item);
639 empty = false;
640-
641- return false;
642- });
643+ }
644
645 return (empty ? null : category_item);
646 }
647
648=== added directory 'src/Widgets'
649=== added file 'src/Widgets/CategoryFlowBox.vala'
650--- src/Widgets/CategoryFlowBox.vala 1970-01-01 00:00:00 +0000
651+++ src/Widgets/CategoryFlowBox.vala 2016-05-12 18:08:48 +0000
652@@ -0,0 +1,139 @@
653+/*
654+* Copyright (c) 2016 elementary LLC (http://launchpad.net/switchboard)
655+*
656+* This program is free software; you can redistribute it and/or
657+* modify it under the terms of the GNU General Public
658+* License as published by the Free Software Foundation; either
659+* version 2 of the License, or (at your option) any later version.
660+*
661+* This program is distributed in the hope that it will be useful,
662+* but WITHOUT ANY WARRANTY; without even the implied warranty of
663+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
664+* General Public License for more details.
665+*
666+* You should have received a copy of the GNU General Public
667+* License along with this program; if not, write to the
668+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
669+* Boston, MA 02111-1307, USA.
670+*
671+*/
672+
673+namespace Switchboard {
674+
675+ public class Category : Gtk.Grid {
676+
677+ private Gtk.FlowBox flowbox;
678+
679+ public Category (Switchboard.Plug.Category category) {
680+ var category_label = new Gtk.Label (Switchboard.CategoryView.get_category_name (category));
681+ category_label.get_style_context ().add_class ("category-label");
682+ category_label.halign = Gtk.Align.START;
683+
684+ var h_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL);
685+ h_separator.set_hexpand (true);
686+
687+ flowbox = new Gtk.FlowBox ();
688+ flowbox.activate_on_single_click = true;
689+ flowbox.column_spacing = 12;
690+ flowbox.row_spacing = 12;
691+ flowbox.homogeneous = true;
692+ flowbox.selection_mode = Gtk.SelectionMode.NONE;
693+
694+ margin_bottom = 12;
695+ margin_start = 12;
696+ margin_end = 12;
697+
698+ column_spacing = 3;
699+ row_spacing = 6;
700+
701+ attach (category_label, 0, 0, 1, 1);
702+ attach (h_separator, 1, 0, 1, 1);
703+ attach (flowbox, 0, 1, 2, 1);
704+
705+ flowbox.child_activated.connect ((child) => {
706+ Switchboard.SwitchboardApp.instance.load_plug (((CategoryIcon) child).plug);
707+ });
708+
709+ flowbox.set_filter_func (plug_filter_func);
710+ flowbox.set_sort_func (plug_sort_func);
711+ }
712+
713+ public Gee.ArrayList get_plugs () {
714+ var plugs = new Gee.ArrayList<Plug?> ();
715+ foreach (unowned Gtk.Widget child in flowbox.get_children ()) {
716+ plugs.add (((CategoryIcon) child).plug);
717+ }
718+ return plugs;
719+ }
720+
721+ public new void add (Gtk.Widget widget) {
722+ flowbox.add (widget);
723+ }
724+
725+ public void activate_first_child () {
726+ foreach (unowned Gtk.Widget child in flowbox.get_children ()) {
727+ if (child.get_child_visible ()) {
728+ child.activate ();
729+ return;
730+ }
731+ }
732+ }
733+
734+ public void filter () {
735+ flowbox.invalidate_filter ();
736+ }
737+
738+ public void focus_first_child () {
739+ flowbox.get_child_at_index (0).grab_focus ();
740+ }
741+
742+ public bool has_child () {
743+ if (flowbox.get_child_at_index (0) != null) {
744+ foreach (unowned Gtk.Widget child in flowbox.get_children ()) {
745+ if (child.get_child_visible ()) {
746+ show_all ();
747+ return true;
748+ }
749+ }
750+ }
751+ hide ();
752+ return false;
753+ }
754+
755+ private bool plug_filter_func (Gtk.FlowBoxChild child) {
756+ var filter = SwitchboardApp.instance.search_box.get_text ();
757+ var plug_name = ((CategoryIcon) child).plug.display_name;
758+ var plug_search = SwitchboardApp.instance.category_view.plug_search;
759+ var plug_search_result = SwitchboardApp.instance.category_view.plug_search_result;
760+
761+ if (plug_search.ready) {
762+ plug_search_result.clear ();
763+
764+ foreach (var tmp in plug_search.search_entries) {
765+ if (tmp.ui_elements.down ().contains (filter.down ())) {
766+ plug_search_result.add (tmp);
767+ }
768+ }
769+
770+ foreach (var tmp in plug_search_result) {
771+ if (tmp.plug_name.down () in plug_name.down ()) {
772+ return true;
773+ }
774+ }
775+ }
776+
777+ if (filter.down () in plug_name.down ()) {
778+ return true;
779+ }
780+
781+ return false;
782+ }
783+
784+ private int plug_sort_func (Gtk.FlowBoxChild child_a, Gtk.FlowBoxChild child_b) {
785+ var plug_name_a = ((CategoryIcon) child_a).plug.display_name;
786+ var plug_name_b = ((CategoryIcon) child_b).plug.display_name;
787+
788+ return strcmp (plug_name_a, plug_name_b);
789+ }
790+ }
791+}
792
793=== added file 'src/Widgets/CategoryIcon.vala'
794--- src/Widgets/CategoryIcon.vala 1970-01-01 00:00:00 +0000
795+++ src/Widgets/CategoryIcon.vala 2016-05-12 18:08:48 +0000
796@@ -0,0 +1,51 @@
797+/*
798+* Copyright (c) 2016 elementary LLC (http://launchpad.net/switchboard)
799+*
800+* This program is free software; you can redistribute it and/or
801+* modify it under the terms of the GNU General Public
802+* License as published by the Free Software Foundation; either
803+* version 2 of the License, or (at your option) any later version.
804+*
805+* This program is distributed in the hope that it will be useful,
806+* but WITHOUT ANY WARRANTY; without even the implied warranty of
807+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
808+* General Public License for more details.
809+*
810+* You should have received a copy of the GNU General Public
811+* License along with this program; if not, write to the
812+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
813+* Boston, MA 02111-1307, USA.
814+*
815+*/
816+
817+namespace Switchboard {
818+
819+ public class CategoryIcon : Gtk.FlowBoxChild {
820+
821+ public Switchboard.Plug plug;
822+
823+ public CategoryIcon (Switchboard.Plug plug_item) {
824+ plug = plug_item;
825+ width_request = 144;
826+
827+ var icon = new Gtk.Image.from_icon_name (plug.icon, Gtk.IconSize.DND);
828+ icon.tooltip_text = plug.description;
829+
830+ var plug_name = new Gtk.Label (plug.display_name);
831+ plug_name.justify = Gtk.Justification.CENTER;
832+ plug_name.max_width_chars = 18;
833+ plug_name.wrap = true;
834+ plug_name.wrap_mode = Pango.WrapMode.WORD_CHAR;
835+
836+ var layout = new Gtk.Grid ();
837+ layout.halign = Gtk.Align.CENTER;
838+ layout.margin = 6;
839+ layout.orientation = Gtk.Orientation.VERTICAL;
840+
841+ layout.add (icon);
842+ layout.add (plug_name);
843+
844+ add (layout);
845+ }
846+ }
847+}

Subscribers

People subscribed via source and target branches