Merge lp:~julien-spautz/switchboard-plug-keyboard/custom-shortcuts into lp:~elementary-pantheon/switchboard-plug-keyboard/trunk

Proposed by Cody Garver
Status: Merged
Merged at revision: 325
Proposed branch: lp:~julien-spautz/switchboard-plug-keyboard/custom-shortcuts
Merge into: lp:~elementary-pantheon/switchboard-plug-keyboard/trunk
Diff against target: 971 lines (+550/-233)
12 files modified
src/CMakeLists.txt (+4/-0)
src/Pages/Shortcuts/conflict_dialog.vala (+19/-0)
src/Pages/Shortcuts/custom_shortcut_settings.vala (+146/-0)
src/Pages/Shortcuts/custom_tree.vala (+178/-0)
src/Pages/Shortcuts/display.vala (+23/-11)
src/Pages/Shortcuts/display_tree.vala (+5/-0)
src/Pages/Shortcuts/list.vala (+1/-26)
src/Pages/Shortcuts/section_switcher.vala (+6/-3)
src/Pages/Shortcuts/settings.vala (+1/-1)
src/Pages/Shortcuts/shortcut.vala (+2/-2)
src/Pages/Shortcuts/tree.vala (+144/-181)
src/Pages/shortcuts.vala (+21/-9)
To merge this branch: bzr merge lp:~julien-spautz/switchboard-plug-keyboard/custom-shortcuts
Reviewer Review Type Date Requested Status
Raphael Isemann (community) code style, functionality Needs Fixing
Artem Anufrij (community) code style Needs Fixing
Danielle Foré Needs Fixing
David Gomes (community) Needs Fixing
Review via email: mp+212343@code.launchpad.net

Description of the change

Now open for review.

Implemented custom shortcuts into the keyboard plug. I'm using dconf/gsettings instead of gconf (unlike elementary tweaks) since the gconf version doesn't seem to work on isis, also it's deprecated.

Custom shortcuts can be added/removed/edited, the UI is a little different from the original ubuntu settings to avoid using unnecessary dialogs. I hope it's still intuitive.

If the schema for custom shortcuts doesn't exist, the section will not be shown at all.

Conflicting shortcuts are handled like before, asking the user whether he wants to reassign the shortcut.

NOTE that changes to custom shortcuts will, for some reason, not be applied immediately but you'll have to log out and in again, reboot or restart gnome-settings-daemon. This is not necessary with ubuntu's system settings, but I haven't yet figured out how to fix this.

To post a comment you must log in.
136. By Julien Spautz

small refactor: using DisplayTree instead of GtkTree to avoid casting

137. By Julien Spautz

remove some unused code

138. By Julien Spautz

fixed failing assertions on clearing shortcuts

Revision history for this message
David Gomes (davidgomes) wrote :

Code style wise this can't really pass for now. You added a new file that is tab-indented (conflict_dialog.vala). (and I realize you did it to keep consistency with existing files in the project, but new code should *usually* be good code).

Also diff lines 727-735 you mixed tabs and spaces.

I can't yet review the code itself, give me a couple of days. I'll test it in the meanwhile too.

review: Needs Fixing
139. By Julien Spautz

fix inconsistent whitespace

Revision history for this message
Julien Spautz (julien-spautz) wrote :

Completely forgot about the whitespace... Following files should now follow elementary's coding guidelines, all other files should still be internally consistent:

src/Pages/Shortcuts/conflict_dialog.vala
src/Pages/Shortcuts/custom_shortcut_settings.vala
src/Pages/Shortcuts/custom_tree.vala
src/Pages/Shortcuts/display_tree.vala
src/Pages/Shortcuts/tree.vala

