Fawkes API
Fawkes Development Version
|
00001 /*************************************************************************** 00002 * multi_interface_chooser_dialog.cpp - Dialog for choosing a blackboard interface 00003 * 00004 * Created: Mon Oct 17 21:01:30 2011 00005 * Copyright 2011 Christoph Schwering 00006 * 00007 ****************************************************************************/ 00008 00009 /* This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. A runtime exception applies to 00013 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00021 */ 00022 00023 #include <gui_utils/multi_interface_chooser_dialog.h> 00024 00025 #include <gtkmm.h> 00026 #include <core/exception.h> 00027 #include <core/exceptions/software.h> 00028 #include <blackboard/blackboard.h> 00029 #include <interface/interface_info.h> 00030 00031 #include <algorithm> 00032 #include <cassert> 00033 #include <cstring> 00034 00035 namespace fawkes { 00036 00037 /** @class MultiInterfaceChooserDialog::Record <gui_utils/multi_interface_chooser_dialog.h> 00038 * Blackboard interface record. 00039 * Adds a checkbox whether or not to load the specific interface. 00040 * @author Christoph Schwering 00041 */ 00042 00043 /** Constructor. */ 00044 MultiInterfaceChooserDialog::Record::Record() 00045 { 00046 add(load); 00047 } 00048 00049 /** @class MultiInterfaceChooserDialog <gui_utils/multi_interface_chooser_dialog.h> 00050 * Blackboard interface chooser dialog that supports multiple choices. 00051 * Allows to choose multiple blackboard interfaces from a list of interfaces 00052 * matching given type and ID patterns. 00053 * @author Christoph Schwering 00054 */ 00055 00056 00057 /** Factory method. 00058 * 00059 * Why a factory method instead of a ctor? 00060 * The factory method calls init(), and init() calls other virtual methods. 00061 * If this was a ctor, this ctor would not be allowed to be called by 00062 * subclasses, because then the virtual methods in init() don't dispatch the 00063 * right way during construction (see Effective C++ #9). 00064 * 00065 * @param parent parent window 00066 * @param blackboard blackboard instance to query interfaces from 00067 * @param type_pattern pattern with shell like globs (* for any number of 00068 * characters, ? for exactly one character) to match the interface type. 00069 * @param id_pattern pattern with shell like globs (* for any number of 00070 * characters, ? for exactly one character) to match the interface ID. 00071 * @param loaded_interfaces list of interfaces which are already loaded 00072 * @param title title of the dialog 00073 * @return new MultiInterfaceChooserDialog 00074 */ 00075 MultiInterfaceChooserDialog* 00076 MultiInterfaceChooserDialog::create( 00077 Gtk::Window& parent, 00078 BlackBoard* blackboard, 00079 const char* type_pattern, 00080 const char* id_pattern, 00081 const TypeIdPairList& loaded_interfaces, 00082 const Glib::ustring& title) 00083 { 00084 MultiInterfaceChooserDialog* d = new MultiInterfaceChooserDialog( 00085 parent, loaded_interfaces, title); 00086 d->init(blackboard, type_pattern, id_pattern); 00087 return d; 00088 } 00089 00090 00091 /** Constructor for subclasses. 00092 * 00093 * After calling this constructor, the init() method needs to be called. 00094 * 00095 * @param parent parent window 00096 * @param loaded_interfaces list of interfaces which are already loaded 00097 * @param title title of the dialog 00098 */ 00099 MultiInterfaceChooserDialog::MultiInterfaceChooserDialog( 00100 Gtk::Window &parent, 00101 const TypeIdPairList& loaded_interfaces, 00102 const Glib::ustring& title) 00103 : InterfaceChooserDialog(parent, title), 00104 __record(NULL) 00105 { 00106 __loaded_interfaces.insert(loaded_interfaces.begin(), loaded_interfaces.end()); 00107 Glib::RefPtr<Gtk::TreeSelection> treesel = __treeview.get_selection(); 00108 __treeview.set_reorderable(true); 00109 __treeview.set_tooltip_text("Drag the rows to change the painting order."); 00110 treesel->set_mode(Gtk::SELECTION_NONE); 00111 // May *NOT* call init(), because init() calls virtual methods. 00112 } 00113 00114 00115 /** Destructor. */ 00116 MultiInterfaceChooserDialog::~MultiInterfaceChooserDialog() 00117 { 00118 if (__record) { 00119 delete __record; 00120 } 00121 } 00122 00123 00124 void 00125 MultiInterfaceChooserDialog::on_load_toggled(const Glib::ustring& path) 00126 { 00127 Gtk::TreeModel::Row row = *__model->get_iter(path); 00128 row[record().load] = !row[record().load]; 00129 } 00130 00131 00132 /** Returns the Record of this chooser dialog. 00133 * Subclasses of InterfaceChooserDialog might want to override this method. 00134 * @return Record implementation. 00135 */ 00136 const MultiInterfaceChooserDialog::Record& 00137 MultiInterfaceChooserDialog::record() const 00138 { 00139 if (!__record) { 00140 MultiInterfaceChooserDialog* this_nonconst = const_cast<MultiInterfaceChooserDialog*>(this); 00141 this_nonconst->__record = new Record(); 00142 } 00143 return *__record; 00144 } 00145 00146 00147 /** Initializes the columns GUI-wise. 00148 * Called in the ctor. 00149 * Subclasses of InterfaceChooserDialog might want to override this method, 00150 * but should probably still call their super-class's implementation 00151 * (i.e., this one). 00152 * @return The number of columns added. 00153 */ 00154 int 00155 MultiInterfaceChooserDialog::init_columns() 00156 { 00157 __treeview.append_column("Load", record().load); 00158 00159 const int n = InterfaceChooserDialog::init_columns(); 00160 00161 Gtk::CellRendererToggle* renderer = dynamic_cast<Gtk::CellRendererToggle*>( 00162 __treeview.get_column_cell_renderer(0)); 00163 assert(renderer != NULL); 00164 00165 renderer->set_activatable(true); 00166 renderer->signal_toggled().connect( 00167 sigc::mem_fun(*this, &MultiInterfaceChooserDialog::on_load_toggled)); 00168 00169 return n + 2; 00170 } 00171 00172 00173 /** Initializes a row with the given interface. 00174 * Called in the ctor. 00175 * Subclasses of InterfaceChooserDialog might want to override this method, 00176 * but should probably still call their super-class's implementation 00177 * (i.e., this one). 00178 * @param row The row whose content is to be set. 00179 * @param ii The interface info that should populate the row. 00180 */ 00181 void 00182 MultiInterfaceChooserDialog::init_row(Gtk::TreeModel::Row& row, 00183 const InterfaceInfo& ii) 00184 { 00185 InterfaceChooserDialog::init_row(row, ii); 00186 row[record().load] = __loaded_interfaces.find(std::make_pair(ii.type(), ii.id())) != 00187 __loaded_interfaces.end(); 00188 } 00189 00190 00191 /** Get selected interface types and their respective IDs. 00192 * @return A list of type + id pairs of interfaces that are to be loaded. 00193 */ 00194 MultiInterfaceChooserDialog::TypeIdPairList 00195 MultiInterfaceChooserDialog::get_selected_interfaces() const 00196 { 00197 TypeIdPairList types_and_ids; 00198 00199 const Gtk::TreeNodeChildren children = __model->children(); 00200 for (Gtk::TreeNodeChildren::const_iterator it = children.begin(); 00201 it != children.end(); ++it) 00202 { 00203 const Gtk::TreeRow& row = *it; 00204 if (row[record().load]) { 00205 TypeIdPair pair = std::make_pair(row[record().type], row[record().id]); 00206 types_and_ids.push_back(pair); 00207 } 00208 } 00209 00210 return types_and_ids; 00211 } 00212 00213 00214 /** Get selected interface types and their respective IDs. 00215 * @return A list of type + id pairs of interfaces that are to be loaded, 00216 * and *NOT* contained in the list of loaded interfaces handed 00217 * over to create(). 00218 */ 00219 MultiInterfaceChooserDialog::TypeIdPairList 00220 MultiInterfaceChooserDialog::get_newly_selected_interfaces() const 00221 { 00222 TypeIdPairList types_and_ids; 00223 00224 const Gtk::TreeNodeChildren children = __model->children(); 00225 for (Gtk::TreeNodeChildren::const_iterator it = children.begin(); 00226 it != children.end(); ++it) 00227 { 00228 const Gtk::TreeRow& row = *it; 00229 if (row[record().load]) { 00230 TypeIdPair pair = std::make_pair(row[record().type], row[record().id]); 00231 if (__loaded_interfaces.find(pair) == __loaded_interfaces.end()) 00232 { 00233 types_and_ids.push_back(pair); 00234 } 00235 } 00236 } 00237 00238 return types_and_ids; 00239 } 00240 00241 } // end of namespace fawkes 00242