Fawkes API  Fawkes Development Version
multi_interface_chooser_dialog.cpp
1 /***************************************************************************
2  * multi_interface_chooser_dialog.cpp - Dialog for choosing a blackboard interface
3  *
4  * Created: Mon Oct 17 21:01:30 2011
5  * Copyright 2011 Christoph Schwering
6  *
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version. A runtime exception applies to
13  * this software (see LICENSE.GPL_WRE file mentioned below for details).
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
21  */
22 
23 #include <gui_utils/multi_interface_chooser_dialog.h>
24 
25 #include <gtkmm.h>
26 #include <core/exception.h>
27 #include <core/exceptions/software.h>
28 #include <blackboard/blackboard.h>
29 #include <interface/interface_info.h>
30 
31 #include <algorithm>
32 #include <cassert>
33 #include <cstring>
34 
35 namespace fawkes {
36 
37 /** @class MultiInterfaceChooserDialog::Record <gui_utils/multi_interface_chooser_dialog.h>
38  * Blackboard interface record.
39  * Adds a checkbox whether or not to load the specific interface.
40  * @author Christoph Schwering
41  */
42 
43 /** Constructor. */
45 {
46  add(load);
47 }
48 
49 /** @class MultiInterfaceChooserDialog <gui_utils/multi_interface_chooser_dialog.h>
50  * Blackboard interface chooser dialog that supports multiple choices.
51  * Allows to choose multiple blackboard interfaces from a list of interfaces
52  * matching given type and ID patterns.
53  * @author Christoph Schwering
54  */
55 
56 
57 /** Factory method.
58  *
59  * Why a factory method instead of a ctor?
60  * The factory method calls init(), and init() calls other virtual methods.
61  * If this was a ctor, this ctor would not be allowed to be called by
62  * subclasses, because then the virtual methods in init() don't dispatch the
63  * right way during construction (see Effective C++ #9).
64  *
65  * @param parent parent window
66  * @param blackboard blackboard instance to query interfaces from
67  * @param type_pattern pattern with shell like globs (* for any number of
68  * characters, ? for exactly one character) to match the interface type.
69  * @param id_pattern pattern with shell like globs (* for any number of
70  * characters, ? for exactly one character) to match the interface ID.
71  * @param loaded_interfaces list of interfaces which are already loaded
72  * @param title title of the dialog
73  * @return new MultiInterfaceChooserDialog
74  */
77  Gtk::Window& parent,
78  BlackBoard* blackboard,
79  const char* type_pattern,
80  const char* id_pattern,
81  const TypeIdPairList& loaded_interfaces,
82  const Glib::ustring& title)
83 {
85  parent, loaded_interfaces, title);
86  d->init(blackboard, type_pattern, id_pattern);
87  return d;
88 }
89 
90 
91 /** Constructor for subclasses.
92  *
93  * After calling this constructor, the init() method needs to be called.
94  *
95  * @param parent parent window
96  * @param loaded_interfaces list of interfaces which are already loaded
97  * @param title title of the dialog
98  */
100  Gtk::Window &parent,
101  const TypeIdPairList& loaded_interfaces,
102  const Glib::ustring& title)
103  : InterfaceChooserDialog(parent, title),
104  __record(NULL)
105 {
106  __loaded_interfaces.insert(loaded_interfaces.begin(), loaded_interfaces.end());
107  Glib::RefPtr<Gtk::TreeSelection> treesel = __treeview.get_selection();
108  __treeview.set_reorderable(true);
109  __treeview.set_tooltip_text("Drag the rows to change the painting order.");
110  treesel->set_mode(Gtk::SELECTION_NONE);
111  // May *NOT* call init(), because init() calls virtual methods.
112 }
113 
114 
115 /** Destructor. */
117 {
118  if (__record) {
119  delete __record;
120  }
121 }
122 
123 
124 void
125 MultiInterfaceChooserDialog::on_load_toggled(const Glib::ustring& path)
126 {
127  Gtk::TreeModel::Row row = *__model->get_iter(path);
128  row[record().load] = !row[record().load];
129 }
130 
131 
132 /** Returns the Record of this chooser dialog.
133  * Subclasses of InterfaceChooserDialog might want to override this method.
134  * @return Record implementation.
135  */
138 {
139  if (!__record) {
140  MultiInterfaceChooserDialog* this_nonconst = const_cast<MultiInterfaceChooserDialog*>(this);
141  this_nonconst->__record = new Record();
142  }
143  return *__record;
144 }
145 
146 
147 /** Initializes the columns GUI-wise.
148  * Called in the ctor.
149  * Subclasses of InterfaceChooserDialog might want to override this method,
150  * but should probably still call their super-class's implementation
151  * (i.e., this one).
152  * @return The number of columns added.
153  */
154 int
156 {
157  __treeview.append_column("Load", record().load);
158 
159  const int n = InterfaceChooserDialog::init_columns();
160 
161  Gtk::CellRendererToggle* renderer = dynamic_cast<Gtk::CellRendererToggle*>(
162  __treeview.get_column_cell_renderer(0));
163  assert(renderer != NULL);
164 
165  renderer->set_activatable(true);
166  renderer->signal_toggled().connect(
167  sigc::mem_fun(*this, &MultiInterfaceChooserDialog::on_load_toggled));
168 
169  return n + 2;
170 }
171 
172 
173 /** Initializes a row with the given interface.
174  * Called in the ctor.
175  * Subclasses of InterfaceChooserDialog might want to override this method,
176  * but should probably still call their super-class's implementation
177  * (i.e., this one).
178  * @param row The row whose content is to be set.
179  * @param ii The interface info that should populate the row.
180  */
181 void
182 MultiInterfaceChooserDialog::init_row(Gtk::TreeModel::Row& row,
183  const InterfaceInfo& ii)
184 {
186  row[record().load] = __loaded_interfaces.find(std::make_pair(ii.type(), ii.id())) !=
187  __loaded_interfaces.end();
188 }
189 
190 
191 /** Get selected interface types and their respective IDs.
192  * @return A list of type + id pairs of interfaces that are to be loaded.
193  */
196 {
197  TypeIdPairList types_and_ids;
198 
199  const Gtk::TreeNodeChildren children = __model->children();
200  for (Gtk::TreeNodeChildren::const_iterator it = children.begin();
201  it != children.end(); ++it)
202  {
203  const Gtk::TreeRow& row = *it;
204  if (row[record().load]) {
205  TypeIdPair pair = std::make_pair(row[record().type], row[record().id]);
206  types_and_ids.push_back(pair);
207  }
208  }
209 
210  return types_and_ids;
211 }
212 
213 
214 /** Get selected interface types and their respective IDs.
215  * @return A list of type + id pairs of interfaces that are to be loaded,
216  * and *NOT* contained in the list of loaded interfaces handed
217  * over to create().
218  */
221 {
222  TypeIdPairList types_and_ids;
223 
224  const Gtk::TreeNodeChildren children = __model->children();
225  for (Gtk::TreeNodeChildren::const_iterator it = children.begin();
226  it != children.end(); ++it)
227  {
228  const Gtk::TreeRow& row = *it;
229  if (row[record().load]) {
230  TypeIdPair pair = std::make_pair(row[record().type], row[record().id]);
231  if (__loaded_interfaces.find(pair) == __loaded_interfaces.end())
232  {
233  types_and_ids.push_back(pair);
234  }
235  }
236  }
237 
238  return types_and_ids;
239 }
240 
241 } // end of namespace fawkes
242 
const char * type() const
Get interface type.
Blackboard interface chooser dialog.
MultiInterfaceChooserDialog(Gtk::Window &parent, const TypeIdPairList &loaded_interfaces, const Glib::ustring &title)
Constructor for subclasses.
std::list< TypeIdPair > TypeIdPairList
List of type and ID of an interface.
Fawkes library namespace.
Gtk::TreeModelColumn< bool > load
Load this interface?
const char * id() const
Get interface ID.
void init(BlackBoard *blackboard, const char *type_pattern, const char *id_pattern)
Initialization method.
Glib::RefPtr< Gtk::ListStore > __model
Data model of the tree.
virtual int init_columns()
Initializes the columns GUI-wise.
Blackboard interface chooser dialog that supports multiple choices.
virtual int init_columns()
Initializes the columns GUI-wise.
TypeIdPairList get_newly_selected_interfaces() const
Get selected interface types and their respective IDs.
Gtk::TreeView __treeview
Tree widget for interfaces.
std::pair< Glib::ustring, Glib::ustring > TypeIdPair
Pair of type and IDs of interfaces.
virtual void init_row(Gtk::TreeModel::Row &row, const InterfaceInfo &ii)
Initializes a row with the given interface.
TypeIdPairList get_selected_interfaces() const
Get selected interface types and their respective IDs.
virtual void init_row(Gtk::TreeModel::Row &row, const InterfaceInfo &ii)
Initializes a row with the given interface.
virtual const Record & record() const
Returns the Record of this chooser dialog.
static MultiInterfaceChooserDialog * create(Gtk::Window &parent, BlackBoard *blackboard, const char *type_pattern, const char *id_pattern, const TypeIdPairList &loaded_interfaces, const Glib::ustring &title=DEFAULT_TITLE)
Factory method.
The BlackBoard abstract class.
Definition: blackboard.h:48
Interface info.