(The four first files are new, the last one isn't, but I had to change a lot of code in that one so I converted it to elementary code)

140. By Julien Spautz

fixed small inconsistency in whitespace

Revision history for this message
David Gomes (davidgomes) wrote :

I can't seem to build this. First I got:

`
/usr/bin/msgfmt: error while opening "/home/david/src/switchboard-plug-keyboard/switchboard-plug-keyboard/build/po/el.mo" for writing: Permission denied
`

So I ran it with root privileges and got: http://paste.debian.net/91497/

Revision history for this message
Julien Spautz (julien-spautz) wrote :

built it on freya beta 1 and it works for me, can someone test it again?

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

Shortcuts don't seem to apply until I log out and log back in. Is there any way to make these apply immediately? (restart/update whatever service is responsible for watching for shortcuts?)

If not, we should at least show an infobar stating that you'll need to log out or restart for the changes to take effect.

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

The "-" button shouldn't be sensitive if there is no line selected

Revision history for this message
Artem Anufrij (artem-anufrij) wrote :

see line comments

review: Needs Fixing (code style)
Revision history for this message
Raphael Isemann (teemperor) wrote :

As Daniel said, you shouln't need to relog/reboot for the keybindings to take effect, so just set "org.gnome.settings-daemon.plugins.media-keys" to false and then to true again and GSD will reload the media-keys plugin.

Interestingly on my system if i do this noise seems to loose the binding to the next/previous keys on my keyboard until i restart noise. But i think that's rather a bug in noise itself?

Otherwise:
* Commented-out code in line 780-781.
* Line 417: tbar = new Gtk.Toolbar(); <- needs a blank before the bracket

review: Needs Fixing (code style, functionality)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2014-01-10 08:17:09 +0000
+++ src/CMakeLists.txt 2014-03-30 21:21:15 +0000
@@ -29,6 +29,10 @@
29 Pages/Shortcuts/shortcut.vala29 Pages/Shortcuts/shortcut.vala
30 Pages/Shortcuts/list.vala30 Pages/Shortcuts/list.vala
31 Pages/Shortcuts/section_switcher.vala31 Pages/Shortcuts/section_switcher.vala
32 Pages/Shortcuts/custom_tree.vala
33 Pages/Shortcuts/custom_shortcut_settings.vala
34 Pages/Shortcuts/conflict_dialog.vala
35 Pages/Shortcuts/display_tree.vala
32 36
33 Pages/layout.vala 37 Pages/layout.vala
34 Pages/Layout/display.vala38 Pages/Layout/display.vala
3539
=== added file 'src/Pages/Shortcuts/conflict_dialog.vala'
--- src/Pages/Shortcuts/conflict_dialog.vala 1970-01-01 00:00:00 +0000
+++ src/Pages/Shortcuts/conflict_dialog.vala 2014-03-30 21:21:15 +0000
@@ -0,0 +1,19 @@
1class ConflictDialog : Gtk.MessageDialog {
2
3 public signal void reassign ();
4
5 public ConflictDialog (string shortcut, string conflict_action, string this_action) {
6 modal = true;
7 message_type = Gtk.MessageType.WARNING;
8 text = @"\"$shortcut\" is already used for \"$conflict_action\"!";
9 secondary_text = _(@"If you reassign the shortcut to \"$this_action\", \"$conflict_action\" will be disabled");
10 add_button (_("Cancel"), 0);
11 add_button (_("Reassign"), 1);
12
13 response.connect ((response_id) => {
14 if (response_id == 1)
15 reassign ();
16 destroy();
17 });
18 }
19}
0\ No newline at end of file20\ No newline at end of file
121
=== added file 'src/Pages/Shortcuts/custom_shortcut_settings.vala'
--- src/Pages/Shortcuts/custom_shortcut_settings.vala 1970-01-01 00:00:00 +0000
+++ src/Pages/Shortcuts/custom_shortcut_settings.vala 2014-03-30 21:21:15 +0000
@@ -0,0 +1,146 @@
1class Pantheon.Keyboard.Shortcuts.CustomShortcutSettings : Object {
2
3 const string SCHEMA = "org.gnome.settings-daemon.plugins.media-keys";
4 const string KEY = "custom-keybinding";
5
6 const string RELOCATABLE_SCHEMA_PATH_TEMLPATE = "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom%d/";
7
8 const int MAX_SHORTCUTS = 100;
9
10 static GLib.Settings settings;
11
12 public static bool available = false;
13
14 public struct CustomShortcut {
15 string shortcut;
16 string command;
17 string relocatable_schema;
18 }
19
20 public static void init () {
21 var schema_source = GLib.SettingsSchemaSource.get_default ();
22
23 var schema = schema_source.lookup (SCHEMA, true);
24
25 if (schema == null) {
26 warning ("Schema \"%s\" is not installed on your system.", SCHEMA);
27 return;
28 }
29
30 settings = new GLib.Settings.full (schema, null, null);
31 available = true;
32 }
33
34 static string[] get_relocatable_schemas () {
35 return settings.get_strv (KEY + "s");
36 }
37
38 static string get_relocatable_schema_path (int i) {
39 return RELOCATABLE_SCHEMA_PATH_TEMLPATE.printf (i);
40 }
41
42 static GLib.Settings? get_relocatable_schema_settings (string relocatable_schema) {
43 return new GLib.Settings.with_path (SCHEMA + "." + KEY, relocatable_schema);
44 }
45
46 public static string? create_shortcut () requires (available) {
47 for (int i = 0; i < MAX_SHORTCUTS; i++) {
48 var new_relocatable_schema = get_relocatable_schema_path (i);
49
50 if (relocatable_schema_is_used (new_relocatable_schema) == false) {
51 add_relocatable_schema (new_relocatable_schema);
52 reset_relocatable_schema (new_relocatable_schema);
53 return new_relocatable_schema;
54 }
55 }
56
57 return (string) null;
58 }
59
60 static bool relocatable_schema_is_used (string new_relocatable_schema) {
61 var relocatable_schemas = get_relocatable_schemas ();
62
63 foreach (var relocatable_schema in relocatable_schemas)
64 if (relocatable_schema == new_relocatable_schema)
65 return true;
66
67 return false;
68 }
69
70 static void add_relocatable_schema (string new_relocatable_schema) {
71 var relocatable_schemas = get_relocatable_schemas ();
72 relocatable_schemas += new_relocatable_schema;
73 settings.set_strv (KEY + "s", relocatable_schemas);
74 }
75
76 static void reset_relocatable_schema (string relocatable_schema) {
77 var relocatable_settings = get_relocatable_schema_settings (relocatable_schema);
78 relocatable_settings.reset ("name");
79 relocatable_settings.reset ("command");
80 relocatable_settings.reset ("binding");
81 }
82
83 public static void remove_shortcut (string relocatable_schema)
84 requires (available) {
85
86 string []relocatable_schemas = {};
87
88 foreach (var schema in get_relocatable_schemas ())
89 if (schema != relocatable_schema)
90 relocatable_schemas += schema;
91
92 reset_relocatable_schema (relocatable_schema);
93 settings.set_strv (KEY + "s", relocatable_schemas);
94 }
95
96 public static bool edit_shortcut (string relocatable_schema, string shortcut)
97 requires (available) {
98
99 var relocatable_settings = get_relocatable_schema_settings (relocatable_schema);
100 relocatable_settings.set_string ("binding", shortcut);
101 return true;
102 }
103
104 public static bool edit_command (string relocatable_schema, string command)
105 requires (available) {
106
107 var relocatable_settings = get_relocatable_schema_settings (relocatable_schema);
108 relocatable_settings.set_string ("command", command);
109 return true;
110 }
111
112 public static GLib.List <CustomShortcut?> list_custom_shortcuts ()
113 requires (available) {
114
115 var list = new GLib.List <CustomShortcut?> ();
116 foreach (var relocatable_schema in get_relocatable_schemas ())
117 list.append (create_custom_shortcut_object (relocatable_schema));
118 return list;
119 }
120
121 static CustomShortcut? create_custom_shortcut_object (string relocatable_schema) {
122 var relocatable_settings = get_relocatable_schema_settings (relocatable_schema);
123
124 return {
125 relocatable_settings.get_string ("binding"),
126 relocatable_settings.get_string ("command"),
127 relocatable_schema
128 };
129 }
130
131 public static bool shortcut_conflicts (Shortcut new_shortcut, out string command,
132 out string relocatable_schema) {
133 var custom_shortcuts = list_custom_shortcuts ();
134
135 foreach (var custom_shortcut in custom_shortcuts) {
136 var shortcut = new Shortcut.parse (custom_shortcut.shortcut);
137 if (shortcut.is_equal (new_shortcut)) {
138 command = custom_shortcut.command;
139 relocatable_schema = custom_shortcut.relocatable_schema;
140 return true;
141 }
142 }
143
144 return false;
145 }
146}
0\ No newline at end of file147\ No newline at end of file
1148
=== added file 'src/Pages/Shortcuts/custom_tree.vala'
--- src/Pages/Shortcuts/custom_tree.vala 1970-01-01 00:00:00 +0000
+++ src/Pages/Shortcuts/custom_tree.vala 2014-03-30 21:21:15 +0000
@@ -0,0 +1,178 @@
1private class Pantheon.Keyboard.Shortcuts.CustomTree : Gtk.TreeView, DisplayTree {
2
3 Gtk.CellRendererText cell_desc;
4 Gtk.CellRendererAccel cell_edit;
5
6 enum Column {
7 COMMAND,
8 SHORTCUT,
9 SCHEMA,
10 COUNT
11 }
12
13 public CustomTree () {
14 setup_gui ();
15 load_and_display_custom_shortcuts ();
16 connect_signals ();
17 }
18
19 Gtk.ListStore list_store {
20 get { return model as Gtk.ListStore; }
21 }
22
23 void setup_gui () {
24 var store = new Gtk.ListStore (Column.COUNT , typeof (string),
25 typeof (string),
26 typeof (string));
27
28 cell_desc = new Gtk.CellRendererText ();
29 cell_edit = new Gtk.CellRendererAccel ();
30
31 cell_desc.editable = true;
32 cell_edit.editable = true;
33 cell_edit.accel_mode = Gtk.CellRendererAccelMode.OTHER;
34
35 this.set_model (store);
36
37 this.insert_column_with_attributes (-1, _("Command"), cell_desc, "markup", Column.COMMAND);
38 this.insert_column_with_attributes (-1, _("Shortcut"), cell_edit, "text", Column.SHORTCUT);
39
40 this.expand = true;
41 this.get_column (0).expand = true;
42 }
43
44 public void load_and_display_custom_shortcuts () {
45 Gtk.TreeIter iter;
46 var store = new Gtk.ListStore (Column.COUNT , typeof (string),
47 typeof (string),
48 typeof (string));
49
50 foreach (var custom_shortcut in CustomShortcutSettings.list_custom_shortcuts ()) {
51 var shortcut = new Shortcut.parse (custom_shortcut.shortcut);
52
53 store.append (out iter);
54 store.set (iter,
55 Column.COMMAND, command_to_display (custom_shortcut.command),
56 Column.SHORTCUT, shortcut.to_readable (),
57 Column.SCHEMA, custom_shortcut.relocatable_schema
58 );
59 }
60
61 model = store;
62 }
63
64 void connect_signals () {
65 this.button_press_event.connect ((event) => {
66 if (event.window != this.get_bin_window ())
67 return false;
68
69 Gtk.TreePath path;
70 Gtk.TreeViewColumn col;
71
72 if (this.get_path_at_pos ((int) event.x, (int) event.y,
73 out path, out col, null, null)) {
74 this.grab_focus ();
75 this.set_cursor (path, col, true);
76 }
77
78 return true;
79 });
80
81 cell_edit.accel_edited.connect ((path, key, mods) => {
82 var shortcut = new Shortcut (key, mods);
83 change_shortcut (path, shortcut);
84 });
85
86 cell_edit.accel_cleared.connect ((path) => {
87 change_shortcut (path, (Shortcut) null);
88 });
89
90 cell_desc.edited.connect (change_command);
91 }
92
93 string command_to_display (string? command) {
94 if (command == null || command.strip () == "")
95 return "<i>" +_("Enter Command") + "</i>";
96 return GLib.Markup.escape_text (command);
97 }
98
99 public void on_add_clicked () {
100 var store = model as Gtk.ListStore;
101 Gtk.TreeIter iter;
102
103 var relocatable_schema = CustomShortcutSettings.create_shortcut ();
104
105 store.append (out iter);
106 store.set (iter, Column.COMMAND, command_to_display (null));
107 store.set (iter, Column.SHORTCUT, (new Shortcut.parse ("")).to_readable ());
108 store.set (iter, Column.SCHEMA, relocatable_schema);
109 }
110
111 public void on_remove_clicked () {
112 Gtk.TreeIter iter;
113 Gtk.TreePath path;
114 GLib.Value relocatable_schema;
115
116 get_cursor (out path, null);
117 model.get_iter (out iter, path);
118 model.get_value (iter, Column.SCHEMA, out relocatable_schema);
119
120 CustomShortcutSettings.remove_shortcut ((string) relocatable_schema);
121 list_store.remove (iter);
122 }
123
124 void change_command (string path, string new_text) {
125 Gtk.TreeIter iter;
126 GLib.Value relocatable_schema;
127
128 model.get_iter (out iter, new Gtk.TreePath.from_string (path));
129 model.get_value (iter, Column.SCHEMA, out relocatable_schema);
130
131 CustomShortcutSettings.edit_command ((string) relocatable_schema, new_text);
132 load_and_display_custom_shortcuts ();
133 }
134
135 public bool shortcut_conflicts (Shortcut shortcut, out string name) {
136 return CustomShortcutSettings.shortcut_conflicts (shortcut, out name, null);
137 }
138
139 public void reset_shortcut (Shortcut shortcut) {
140 string relocatable_schema;
141 CustomShortcutSettings.shortcut_conflicts (shortcut, null, out relocatable_schema);
142 CustomShortcutSettings.edit_shortcut (relocatable_schema, "");
143 load_and_display_custom_shortcuts ();
144 }
145
146 bool change_shortcut (string path, Shortcut? shortcut) {
147 Gtk.TreeIter iter;
148 GLib.Value command, relocatable_schema;
149
150 model.get_iter (out iter, new Gtk.TreePath.from_string (path));
151 model.get_value (iter, Column.SCHEMA, out relocatable_schema);
152 model.get_value (iter, Column.COMMAND, out command);
153
154 var not_null_shortcut = shortcut ?? new Shortcut ();
155
156 string conflict_name;
157
158 if (shortcut != null) {
159 foreach (var tree in trees) {
160 if (tree.shortcut_conflicts (shortcut, out conflict_name) == false)
161 continue;
162
163 var dialog = new ConflictDialog (shortcut.to_readable (), conflict_name, (string) command);
164 dialog.reassign.connect (() => {
165 tree.reset_shortcut (shortcut);
166 CustomShortcutSettings.edit_shortcut ((string) relocatable_schema, not_null_shortcut.to_gsettings ());
167 load_and_display_custom_shortcuts ();
168 });
169 dialog.show ();
170 return false;
171 }
172 }
173
174 CustomShortcutSettings.edit_shortcut ((string) relocatable_schema, not_null_shortcut.to_gsettings ());
175 load_and_display_custom_shortcuts ();
176 return true;
177 }
178}
0\ No newline at end of file179\ No newline at end of file
1180
=== modified file 'src/Pages/Shortcuts/display.vala'
--- src/Pages/Shortcuts/display.vala 2014-01-06 17:12:27 +0000
+++ src/Pages/Shortcuts/display.vala 2014-03-30 21:21:15 +0000
@@ -1,3 +1,4 @@
1// TODO use new Gtk.Stack widget here
1namespace Pantheon.Keyboard.Shortcuts2namespace Pantheon.Keyboard.Shortcuts
2{3{
3 // creates a grid containing a tree view and an inline toolbar4 // creates a grid containing a tree view and an inline toolbar
@@ -6,16 +7,17 @@
6 int selected;7 int selected;
7 8
8 Gtk.ScrolledWindow scroll;9 Gtk.ScrolledWindow scroll;
9 Tree[] trees;10 DisplayTree[] trees;
10 11
11 public ShortcutDisplay (Tree[] t)12 Gtk.Toolbar tbar;
13
14 public ShortcutDisplay (DisplayTree[] t)
12 {15 {
13 selected = 0;16 selected = 0;
14 17
15 trees = t;18 foreach (var tree in t) {
16
17 foreach (var tree in trees) {
18 tree.set_rules_hint (true);19 tree.set_rules_hint (true);
20 trees += tree;
19 }21 }
20 22
21 scroll = new Gtk.ScrolledWindow(null, null);23 scroll = new Gtk.ScrolledWindow(null, null);
@@ -23,14 +25,15 @@
23 scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC;25 scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC;
24 scroll.shadow_type = Gtk.ShadowType.IN;26 scroll.shadow_type = Gtk.ShadowType.IN;
25 scroll.expand = true;27 scroll.expand = true;
26 scroll.add (trees[selected]);28 scroll.add (t[selected]);
27 29
28 var tbar = new Gtk.Toolbar();30 tbar = new Gtk.Toolbar();
29 tbar.set_style(Gtk.ToolbarStyle.ICONS);31 tbar.set_style(Gtk.ToolbarStyle.ICONS);
30 tbar.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR);32 tbar.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR);
31 tbar.set_show_arrow(false);33 tbar.set_show_arrow(false);
32 tbar.hexpand = true;34 tbar.hexpand = true;
33 35 tbar.no_show_all = true;
36
34 scroll.get_style_context().set_junction_sides(Gtk.JunctionSides.BOTTOM);37 scroll.get_style_context().set_junction_sides(Gtk.JunctionSides.BOTTOM);
35 tbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);38 tbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
36 tbar.get_style_context().set_junction_sides(Gtk.JunctionSides.TOP);39 tbar.get_style_context().set_junction_sides(Gtk.JunctionSides.TOP);
@@ -48,7 +51,12 @@
48 tbar.insert (remove_button, -1);51 tbar.insert (remove_button, -1);
4952
50 this.attach (scroll, 0, 0, 1, 1);53 this.attach (scroll, 0, 0, 1, 1);
51 //this.attach (tbar, 0, 1, 1, 1);54 this.attach (tbar, 0, 1, 1, 1);
55
56 add_button.clicked.connect (() =>
57 (trees[selected] as CustomTree).on_add_clicked ());
58 remove_button.clicked.connect (() =>
59 (trees[selected] as CustomTree).on_remove_clicked ());
52 }60 }
53 61
54 // replace old tree view with new one62 // replace old tree view with new one
@@ -58,7 +66,11 @@
58 scroll.add (trees[new_selection]);66 scroll.add (trees[new_selection]);
59 67
60 selected = new_selection;68 selected = new_selection;
61 scroll.show_all ();69
70 tbar.no_show_all = new_selection != SectionID.CUSTOM;
71 tbar.visible = new_selection == SectionID.CUSTOM;
72
73 show_all ();
62 74
63 return true;75 return true;
64 }76 }
6577
=== added file 'src/Pages/Shortcuts/display_tree.vala'
--- src/Pages/Shortcuts/display_tree.vala 1970-01-01 00:00:00 +0000
+++ src/Pages/Shortcuts/display_tree.vala 2014-03-30 21:21:15 +0000
@@ -0,0 +1,5 @@
1interface Pantheon.Keyboard.Shortcuts.DisplayTree : Gtk.TreeView {
2
3 public abstract bool shortcut_conflicts (Shortcut shortcut, out string name);
4 public abstract void reset_shortcut (Shortcut shortcut);
5}
0\ No newline at end of file6\ No newline at end of file
17
=== modified file 'src/Pages/Shortcuts/list.vala'
--- src/Pages/Shortcuts/list.vala 2014-03-12 08:11:41 +0000
+++ src/Pages/Shortcuts/list.vala 2014-03-30 21:21:15 +0000
@@ -21,31 +21,6 @@
21 return;21 return;
22 }22 }
23 23
24 public bool conflicts (Shortcut s, out string key, out int group, out int path)
25 {
26 key = (string) null;
27 group = (SectionID) 0;
28 path = -1;
29
30 if (s.accel_key == Gdk.Key.BackSpace)
31 return false;
32
33 for (int g = 0; g < groups.length; g++)
34 {
35 for (int i = 0; i < groups[g].actions.length; i++)
36 {
37 if (s.is_equal (settings.get_val(groups[g].schemas[i], groups[g].keys[i])))
38 {
39 key = groups[g].keys[i];
40 group = g;
41 path = i;
42 return true;
43 }
44 }
45 }
46 return false;
47 }
48
49 public List ()24 public List ()
50 {25 {
51 groups =26 groups =
@@ -70,7 +45,7 @@
70 _("Expose Windows"),45 _("Expose Windows"),
71 _("Expose all Windows")46 _("Expose all Windows")
72 },47 },
73 schemas = {48 schemas = {
74 Schema.WM,49 Schema.WM,
75 Schema.WM,50 Schema.WM,
76 Schema.WM,51 Schema.WM,
7752
=== modified file 'src/Pages/Shortcuts/section_switcher.vala'
--- src/Pages/Shortcuts/section_switcher.vala 2014-01-06 17:12:27 +0000
+++ src/Pages/Shortcuts/section_switcher.vala 2014-03-30 21:21:15 +0000
@@ -12,8 +12,11 @@
12 12
13 Gtk.TreeIter iter;13 Gtk.TreeIter iter;
14 14
15 // add the sections15 var max_section_id = CustomShortcutSettings.available
16 for (int id = 0; id < SectionID.COUNT; id++) {16 ? SectionID.COUNT
17 : SectionID.CUSTOM;
18
19 for (int id = 0; id < max_section_id; id++) {
17 store.append (out iter);20 store.append (out iter);
18 store.set (iter, 0, section_names[id]);21 store.set (iter, 0, section_names[id]);
19 }22 }
@@ -39,6 +42,6 @@
39 });42 });
40 }43 }
41 44
42 public signal void changed (int i);45 public signal bool changed (int i);
43 }46 }
44}47}
45\ No newline at end of file48\ No newline at end of file
4649
=== modified file 'src/Pages/Shortcuts/settings.vala'
--- src/Pages/Shortcuts/settings.vala 2014-01-06 17:12:27 +0000
+++ src/Pages/Shortcuts/settings.vala 2014-03-30 21:21:15 +0000
@@ -26,7 +26,7 @@
26 var schema = schema_source.lookup (name, true);26 var schema = schema_source.lookup (name, true);
27 27
28 if (schema == null) {28 if (schema == null) {
29 warning ("Schema \"%s\" is not installed on you system.", name);29 warning ("Schema \"%s\" is not installed on your system.", name);
30 schemas += (GLib.Settings) null;30 schemas += (GLib.Settings) null;
31 } else {31 } else {
32 schemas += new GLib.Settings.full (schema, null, null);32 schemas += new GLib.Settings.full (schema, null, null);
3333
=== modified file 'src/Pages/Shortcuts/shortcut.vala'
--- src/Pages/Shortcuts/shortcut.vala 2014-01-06 17:12:27 +0000
+++ src/Pages/Shortcuts/shortcut.vala 2014-03-30 21:21:15 +0000
@@ -10,7 +10,7 @@
10 string SEPARATOR = " · ";10 string SEPARATOR = " · ";
11 11
12 // constructors12 // constructors
13 public Shortcut ( uint key, Gdk.ModifierType mod )13 public Shortcut (uint key = 0, Gdk.ModifierType mod = (Gdk.ModifierType) 0)
14 {14 {
15 accel_key = key;15 accel_key = key;
16 modifiers = mod;16 modifiers = mod;
@@ -107,4 +107,4 @@
107 }107 }
108108
109 }109 }
110}
111\ No newline at end of file110\ No newline at end of file
111}
112112
=== modified file 'src/Pages/Shortcuts/tree.vala'
--- src/Pages/Shortcuts/tree.vala 2014-01-06 17:12:27 +0000
+++ src/Pages/Shortcuts/tree.vala 2014-03-30 21:21:15 +0000
@@ -1,182 +1,145 @@
1namespace Pantheon.Keyboard.Shortcuts1namespace Pantheon.Keyboard.Shortcuts {
2{2
3 // contains the shortcuts and handels all changes in gsettings3 private class Tree : Gtk.TreeView, DisplayTree {
4 private class Tree : Gtk.TreeView4
5 {5 public SectionID group { private get; construct; }
6 private string[] actions;6
7 private Schema[] schemas;7 private string[] actions;
8 private string[] keys;8 private Schema[] schemas;
9 9 private string[] keys;
10 // quick access to one item in the tree view10
11 public bool get_item (uint i, out string action, out Schema schema, out string key)11 public Tree (SectionID group) {
12 {12 Object (group: group);
13 action = null;13
14 schema = (Schema) null;14 load_and_display_shortcuts ();
15 key = null;15
16 16 var cell_desc = new Gtk.CellRendererText ();
17 if (i < actions.length)17 var cell_edit = new Gtk.CellRendererAccel ();
18 {18
19 action = actions[i];19 cell_edit.editable = true;
20 schema = schemas[i];20 cell_edit.accel_mode = Gtk.CellRendererAccelMode.OTHER;
21 key = keys[i];21
22 return true;22 this.insert_column_with_attributes (-1, null, cell_desc, "text", 0);
23 }23 this.insert_column_with_attributes (-1, null, cell_edit, "text", 1);
24 return false;24 //this.insert_column_with_attributes (-1, null, cell_desc, "text", 2);
25 }25 //this.insert_column_with_attributes (-1, null, cell_edit, "text", 3);
26 26
27 public Tree (SectionID group)27 this.headers_visible = false;
28 {28 this.expand = true;
29 list.get_group (group, out actions, out schemas, out keys);29
30 30 this.get_column (0).expand = true;
31 // create list store31
32 var store = new Gtk.ListStore (4, typeof (string),32 this.button_press_event.connect ((event) => {
33 typeof (string), 33 if (event.window != this.get_bin_window ())
34 typeof (Schema),34 return false;
35 typeof (string));35
3636 Gtk.TreePath path;
37 Gtk.TreeIter iter;37
38 38 if (this.get_path_at_pos ((int) event.x, (int) event.y,
39 for (int i = 0; i < actions.length; i++)39 out path, null, null, null)) {
40 {40 Gtk.TreeViewColumn col = this.get_column (1);
41 var shortcut = settings.get_val(schemas[i], keys[i]);41 this.grab_focus ();
42 42 this.set_cursor (path, col, true);
43 // simply ignore missing keys/schemas43 }
44 if (shortcut == null)44
45 continue;45 return true;
4646 });
47 store.append (out iter);47
48 store.set (iter, 0, actions[i], 48 cell_edit.accel_edited.connect ((path, key, mods) => {
49 1, shortcut.to_readable(),49 var shortcut = new Shortcut (key, mods);
50 2, schemas[i], // hidden50 change_shortcut (path, shortcut);
51 3, keys[i], -1); // hidden51 });
52 }52
53 53 cell_edit.accel_cleared.connect ((path) => {
54 // create tree view54 change_shortcut (path, (Shortcut) null);
55 var cell_desc = new Gtk.CellRendererText ();55 });
56 var cell_edit = new Gtk.CellRendererAccel ();56 }
57 57
58 cell_edit.editable = true;58 void load_and_display_shortcuts () {
59 cell_edit.accel_mode = Gtk.CellRendererAccelMode.OTHER;59 list.get_group (group, out actions, out schemas, out keys);
60 60
61 this.set_model (store);61 var store = new Gtk.ListStore (4, typeof (string), typeof (string),
6262 typeof (Schema), typeof (string));
63 this.insert_column_with_attributes (-1, null, cell_desc, "text", 0);63
64 this.insert_column_with_attributes (-1, null, cell_edit, "text", 1);64 Gtk.TreeIter iter;
65 // debug65
66 //this.insert_column_with_attributes (-1, null, cell_desc, "text", 2);66 for (int i = 0; i < actions.length; i++) {
67 //this.insert_column_with_attributes (-1, null, cell_edit, "text", 3);67 var shortcut = settings.get_val(schemas[i], keys[i]);
68 68
69 this.headers_visible = false;69 if (shortcut == null)
70 this.expand = true;70 continue;
71 71
72 this.get_column (0).expand = true;72 store.append (out iter);
73 73 store.set (iter, 0, actions[i],
74 this.button_press_event.connect ((event) =>74 1, shortcut.to_readable(),
75 {75 2, schemas[i], // hidden
76 if (event.window != this.get_bin_window ())76 3, keys[i], -1); // hidden
77 return false;77 }
78 78
79 Gtk.TreePath path;79 model = store;
80 80 }
81 if (this.get_path_at_pos ((int) event.x,81
82 (int) event.y,82 public bool shortcut_conflicts (Shortcut shortcut, out string name) {
83 out path, null,83 string[] actions, keys;
84 null, null))84 Schema[] schemas;
85 {85
86 Gtk.TreeViewColumn col = this.get_column (1);86 list.get_group (group, out actions, out schemas, out keys);
87 this.grab_focus ();87
88 this.set_cursor (path, col, true);88 for (int i = 0; i < actions.length; i++) {
89 }89 if (shortcut.is_equal (settings.get_val (schemas[i], keys[i]))) {
90 90 name = actions[i];
91 return true;91 return true;
92 } );92 }
93 93 }
94 // signals94
95 cell_edit.accel_edited.connect ((path, key, mods) => 95 return false;
96 {96 }
97 var shortcut = new Shortcut (key, mods);97
98 change_shortcut (path, shortcut);98 public void reset_shortcut (Shortcut shortcut) {
99 } );99 string[] actions, keys;
100 100 Schema[] schemas;
101 cell_edit.accel_cleared.connect ((path) => 101 var empty_shortcut = new Shortcut ();
102 {102
103 change_shortcut (path, (Shortcut) null);103 list.get_group (group, out actions, out schemas, out keys);
104 } );104
105 }105 for (int i = 0; i < actions.length; i++)
106 106 if (shortcut.is_equal (settings.get_val (schemas[i], keys[i])))
107 // change a shortcut in the list store and gsettings107 settings.set_val (schemas[i], keys[i], empty_shortcut);
108 private bool change_shortcut (string path, Shortcut? shortcut)108
109 {109 load_and_display_shortcuts ();
110 Gtk.TreeIter iter;110 }
111 GLib.Value key, schema, name;111
112 112 public bool change_shortcut (string path, Shortcut? shortcut) {
113 model.get_iter (out iter, new Gtk.TreePath.from_string (path));113 Gtk.TreeIter iter;
114 114 GLib.Value key, schema, name;
115 model.get_value (iter, 0, out name);115
116 model.get_value (iter, 2, out schema);116 model.get_iter (out iter, new Gtk.TreePath.from_string (path));
117 model.get_value (iter, 3, out key);117
118 118 model.get_value (iter, 0, out name);
119119 model.get_value (iter, 2, out schema);
120 if (shortcut != null)120 model.get_value (iter, 3, out key);
121 {121
122 // new shortcut is old shortcut?122 string conflict_name;
123 if (shortcut.is_equal (settings.get_val ((Schema)schema, (string)key)))123
124 return true;124 if (shortcut != null) {
125 125 foreach (var tree in trees) {
126 string conflict_accel;126 if (tree.shortcut_conflicts (shortcut, out conflict_name) == false)
127 int conflict_group;127 continue;
128 int conflict_path;128
129 129 var dialog = new ConflictDialog (shortcut.to_readable (), conflict_name, (string) name);
130 // check if shortcut is already used130 dialog.reassign.connect (() => {
131 if (list.conflicts (shortcut, out conflict_accel, out conflict_group, out conflict_path))131 tree.reset_shortcut (shortcut);
132 {132 settings.set_val ((Schema) schema, (string) key, shortcut);
133 string conflict_action;133 load_and_display_shortcuts ();
134 Schema conflict_schema;134 });
135 string conflict_key;135 dialog.show ();
136 136 return false;
137 // get some info about the conflicting item137 }
138 trees[conflict_group].get_item (conflict_path, out conflict_action, out conflict_schema, out conflict_key);138 }
139 139
140 // ask user what to do140 settings.set_val ((Schema) schema, (string) key, shortcut ?? new Shortcut ());
141 var msg = new Gtk.MessageDialog (null, Gtk.DialogFlags.MODAL,141 load_and_display_shortcuts ();
142 Gtk.MessageType.WARNING, 142 return true;
143 Gtk.ButtonsType.NONE, 143 }
144 "\"%s\" is already used for \"%s\"!", shortcut.to_readable (), conflict_action);144 }
145
146 msg.secondary_text = _("If you reassign the shortcut to \"%s\", \"%s\" will be disabled").printf ((string)name, conflict_action);
147 msg.add_button (_("Cancel"), 0);
148 msg.add_button (_("Reassign"), 1);
149
150 msg.response.connect ((response_id) =>
151 {
152 if (response_id == 1)
153 {
154 trees[conflict_group].change_shortcut (conflict_path.to_string (), (Shortcut) null);
155 change_shortcut (path, shortcut);
156 }
157
158 msg.destroy();
159 });
160 msg.show ();
161
162 return false;
163 }
164
165 if (!shortcut.valid ())
166 return false;
167 }
168
169 // unset/disable shortcut
170 if (shortcut == null)
171 {
172 (model as Gtk.ListStore).set (iter, 1, _("Disabled"));
173 settings.set_val((Schema)schema, (string)key, new Shortcut(0, (Gdk.ModifierType)0));
174 return true;
175 }
176
177 (model as Gtk.ListStore).set (iter, 1, shortcut.to_readable ());
178 settings.set_val((Schema)schema, (string)key, shortcut);
179 return true;
180 }
181 }
182}145}
183\ No newline at end of file146\ No newline at end of file
184147
=== modified file 'src/Pages/shortcuts.vala'
--- src/Pages/shortcuts.vala 2014-01-06 17:12:27 +0000
+++ src/Pages/shortcuts.vala 2014-03-30 21:21:15 +0000
@@ -5,9 +5,18 @@
5 // class to interact with gsettings5 // class to interact with gsettings
6 private Shortcuts.Settings settings;6 private Shortcuts.Settings settings;
7 // array of tree views, one for each section7 // array of tree views, one for each section
8 private Tree[] trees;8 private DisplayTree[] trees;
9 9
10 private enum SectionID { WINDOWS, WORKSPACES, SCREENSHOTS, APPS, MEDIA, A11Y, COUNT }10 private enum SectionID {
11 WINDOWS,
12 WORKSPACES,
13 SCREENSHOTS,
14 APPS,
15 MEDIA,
16 A11Y,
17 CUSTOM,
18 COUNT
19 }
11 20
12 private string[] section_names;21 private string[] section_names;
13 22
@@ -27,6 +36,8 @@
27 36
28 public Page ()37 public Page ()
29 {38 {
39 CustomShortcutSettings.init ();
40
30 // init public elements41 // init public elements
31 section_names = {42 section_names = {
32 _("Windows"),43 _("Windows"),
@@ -34,15 +45,18 @@
34 _("Screenshots"),45 _("Screenshots"),
35 _("Applications"),46 _("Applications"),
36 _("Media"),47 _("Media"),
37 _("Universal Access")48 _("Universal Access"),
49 _("Custom")
38 };50 };
39 51
40 list = new List ();52 list = new List ();
41 settings = new Shortcuts.Settings ();53 settings = new Shortcuts.Settings ();
42 54
43 for (int id = 0; id < SectionID.COUNT; id++) {55 for (int id = 0; id < SectionID.CUSTOM; id++)
44 trees += new Tree ((SectionID) id);56 trees += new Tree ((SectionID) id);
45 }57
58 if (CustomShortcutSettings.available)
59 trees += new CustomTree ();
46 60
47 // private elements61 // private elements
48 var shortcut_display = new ShortcutDisplay (trees);62 var shortcut_display = new ShortcutDisplay (trees);
@@ -51,9 +65,7 @@
51 this.attach (section_switcher, 0, 0, 1, 1);65 this.attach (section_switcher, 0, 0, 1, 1);
52 this.attach (shortcut_display, 1, 0, 2, 1);66 this.attach (shortcut_display, 1, 0, 2, 1);
53 67
54 section_switcher.changed.connect ((i) => {68 section_switcher.changed.connect (shortcut_display.change_selection);
55 shortcut_display.change_selection (i);
56 });
57 }69 }
58 }70 }
59}
60\ No newline at end of file71\ No newline at end of file
72}

Subscribers

People subscribed via source and target branches

to all changes: