add keybinding editor
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 12 Oct 2007 01:54:35 +0000 (01:54 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 12 Oct 2007 01:54:35 +0000 (01:54 +0000)
git-svn-id: svn://localhost/ardour2/trunk@2543 d708f5d6-7413-0410-9779-e7cbd77b26cf

13 files changed:
gtk2_ardour/SConscript
gtk2_ardour/actions.cc
gtk2_ardour/actions.h
gtk2_ardour/ardour.menus
gtk2_ardour/ardour2_ui_dark.rc.in
gtk2_ardour/ardour2_ui_light.rc.in
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui2.cc
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/keyeditor.cc [new file with mode: 0644]
gtk2_ardour/keyeditor.h [new file with mode: 0644]
libs/pbd/strsplit.cc

index 12e3225f895b2758a550df337461e56945a0c2d6..61d653bed7796936bd164766247b8add154d4dff 100644 (file)
@@ -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
index 5835292cf9bfd4af96c31483ff5fd981635c5316..f7609d2712465cb79208562f4c23ddbbbb4b9ad8 100644 (file)
@@ -153,19 +153,28 @@ ActionManager::lookup_entry (const ustring accel_path, Gtk::AccelKey& key)
 void
 ActionManager::get_all_actions (vector<string>& names, vector<string>& paths, vector<string>& keys, vector<AccelKey>& bindings)
 {
-       ListHandle<RefPtr<ActionGroup> > uim_groups = ui_manager->get_action_groups ();
-       
-       for (ListHandle<RefPtr<ActionGroup> >::iterator g = uim_groups.begin(); g != uim_groups.end(); ++g) {
-               
-               ListHandle<RefPtr<Action> > group_actions = (*g)->get_actions();
-               
-               for (ListHandle<RefPtr<Action> >::iterator a = group_actions.begin(); a != group_actions.end(); ++a) {
-                       
-                       ustring accel_path;
-                       
-                       accel_path = (*a)->get_accel_path();
+       /* 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<Action> act = Glib::wrap (action, true);
+
+                       string accel_path = act->get_accel_path ();
+                       ustring label = act->property_label();
                        
-                       names.push_back ((*a)->get_name());
+                       names.push_back (label);
                        paths.push_back (accel_path);
                        
                        AccelKey key;
index 5816325265465c0c28c8c5ca99ccff7625acc793..bdad02611002738e4e1cdaf91511d43963e3acf1 100644 (file)
@@ -27,6 +27,8 @@
 #include <gtkmm/actiongroup.h>
 #include <gtkmm/accelkey.h>
 
+#include <ardour/configuration.h>
+
 namespace Gtk {
        class UIManager;
 }
index 128ca81c278151d31afbfa422861950e888903d5..4c8c3d6df99f3001bf7797e435119b069aa8a6a1 100644 (file)
                <menuitem action='ToggleOptionsEditor'/>
                <menuitem action='ToggleInspector'/>
                <menuitem action='ToggleLocations'/>
+               <menuitem action='ToggleKeyEditor'/>
                <menuitem action='ToggleThemeManager'/>
                <menuitem action='ToggleBigClock'/>
               <separator/>
index ba8e5fe1e1183970f5201d1179c8cd9313b53827..4ee90ddd309d07706a43d6a3d63d63532dee863c 100644 (file)
@@ -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 }    
index b8c3683e91ba8d0c9fd1590a852ad1912e97c48d..b485ae14ce22a63b1e91e4157165fb2a71b02680 100644 (file)
@@ -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 }    
index 427d40dffe3f1197daf538e0da141e2ade69a61d..9061f789a13a5c74501e3479e8c995a2a75ef356 100644 (file)
@@ -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;
index 8f755a3d93b9b8530df33d53c6c47417730a298d..fcb721a9f05027262eb8ff9b7b2cd7627fc00dcf 100644 (file)
@@ -78,8 +78,6 @@ ARDOUR_UI::setup_windows ()
 
        theme_manager->signal_unmap().connect (bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/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;
index 9a71443489685a1befe1083c48c6cb69f8323a83..89ab470d9b9aba9e33657d38364af504f0f53d4f 100644 (file)
@@ -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_("<Actions>/Common/ToggleKeyEditor")));  
+       }
+
+       RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleKeyEditor"));
+       if (act) {
+               RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
+       
+               if (tact->get_active()) {
+                       key_editor->show_all ();
+                       key_editor->present ();
+               } else {
+                       key_editor->hide ();
+               } 
+       }
+}
+
 void
 ARDOUR_UI::toggle_theme_manager ()
 {
index c850d72048803a2d9b22d339fa0728a5e46732fc..8ba5e3790ac996d554ec8413527280f16dd409ff 100644 (file)
@@ -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<ActionGroup> transport_actions = ActionGroup::create (X_("Transport"));
 
diff --git a/gtk2_ardour/keyeditor.cc b/gtk2_ardour/keyeditor.cc
new file mode 100644 (file)
index 0000000..07aad65
--- /dev/null
@@ -0,0 +1,159 @@
+#include <map>
+
+#include <gtkmm/stock.h>
+#include <gtkmm/accelkey.h>
+#include <gtkmm/accelmap.h>
+#include <gtkmm/uimanager.h>
+
+#include <pbd/strsplit.h>
+
+#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<string> paths;
+       vector<string> labels;
+       vector<string> keys;
+       vector<AccelKey> bindings;
+       typedef std::map<string,TreeIter> NodeMap;
+       NodeMap nodes;
+       NodeMap::iterator r;
+       
+       ActionManager::get_all_actions (labels, paths, keys, bindings);
+       
+       vector<string>::iterator k;
+       vector<string>::iterator p;
+       vector<string>::iterator l;
+
+       model->clear ();
+
+       for (l = labels.begin(), k = keys.begin(), p = paths.begin(); l != labels.end(); ++k, ++p, ++l) {
+               
+               TreeModel::Row row;
+               vector<string> 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 (file)
index 0000000..b200ada
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __ardour_gtk_key_editor_h__
+#define __ardour_gtk_key_editor_h__
+
+#include <string>
+
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/scrolledwindow.h>
+#include <glibmm/ustring.h>
+
+#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<Glib::ustring> action;
+           Gtk::TreeModelColumn<std::string> binding;
+           Gtk::TreeModelColumn<std::string> path;
+       };
+
+       Gtk::ScrolledWindow scroller;
+       Gtk::TreeView view;
+       Glib::RefPtr<Gtk::TreeStore> model;
+       KeyEditorColumns columns;
+
+       void action_selected ();
+       void populate ();
+};
+
+#endif /* __ardour_gtk_key_editor_h__ */
index b7a7109af4159fe64f3b2f8411972c41b6001a28..342daadaa222f67906504f5acc1c30d77dae79b3 100644 (file)
@@ -49,7 +49,7 @@ split (string str, vector<string>& 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<ustring>& 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);
        }