From 29f0d9732eb68fcaa22219cedddddd47bcaa8c17 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 12 Oct 2007 01:54:35 +0000 Subject: [PATCH] add keybinding editor git-svn-id: svn://localhost/ardour2/trunk@2543 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/SConscript | 1 + gtk2_ardour/actions.cc | 33 +++--- gtk2_ardour/actions.h | 2 + gtk2_ardour/ardour.menus | 1 + gtk2_ardour/ardour2_ui_dark.rc.in | 2 +- gtk2_ardour/ardour2_ui_light.rc.in | 2 +- gtk2_ardour/ardour_ui.h | 6 ++ gtk2_ardour/ardour_ui2.cc | 4 +- gtk2_ardour/ardour_ui_dialogs.cc | 22 ++++ gtk2_ardour/ardour_ui_ed.cc | 4 +- gtk2_ardour/keyeditor.cc | 159 +++++++++++++++++++++++++++++ gtk2_ardour/keyeditor.h | 44 ++++++++ libs/pbd/strsplit.cc | 4 +- 13 files changed, 264 insertions(+), 20 deletions(-) create mode 100644 gtk2_ardour/keyeditor.cc create mode 100644 gtk2_ardour/keyeditor.h diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index 12e3225f89..61d653bed7 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -167,6 +167,7 @@ gtk-custom-hruler.c gtk-custom-ruler.c io_selector.cc keyboard.cc +keyeditor.cc ladspa_pluginui.cc latency_gui.cc location_ui.cc diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc index 5835292cf9..f7609d2712 100644 --- a/gtk2_ardour/actions.cc +++ b/gtk2_ardour/actions.cc @@ -153,19 +153,28 @@ ActionManager::lookup_entry (const ustring accel_path, Gtk::AccelKey& key) void ActionManager::get_all_actions (vector& names, vector& paths, vector& keys, vector& bindings) { - ListHandle > uim_groups = ui_manager->get_action_groups (); - - for (ListHandle >::iterator g = uim_groups.begin(); g != uim_groups.end(); ++g) { - - ListHandle > group_actions = (*g)->get_actions(); - - for (ListHandle >::iterator a = group_actions.begin(); a != group_actions.end(); ++a) { + /* the C++ API for functions used here appears to be broken in + gtkmm2.6, so we fall back to the C level. + */ + + GList* list = gtk_ui_manager_get_action_groups (ui_manager->gobj()); + GList* node; + GList* acts; + + for (node = list; node; node = g_list_next (node)) { + + GtkActionGroup* group = (GtkActionGroup*) node->data; + + for (acts = gtk_action_group_list_actions (group); acts; acts = g_list_next (acts)) { + + GtkAction* action = (GtkAction*) acts->data; + + Glib::RefPtr act = Glib::wrap (action, true); + + string accel_path = act->get_accel_path (); + ustring label = act->property_label(); - ustring accel_path; - - accel_path = (*a)->get_accel_path(); - - names.push_back ((*a)->get_name()); + names.push_back (label); paths.push_back (accel_path); AccelKey key; diff --git a/gtk2_ardour/actions.h b/gtk2_ardour/actions.h index 5816325265..bdad026110 100644 --- a/gtk2_ardour/actions.h +++ b/gtk2_ardour/actions.h @@ -27,6 +27,8 @@ #include #include +#include + namespace Gtk { class UIManager; } diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index 128ca81c27..4c8c3d6df9 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -233,6 +233,7 @@ + diff --git a/gtk2_ardour/ardour2_ui_dark.rc.in b/gtk2_ardour/ardour2_ui_dark.rc.in index ba8e5fe1e1..4ee90ddd30 100644 --- a/gtk2_ardour/ardour2_ui_dark.rc.in +++ b/gtk2_ardour/ardour2_ui_dark.rc.in @@ -91,7 +91,7 @@ style "default_base" = "medium_text" GtkTreeView::vertical-padding = 0 GtkTreeView::horizontal-padding = 0 GtkTreeView::even-row-color = { 0, 0, 0 } - GtkTreeView::odd-row-color = { 0, 0, 0 } + GtkTreeView::odd-row-color = { 0.06, 0.06, 0.10 } fg[NORMAL] = { 0.80, 0.80, 0.80 } fg[ACTIVE] = { 0.80, 0.80, 0.80 } diff --git a/gtk2_ardour/ardour2_ui_light.rc.in b/gtk2_ardour/ardour2_ui_light.rc.in index b8c3683e91..b485ae14ce 100644 --- a/gtk2_ardour/ardour2_ui_light.rc.in +++ b/gtk2_ardour/ardour2_ui_light.rc.in @@ -91,7 +91,7 @@ style "default_base" = "medium_text" GtkTreeView::vertical-padding = 0 GtkTreeView::horizontal-padding = 0 GtkTreeView::even-row-color = { 0.70, 0.70, 0.70 } - GtkTreeView::odd-row-color = { 0.70, 0.70, 0.70 } + GtkTreeView::odd-row-color = { 0.64, 0.64, 0.64 } fg[NORMAL] = { 0.30, 0.30, 0.40 } fg[ACTIVE] = { 0.30, 0.30, 0.40 } diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 427d40dffe..9061f789a1 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -69,6 +69,7 @@ class AudioClock; class PublicEditor; class Keyboard; class OptionEditor; +class KeyEditor; class Mixer_UI; class ConnectionEditor; class RouteParams_UI; @@ -154,6 +155,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI PublicEditor& the_editor(){return *editor;} Mixer_UI* the_mixer() { return mixer; } + void toggle_key_editor (); void toggle_location_window (); void toggle_theme_manager (); void toggle_big_clock_window (); @@ -620,6 +622,10 @@ class ARDOUR_UI : public Gtkmm2ext::UI static UIConfiguration *ui_config; ThemeManager *theme_manager; + /* Key bindings editor */ + + KeyEditor *key_editor; + /* Options window */ OptionEditor *option_editor; diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc index 8f755a3d93..fcb721a9f0 100644 --- a/gtk2_ardour/ardour_ui2.cc +++ b/gtk2_ardour/ardour_ui2.cc @@ -78,8 +78,6 @@ ARDOUR_UI::setup_windows () theme_manager->signal_unmap().connect (bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("/Common/ToggleThemeManager"))); - top_packer.pack_start (transport_frame, false, false); - #ifdef TOP_MENUBAR HBox* status_bar_packer = manage (new HBox); @@ -95,6 +93,8 @@ ARDOUR_UI::setup_windows () top_packer.pack_start (menu_bar_base, false, false); #endif + top_packer.pack_start (transport_frame, false, false); + editor->add_toplevel_controls (top_packer); return 0; diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 9a71443489..89ab470d9b 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -35,6 +35,7 @@ #include "route_params_ui.h" #include "sfdb_ui.h" #include "theme_manager.h" +#include "keyeditor.h" #include "i18n.h" @@ -325,6 +326,27 @@ ARDOUR_UI::toggle_location_window () } } +void +ARDOUR_UI::toggle_key_editor () +{ + if (key_editor == 0) { + key_editor = new KeyEditor; + key_editor->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("/Common/ToggleKeyEditor"))); + } + + RefPtr act = ActionManager::get_action (X_("Common"), X_("ToggleKeyEditor")); + if (act) { + RefPtr tact = RefPtr::cast_dynamic(act); + + if (tact->get_active()) { + key_editor->show_all (); + key_editor->present (); + } else { + key_editor->hide (); + } + } +} + void ARDOUR_UI::toggle_theme_manager () { diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index c850d72048..8ba5e3790a 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -204,8 +204,6 @@ ARDOUR_UI::install_actions () ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_toggle_action (common_actions, X_("ToggleBigClock"), _("Big Clock"), mem_fun(*this, &ARDOUR_UI::toggle_big_clock_window)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), mem_fun(*this, &ARDOUR_UI::toggle_theme_manager)); - ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal, 1)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (common_actions, X_("AddAudioBus"), _("Add Audio Bus"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_bus), 1, 1, 1)); @@ -220,6 +218,8 @@ ARDOUR_UI::install_actions () ActionManager::session_sensitive_actions.push_back (act); ActionManager::register_action (common_actions, X_("About"), _("About"), mem_fun(*this, &ARDOUR_UI::show_splash)); + ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), mem_fun(*this, &ARDOUR_UI::toggle_theme_manager)); + ActionManager::register_toggle_action (common_actions, X_("ToggleKeyEditor"), _("Keybindings"), mem_fun(*this, &ARDOUR_UI::toggle_key_editor)); Glib::RefPtr transport_actions = ActionGroup::create (X_("Transport")); diff --git a/gtk2_ardour/keyeditor.cc b/gtk2_ardour/keyeditor.cc new file mode 100644 index 0000000000..07aad652af --- /dev/null +++ b/gtk2_ardour/keyeditor.cc @@ -0,0 +1,159 @@ +#include + +#include +#include +#include +#include + +#include + +#include "actions.h" +#include "keyboard.h" +#include "keyeditor.h" + +#include "i18n.h" + +using namespace std; +using namespace Gtk; +using namespace Gdk; + +KeyEditor::KeyEditor () + : ArdourDialog (_("Keybinding Editor"), false) +{ + model = TreeStore::create(columns); + + view.set_model (model); + view.append_column (_("Action"), columns.action); + view.append_column (_("Binding"), columns.binding); + view.set_headers_visible (true); + view.get_selection()->set_mode (SELECTION_SINGLE); + view.set_reorderable (false); + view.set_size_request (300,200); + view.set_enable_search (false); + view.set_rules_hint (true); + view.set_name (X_("KeyEditorTree")); + + view.get_selection()->signal_changed().connect (mem_fun (*this, &KeyEditor::action_selected)); + + scroller.add (view); + scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + get_vbox()->pack_start (scroller); + + scroller.show (); + view.show (); +} + +void +KeyEditor::on_show () +{ + populate (); + view.get_selection()->unselect_all (); + ArdourDialog::on_show (); +} + +void +KeyEditor::on_unmap () +{ + ArdourDialog::on_unmap (); +} + +void +KeyEditor::action_selected () +{ +} + +bool +KeyEditor::on_key_release_event (GdkEventKey* ev) +{ + TreeModel::iterator i = view.get_selection()->get_selected(); + + if (i != model->children().end()) { + string path = (*i)[columns.path]; + + bool result = AccelMap::change_entry (path, + ev->keyval, + (ModifierType) ev->state, + true); + + if (result) { + bool known; + AccelKey key; + + known = ActionManager::lookup_entry (path, key); + + if (known) { + (*i)[columns.binding] = ActionManager::ui_manager->get_accel_group()->name (key.get_key(), Gdk::ModifierType (key.get_mod())); + } else { + (*i)[columns.binding] = string(); + } + } + + + } + + return true; +} + +void +KeyEditor::populate () +{ + vector paths; + vector labels; + vector keys; + vector bindings; + typedef std::map NodeMap; + NodeMap nodes; + NodeMap::iterator r; + + ActionManager::get_all_actions (labels, paths, keys, bindings); + + vector::iterator k; + vector::iterator p; + vector::iterator l; + + model->clear (); + + for (l = labels.begin(), k = keys.begin(), p = paths.begin(); l != labels.end(); ++k, ++p, ++l) { + + TreeModel::Row row; + vector parts; + + parts.clear (); + + split (*p, parts, '/'); + + if (parts.empty()) { + continue; + } + + if ((r = nodes.find (parts[1])) == nodes.end()) { + + /* top level is missing */ + + TreeIter rowp; + TreeModel::Row parent; + rowp = model->append(); + nodes[parts[1]] = rowp; + parent = *(rowp); + parent[columns.action] = parts[1]; + + row = *(model->append (parent.children())); + + } else { + + row = *(model->append ((*r->second)->children())); + + } + + /* add this action */ + + row[columns.action] = (*l); + row[columns.path] = (*p); + + if (*k == ActionManager::unbound_string) { + row[columns.binding] = string(); + } else { + row[columns.binding] = (*k); + } + } +} diff --git a/gtk2_ardour/keyeditor.h b/gtk2_ardour/keyeditor.h new file mode 100644 index 0000000000..b200adabf4 --- /dev/null +++ b/gtk2_ardour/keyeditor.h @@ -0,0 +1,44 @@ +#ifndef __ardour_gtk_key_editor_h__ +#define __ardour_gtk_key_editor_h__ + +#include + +#include +#include +#include +#include + +#include "ardour_dialog.h" + +class KeyEditor : public ArdourDialog +{ + public: + KeyEditor (); + + protected: + void on_show (); + void on_unmap (); + bool on_key_release_event (GdkEventKey*); + + private: + struct KeyEditorColumns : public Gtk::TreeModel::ColumnRecord { + KeyEditorColumns () { + add (action); + add (binding); + add (path); + } + Gtk::TreeModelColumn action; + Gtk::TreeModelColumn binding; + Gtk::TreeModelColumn path; + }; + + Gtk::ScrolledWindow scroller; + Gtk::TreeView view; + Glib::RefPtr model; + KeyEditorColumns columns; + + void action_selected (); + void populate (); +}; + +#endif /* __ardour_gtk_key_editor_h__ */ diff --git a/libs/pbd/strsplit.cc b/libs/pbd/strsplit.cc index b7a7109af4..342daadaa2 100644 --- a/libs/pbd/strsplit.cc +++ b/libs/pbd/strsplit.cc @@ -49,7 +49,7 @@ split (string str, vector& result, char splitchar) remaining = str; - while ((pos = remaining.find_first_of (':')) != string::npos) { + while ((pos = remaining.find_first_of (splitchar)) != string::npos) { result.push_back (remaining.substr (0, pos)); remaining = remaining.substr (pos+1); } @@ -87,7 +87,7 @@ split (ustring str, vector& result, char splitchar) remaining = str; - while ((pos = remaining.find_first_of (':')) != ustring::npos) { + while ((pos = remaining.find_first_of (splitchar)) != ustring::npos) { result.push_back (remaining.substr (0, pos)); remaining = remaining.substr (pos+1); }