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
Glue(boost::shared_ptr<Stripable> s)30 StripableTreeModel::Glue::Glue (boost::shared_ptr<Stripable> s)
31 : stripable (s)
32 {
33 }
34
StripableTreeModel(AxisViewProvider & avp)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
set_session(Session & s)44 StripableTreeModel::set_session (Session& s)
45 {
46 _session = &s;
47 }
48
~StripableTreeModel()49 StripableTreeModel::~StripableTreeModel()
50 {
51 }
52
53 Glib::RefPtr<StripableTreeModel>
create(AxisViewProvider & avp)54 StripableTreeModel::create (AxisViewProvider& avp)
55 {
56 return Glib::RefPtr<StripableTreeModel> (new StripableTreeModel (avp));
57 }
58
59 Gtk::TreeModelFlags
get_flags_vfunc() const60 StripableTreeModel::get_flags_vfunc() const
61 {
62 return Gtk::TREE_MODEL_LIST_ONLY;
63 }
64
65 int
get_n_columns_vfunc() const66 StripableTreeModel::get_n_columns_vfunc() const
67 {
68 return n_columns;
69 }
70
71 GType
get_column_type_vfunc(int index) const72 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
get_value_vfunc(const TreeModel::iterator & iter,int column,Glib::ValueBase & value) const81 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
text_value(boost::shared_ptr<Stripable> stripable,Glib::ValueBase & value) const105 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
iter_next_vfunc(const iterator & iter,iterator & iter_next) const113 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
iter_children_vfunc(const iterator & parent,iterator & iter) const154 StripableTreeModel::iter_children_vfunc(const iterator& parent, iterator& iter) const
155 {
156 return false;
157 }
158
159 bool
iter_has_child_vfunc(const iterator & iter) const160 StripableTreeModel::iter_has_child_vfunc(const iterator& iter) const
161 {
162 return false;
163 }
164
165 int
iter_n_children_vfunc(const iterator & iter) const166 StripableTreeModel::iter_n_children_vfunc(const iterator& iter) const
167 {
168 return 0;
169 }
170
171 int
iter_n_root_children_vfunc() const172 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
iter_nth_child_vfunc(const iterator & parent,int,iterator & iter) const183 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
iter_nth_root_child_vfunc(int n,iterator & iter) const190 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
iter_parent_vfunc(const iterator & child,iterator & iter) const221 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
get_path_vfunc(const iterator &) const228 StripableTreeModel::get_path_vfunc(const iterator& /* iter */) const
229 {
230 //TODO:
231 return Path();
232 }
233
234 bool
get_iter_vfunc(const Path & path,iterator & iter) const235 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
iter_is_valid(const iterator & iter) const251 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
remember_glue_item(Glue * item) const263 StripableTreeModel::remember_glue_item (Glue* item) const
264 {
265 glue_list.insert (item);
266 }
267