Fix DSP load sorting with inactive plugins
[ardour.git] / gtk2_ardour / stripable_treemodel.cc
1 /*
2  * Copyright (C) 2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2017 Robin Gareus <robin@gareus.org>
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 along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 #include <iostream>
21
22 #include "ardour/session.h"
23 #include "ardour/types.h"
24
25 #include "axis_provider.h"
26 #include "stripable_treemodel.h"
27
28 using namespace ARDOUR;
29
30 StripableTreeModel::Glue::Glue (boost::shared_ptr<Stripable> s)
31         : stripable (s)
32 {
33 }
34
35 StripableTreeModel::StripableTreeModel (AxisViewProvider& avp)
36         : Glib::ObjectBase( typeid(StripableTreeModel) ) //register a custom GType.
37         , Glib::Object() //The custom GType is actually registered here.
38         , axis_view_provider (avp)
39 {
40         n_columns = columns.size();
41 }
42
43 void
44 StripableTreeModel::set_session (Session& s)
45 {
46         _session = &s;
47 }
48
49 StripableTreeModel::~StripableTreeModel()
50 {
51 }
52
53 Glib::RefPtr<StripableTreeModel>
54 StripableTreeModel::create (AxisViewProvider& avp)
55 {
56         return Glib::RefPtr<StripableTreeModel> (new StripableTreeModel (avp));
57 }
58
59 Gtk::TreeModelFlags
60 StripableTreeModel::get_flags_vfunc() const
61 {
62         return Gtk::TREE_MODEL_LIST_ONLY;
63 }
64
65 int
66 StripableTreeModel::get_n_columns_vfunc() const
67 {
68         return n_columns;
69 }
70
71 GType
72 StripableTreeModel::get_column_type_vfunc (int index) const
73 {
74         if (index <= n_columns) {
75                 return columns.types()[index];
76         }
77         return 0;
78 }
79
80 void
81 StripableTreeModel::get_value_vfunc (const TreeModel::iterator& iter, int column, Glib::ValueBase& value) const
82 {
83         if (!_session) {
84                 return;
85         }
86
87         if (column > n_columns) {
88                 return;
89         }
90
91         const Glue* glue = (const Glue*)iter.gobj()->user_data;
92         boost::shared_ptr<Stripable> iter_stripable = glue->stripable.lock();
93
94         if (!iter_stripable) {
95                 return;
96         }
97
98         switch (column) {
99         case 0:
100                 return text_value (iter_stripable, value);
101         }
102 }
103
104 void
105 StripableTreeModel::text_value (boost::shared_ptr<Stripable> stripable, Glib::ValueBase& value) const
106 {
107         StringColumn::ValueType val;
108         val.set (stripable->name());
109         value = val;
110 }
111
112 bool
113 StripableTreeModel::iter_next_vfunc (const iterator& iter, iterator& iter_next) const
114 {
115         if (!_session) {
116                 return false;
117         }
118
119         const Glue* glue = (const Glue*)iter.gobj()->user_data;
120         boost::shared_ptr<Stripable> iter_stripable = glue->stripable.lock();
121
122         if (!iter_stripable) {
123                 return false;
124         }
125
126         //initialize the next iterator:
127         iter_next = iterator();
128
129         StripableList sl;
130         _session->get_stripables (sl);
131         if (sl.empty()) {
132                 return false;
133         }
134         sl.sort (Stripable::Sorter());
135
136         for (StripableList::const_iterator s = sl.begin(); s != sl.end(); ++s) {
137
138                 if (*s == iter_stripable) {
139                         ++s;
140                         if (s != sl.end()) {
141                                 Glue* new_glue = new Glue (iter_stripable);
142                                 iter_next.gobj()->user_data = (void*)new_glue;
143                                 remember_glue_item (new_glue);
144                                 return true; //success
145                         }
146                         break;
147                 }
148         }
149
150         return false; //There is no next row.
151 }
152
153 bool
154 StripableTreeModel::iter_children_vfunc(const iterator& parent, iterator& iter) const
155 {
156         return false;
157 }
158
159 bool
160 StripableTreeModel::iter_has_child_vfunc(const iterator& iter) const
161 {
162         return false;
163 }
164
165 int
166 StripableTreeModel::iter_n_children_vfunc(const iterator& iter) const
167 {
168         return 0;
169 }
170
171 int
172 StripableTreeModel::iter_n_root_children_vfunc() const
173 {
174         if (_session) {
175                 StripableList sl;
176                 _session->get_stripables (sl);
177                 return sl.size();
178         }
179         return 0;
180 }
181
182 bool
183 StripableTreeModel::iter_nth_child_vfunc(const iterator& parent, int /* n */, iterator& iter) const
184 {
185         iter = iterator(); //Set is as invalid, as the TreeModel documentation says that it should be.
186         return false; //There are no children.
187 }
188
189 bool
190 StripableTreeModel::iter_nth_root_child_vfunc(int n, iterator& iter) const
191 {
192         iter = iterator(); //clear the input parameter.
193         if (!_session) {
194                 return false;
195         }
196
197         StripableList sl;
198         _session->get_stripables (sl);
199
200         if (sl.empty()) {
201                 return false;
202         }
203
204         sl.sort (Stripable::Sorter());
205
206         StripableList::const_iterator s;
207
208         for (s = sl.begin(); s != sl.end() && n > 0; ++s, --n);
209
210         if (s != sl.end()) {
211                 Glue* new_glue = new Glue (*s);
212                 iter.gobj()->user_data = new_glue;
213                 remember_glue_item (new_glue);
214                 return true;
215         }
216
217         return false; //There are no children.
218 }
219
220 bool
221 StripableTreeModel::iter_parent_vfunc(const iterator& child, iterator& iter) const
222 {
223         iter = iterator(); //Set is as invalid, as the TreeModel documentation says that it should be.
224         return false; //There are no children, so no parents.
225 }
226
227 Gtk::TreeModel::Path
228 StripableTreeModel::get_path_vfunc(const iterator& /* iter */) const
229 {
230         //TODO:
231         return Path();
232 }
233
234 bool
235 StripableTreeModel::get_iter_vfunc (const Path& path, iterator& iter) const
236 {
237         unsigned sz = path.size();
238
239         if (!sz || sz > 1) {
240                 /* path must refer to something, but not children since we
241                    don't do children.
242                 */
243                 iter = iterator(); //Set is as invalid, as the TreeModel documentation says that it should be.
244                 return false;
245         }
246
247         return iter_nth_root_child_vfunc (path[0], iter);
248 }
249
250 bool
251 StripableTreeModel::iter_is_valid(const iterator& iter) const
252 {
253         const Glue* glue = (const Glue*)iter.gobj()->user_data;
254
255         if (!glue->stripable.lock()) {
256                 return false;
257         }
258
259         return Gtk::TreeModel::iter_is_valid(iter);
260 }
261
262 void
263 StripableTreeModel::remember_glue_item (Glue* item) const
264 {
265         glue_list.insert (item);
266 }