Provide a function to fill a Gtk::ComboBox with all available actions
[ardour.git] / libs / gtkmm2ext / action_model.cc
1 /*
2     Copyright (C) 2009-2013 Paul Davis
3     Author: Johannes Mueller
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <vector>
22
23 #include  <gtkmm/combobox.h>
24
25 #include "pbd/i18n.h"
26 #include "pbd/strsplit.h"
27
28 #include "gtkmm2ext/actions.h"
29 #include "gtkmm2ext/action_model.h"
30
31 using namespace std;
32 using namespace Gtk;
33
34 const ActionManager::ActionModel&
35 ActionManager::ActionModel::instance ()
36 {
37         static ActionManager::ActionModel am;
38         return am;
39 }
40
41 ActionManager::ActionModel::ActionModel ()
42 {
43         _model = TreeStore::create (_columns);
44         _model->clear ();
45
46         typedef std::map<string,TreeIter> NodeMap;
47         NodeMap nodes;
48         NodeMap::iterator r;
49
50         TreeIter rowp;
51         TreeModel::Row parent;
52
53         rowp = _model->append ();
54         parent = *(rowp);
55         parent[_columns.name] = _("Disabled");
56
57         vector<string> paths;
58         vector<string> labels;
59         vector<string> tooltips;
60         vector<string> keys;
61         vector<Glib::RefPtr<Gtk::Action> > actions;
62
63         ActionManager::get_all_actions (paths, labels, tooltips, keys, actions);
64
65         vector<string>::iterator k;
66         vector<string>::iterator p;
67         vector<string>::iterator t;
68         vector<string>::iterator l;
69
70         for (l = labels.begin(), k = keys.begin(), p = paths.begin(), t = tooltips.begin(); l != labels.end(); ++k, ++p, ++t, ++l) {
71
72                 TreeModel::Row row;
73                 vector<string> parts;
74                 parts.clear ();
75                 split (*p, parts, '/');
76
77                 if (parts.empty()) {
78                         continue;
79                 }
80
81                 //kinda kludgy way to avoid displaying menu items as mappable
82                 if ( parts[0] == _("Main_menu") )
83                         continue;
84                 if ( parts[0] == _("JACK") )
85                         continue;
86                 if ( parts[0] == _("redirectmenu") )
87                         continue;
88                 if ( parts[0] == _("Editor_menus") )
89                         continue;
90                 if ( parts[0] == _("RegionList") )
91                         continue;
92                 if ( parts[0] == _("ProcessorMenu") )
93                         continue;
94
95                 if ((r = nodes.find (parts[0])) == nodes.end()) {
96                         /* top level is missing */
97
98                         TreeIter rowp;
99                         TreeModel::Row parent;
100                         rowp = _model->append();
101                         nodes[parts[0]] = rowp;
102                         parent = *(rowp);
103                         parent[_columns.name] = parts[0];
104
105                         row = *(_model->append (parent.children()));
106                 } else {
107                         row = *(_model->append ((*r->second)->children()));
108                 }
109
110                 /* add this action */
111
112                 if (l->empty ()) {
113                         row[_columns.name] = *t;
114                 } else {
115                         row[_columns.name] = *l;
116                 }
117
118                 row[_columns.path] = *p;
119         }
120 }
121
122 bool
123 ActionManager::ActionModel::find_action_in_model (const TreeModel::iterator& iter, std::string const & action_path, TreeModel::iterator* found) const
124 {
125         TreeModel::Row row = *iter;
126         string path = row[_columns.path];
127
128         if (path == action_path) {
129                 *found = iter;
130                 return true;
131         }
132
133         return false;
134 }
135
136 void
137 ActionManager::ActionModel::build_action_combo (ComboBox& cb, string const& current_action) const
138 {
139         cb.set_model (_model);
140         cb.pack_start (_columns.name);
141
142         if (current_action.empty()) {
143                 cb.set_active (0); /* "disabled" */
144                 return;
145         }
146
147         TreeModel::iterator iter = _model->children().end();
148
149         _model->foreach_iter (sigc::bind (sigc::mem_fun (*this, &ActionManager::ActionModel::find_action_in_model), current_action, &iter));
150
151         if (iter != _model->children().end()) {
152                 cb.set_active (iter);
153         } else {
154                 cb.set_active (0);
155         }
156 }