3 #include <ardour/profile.h>
5 #include <gtkmm/stock.h>
6 #include <gtkmm/label.h>
7 #include <gtkmm/accelkey.h>
8 #include <gtkmm/accelmap.h>
9 #include <gtkmm/uimanager.h>
11 #include <pbd/strsplit.h>
12 #include <pbd/replace_all.h>
14 #include <ardour/profile.h>
18 #include "keyeditor.h"
28 KeyEditor::KeyEditor ()
29 : ArdourDialog (_("Keybindings"), false)
30 , unbind_button (_("Remove shortcut"))
31 , unbind_box (BUTTONBOX_END
)
37 model
= TreeStore::create(columns
);
39 view
.set_model (model
);
40 view
.append_column (_("Action"), columns
.action
);
41 view
.append_column (_("Shortcut"), columns
.binding
);
42 view
.set_headers_visible (true);
43 view
.get_selection()->set_mode (SELECTION_SINGLE
);
44 view
.set_reorderable (false);
45 view
.set_size_request (500,300);
46 view
.set_enable_search (false);
47 view
.set_rules_hint (true);
48 view
.set_name (X_("KeyEditorTree"));
50 view
.get_selection()->signal_changed().connect (mem_fun (*this, &KeyEditor::action_selected
));
53 scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
56 get_vbox()->set_spacing (6);
57 get_vbox()->pack_start (scroller
);
59 if (!ARDOUR::Profile
->get_sae()) {
61 Label
* hint
= manage (new Label (_("Select an action, then press the key(s) to (re)set its shortcut")));
63 unbind_box
.set_spacing (6);
64 unbind_box
.pack_start (*hint
, false, true);
65 unbind_box
.pack_start (unbind_button
, false, false);
66 unbind_button
.signal_clicked().connect (mem_fun (*this, &KeyEditor::unbind
));
68 get_vbox()->pack_start (unbind_box
, false, false);
70 unbind_button
.show ();
74 get_vbox()->set_border_width (12);
79 unbind_button
.set_sensitive (false);
85 TreeModel::iterator i
= view
.get_selection()->get_selected();
87 unbind_button
.set_sensitive (false);
89 if (i
!= model
->children().end()) {
90 string path
= (*i
)[columns
.path
];
92 if (!(*i
)[columns
.bindable
]) {
96 bool result
= AccelMap::change_entry (path
,
101 (*i
)[columns
.binding
] = string ();
107 KeyEditor::on_show ()
110 view
.get_selection()->unselect_all ();
111 ArdourDialog::on_show ();
115 KeyEditor::on_unmap ()
117 ArdourDialog::on_unmap ();
121 KeyEditor::action_selected ()
123 if (view
.get_selection()->count_selected_rows() == 0) {
127 TreeModel::iterator i
= view
.get_selection()->get_selected();
129 unbind_button
.set_sensitive (false);
131 if (i
!= model
->children().end()) {
133 string path
= (*i
)[columns
.path
];
135 if (!(*i
)[columns
.bindable
]) {
139 string binding
= (*i
)[columns
.binding
];
141 if (!binding
.empty()) {
142 unbind_button
.set_sensitive (true);
148 KeyEditor::on_key_press_event (GdkEventKey
* ev
)
151 last_state
= ev
->state
;
156 KeyEditor::on_key_release_event (GdkEventKey
* ev
)
158 if (ARDOUR::Profile
->get_sae() || !can_bind
|| ev
->state
!= last_state
) {
162 TreeModel::iterator i
= view
.get_selection()->get_selected();
164 if (i
!= model
->children().end()) {
165 string path
= (*i
)[columns
.path
];
167 if (!(*i
)[columns
.bindable
]) {
171 possibly_translate_keyval_to_make_legal_accelerator (ev
->keyval
);
173 bool result
= AccelMap::change_entry (path
,
175 ModifierType (Keyboard::RelevantModifierKeyMask
& ev
->state
),
182 known
= ActionManager::lookup_entry (path
, key
);
185 (*i
)[columns
.binding
] = ActionManager::ui_manager
->get_accel_group()->name (key
.get_key(), Gdk::ModifierType (key
.get_mod()));
187 (*i
)[columns
.binding
] = string();
198 KeyEditor::populate ()
200 vector
<string
> paths
;
201 vector
<string
> labels
;
203 vector
<AccelKey
> bindings
;
204 typedef std::map
<string
,TreeIter
> NodeMap
;
208 ActionManager::get_all_actions (labels
, paths
, keys
, bindings
);
210 vector
<string
>::iterator k
;
211 vector
<string
>::iterator p
;
212 vector
<string
>::iterator l
;
216 for (l
= labels
.begin(), k
= keys
.begin(), p
= paths
.begin(); l
!= labels
.end(); ++k
, ++p
, ++l
) {
219 vector
<string
> parts
;
223 split (*p
, parts
, '/');
229 if ((r
= nodes
.find (parts
[1])) == nodes
.end()) {
231 /* top level is missing */
234 TreeModel::Row parent
;
235 rowp
= model
->append();
236 nodes
[parts
[1]] = rowp
;
238 parent
[columns
.action
] = parts
[1];
239 parent
[columns
.bindable
] = false;
241 row
= *(model
->append (parent
.children()));
245 row
= *(model
->append ((*r
->second
)->children()));
249 /* add this action */
251 row
[columns
.action
] = (*l
);
252 row
[columns
.path
] = (*p
);
253 row
[columns
.bindable
] = true;
255 if (*k
== ActionManager::unbound_string
) {
256 row
[columns
.binding
] = string();
263 NSAlternate/NSOption key to Mod1
264 NSCommand key to Meta
267 replace_all (label
, "<Meta>", _("Command-"));
268 replace_all (label
, "<Alt>", _("Option-"));
269 replace_all (label
, "<Shift>", _("Shift-"));
270 replace_all (label
, "<Control>", _("Control-"));
271 row
[columns
.binding
] = label
;
273 row
[columns
.binding
] = (*k
);