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 "gtkmm2ext/utils.h"
13 #include "pbd/strsplit.h"
14 #include "pbd/replace_all.h"
16 #include "ardour/profile.h"
20 #include "keyeditor.h"
30 using Gtkmm2ext::Keyboard
;
32 KeyEditor::KeyEditor ()
33 : ArdourDialog (_("Key Bindings"), false)
34 , unbind_button (_("Remove shortcut"))
35 , unbind_box (BUTTONBOX_END
)
41 model
= TreeStore::create(columns
);
43 view
.set_model (model
);
44 view
.append_column (_("Action"), columns
.action
);
45 view
.append_column (_("Shortcut"), columns
.binding
);
46 view
.set_headers_visible (true);
47 view
.get_selection()->set_mode (SELECTION_SINGLE
);
48 view
.set_reorderable (false);
49 view
.set_size_request (500,300);
50 view
.set_enable_search (false);
51 view
.set_rules_hint (true);
52 view
.set_name (X_("KeyEditorTree"));
54 view
.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &KeyEditor::action_selected
));
57 scroller
.set_policy (Gtk::POLICY_NEVER
, Gtk::POLICY_AUTOMATIC
);
60 get_vbox()->set_spacing (6);
61 get_vbox()->pack_start (scroller
);
63 if (!ARDOUR::Profile
->get_sae()) {
65 Label
* hint
= manage (new Label (_("Select an action, then press the key(s) to (re)set its shortcut")));
67 unbind_box
.set_spacing (6);
68 unbind_box
.pack_start (*hint
, false, true);
69 unbind_box
.pack_start (unbind_button
, false, false);
70 unbind_button
.signal_clicked().connect (sigc::mem_fun (*this, &KeyEditor::unbind
));
72 get_vbox()->pack_start (unbind_box
, false, false);
74 unbind_button
.show ();
78 get_vbox()->set_border_width (12);
83 unbind_button
.set_sensitive (false);
89 TreeModel::iterator i
= view
.get_selection()->get_selected();
91 unbind_button
.set_sensitive (false);
93 cerr
<< "trying to unbind\n";
95 if (i
!= model
->children().end()) {
96 string path
= (*i
)[columns
.path
];
98 if (!(*i
)[columns
.bindable
]) {
102 bool result
= AccelMap::change_entry (path
,
107 (*i
)[columns
.binding
] = string ();
113 KeyEditor::on_show ()
116 view
.get_selection()->unselect_all ();
117 ArdourDialog::on_show ();
121 KeyEditor::on_unmap ()
123 ArdourDialog::on_unmap ();
127 KeyEditor::action_selected ()
129 if (view
.get_selection()->count_selected_rows() == 0) {
133 TreeModel::iterator i
= view
.get_selection()->get_selected();
135 unbind_button
.set_sensitive (false);
137 if (i
!= model
->children().end()) {
139 string path
= (*i
)[columns
.path
];
141 if (!(*i
)[columns
.bindable
]) {
145 string binding
= (*i
)[columns
.binding
];
147 if (!binding
.empty()) {
148 unbind_button
.set_sensitive (true);
154 KeyEditor::on_key_press_event (GdkEventKey
* ev
)
157 last_state
= ev
->state
;
162 KeyEditor::on_key_release_event (GdkEventKey
* ev
)
164 if (ARDOUR::Profile
->get_sae() || !can_bind
|| ev
->state
!= last_state
) {
168 TreeModel::iterator i
= view
.get_selection()->get_selected();
170 if (i
!= model
->children().end()) {
171 string path
= (*i
)[columns
.path
];
173 if (!(*i
)[columns
.bindable
]) {
177 cerr
<< "real lkeyval: " << ev
->keyval
<< endl
;
178 Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (ev
->keyval
);
179 cerr
<< "using keyval = " << ev
->keyval
<< endl
;
182 bool result
= AccelMap::change_entry (path
,
184 ModifierType (Keyboard::RelevantModifierKeyMask
& ev
->state
),
187 cerr
<< "New binding to " << ev
->keyval
<< " worked: " << result
<< endl
;
191 (*i
)[columns
.binding
] = ActionManager::get_key_representation (path
, key
);
201 KeyEditor::populate ()
203 vector
<string
> paths
;
204 vector
<string
> labels
;
206 vector
<AccelKey
> bindings
;
207 typedef std::map
<string
,TreeIter
> NodeMap
;
211 ActionManager::get_all_actions (labels
, paths
, keys
, bindings
);
213 vector
<string
>::iterator k
;
214 vector
<string
>::iterator p
;
215 vector
<string
>::iterator l
;
219 for (l
= labels
.begin(), k
= keys
.begin(), p
= paths
.begin(); l
!= labels
.end(); ++k
, ++p
, ++l
) {
222 vector
<string
> parts
;
226 split (*p
, parts
, '/');
232 if ((r
= nodes
.find (parts
[1])) == nodes
.end()) {
234 /* top level is missing */
237 TreeModel::Row parent
;
238 rowp
= model
->append();
239 nodes
[parts
[1]] = rowp
;
241 parent
[columns
.action
] = parts
[1];
242 parent
[columns
.bindable
] = false;
244 row
= *(model
->append (parent
.children()));
248 row
= *(model
->append ((*r
->second
)->children()));
252 /* add this action */
254 row
[columns
.action
] = (*l
);
255 row
[columns
.path
] = (*p
);
256 row
[columns
.bindable
] = true;
258 if (*k
== ActionManager::unbound_string
) {
259 row
[columns
.binding
] = string();
266 NSAlternate/NSOption key to Mod1
267 NSCommand key to Meta
270 replace_all (label
, "<Meta>", _("Command-"));
271 replace_all (label
, "<Alt>", _("Option-"));
272 replace_all (label
, "<Shift>", _("Shift-"));
273 replace_all (label
, "<Control>", _("Control-"));
274 row
[columns
.binding
] = label
;
276 row
[columns
.binding
] = (*k
);