Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * interface_chooser_dialog.cpp - Dialog for choosing a blackboard interface 00004 * 00005 * Created: Sat Mar 19 12:21:40 2011 00006 * Copyright 2008-2011 Tim Niemueller [www.niemueller.de] 00007 * Copyright 2011 Christoph Schwering 00008 * 00009 ****************************************************************************/ 00010 00011 /* This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. A runtime exception applies to 00015 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00016 * 00017 * This program is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU Library General Public License for more details. 00021 * 00022 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00023 */ 00024 00025 #include <gui_utils/interface_chooser_dialog.h> 00026 00027 #include <gtkmm.h> 00028 #include <core/exception.h> 00029 #include <core/exceptions/software.h> 00030 #include <blackboard/blackboard.h> 00031 #include <interface/interface_info.h> 00032 00033 #include <cstring> 00034 00035 namespace fawkes { 00036 #if 0 /* just to make Emacs auto-indent happy */ 00037 } 00038 #endif 00039 00040 /** Default title of interface chooser dialogs. */ 00041 const char* const InterfaceChooserDialog::DEFAULT_TITLE = "Select Interfaces"; 00042 00043 /** @class InterfaceChooserDialog::Record <gui_utils/interface_chooser_dialog.h> 00044 * Blackboard interface record. 00045 * Record with information about a blackboard interface for a tree model. 00046 * @author Tim Niemueller 00047 */ 00048 00049 /** Constructor. */ 00050 InterfaceChooserDialog::Record::Record() 00051 { 00052 add(type); 00053 add(id); 00054 add(has_writer); 00055 add(num_readers); 00056 } 00057 00058 /** @class InterfaceChooserDialog <gui_utils/interface_chooser_dialog.h> 00059 * Blackboard interface chooser dialog. 00060 * Allows to choose a blackboard interface from a list of interfaces matching 00061 * given type and ID patterns. 00062 * @author Tim Niemueller, Christoph Schwering 00063 */ 00064 00065 00066 /** Factory method. 00067 * 00068 * Why a factory method instead of a ctor? 00069 * The factory method calls init(), and init() calls other virtual methods. 00070 * If this was a ctor, this ctor would not be allowed to be called by 00071 * subclasses, because then the virtual methods in init() don't dispatch the 00072 * right way during construction (see Effective C++ #9). 00073 * 00074 * @param parent parent window 00075 * @param blackboard blackboard instance to query interfaces from 00076 * @param type_pattern pattern with shell like globs (* for any number of 00077 * characters, ? for exactly one character) to match the interface type. 00078 * @param id_pattern pattern with shell like globs (* for any number of 00079 * characters, ? for exactly one character) to match the interface ID. 00080 * @param title title of the dialog 00081 * @return new InterfaceChooserDialog 00082 */ 00083 InterfaceChooserDialog* 00084 InterfaceChooserDialog::create( 00085 Gtk::Window& parent, 00086 BlackBoard* blackboard, 00087 const char* type_pattern, 00088 const char* id_pattern, 00089 const Glib::ustring& title) 00090 { 00091 InterfaceChooserDialog* d = new InterfaceChooserDialog(parent, title); 00092 d->init(blackboard, type_pattern, id_pattern); 00093 return d; 00094 } 00095 00096 00097 /** Constructor for subclasses. 00098 * 00099 * After calling this constructor, the init() method needs to be called. 00100 * 00101 * @param parent parent window 00102 * @param title title of the dialog 00103 */ 00104 InterfaceChooserDialog::InterfaceChooserDialog(Gtk::Window& parent, 00105 const Glib::ustring& title) 00106 : Gtk::Dialog(title, parent, /* modal */ true), 00107 __parent(parent), 00108 __record(NULL) 00109 { 00110 // May *NOT* call init(), because init() calls virtual methods. 00111 } 00112 00113 00114 /** Initialization method. 00115 * 00116 * Subclasses should use the protected constructor and should then call the 00117 * init() method. 00118 * This ensures that init()'s calls to virtual methods dispatch to the right 00119 * ones. 00120 * 00121 * @param blackboard blackboard instance to query interfaces from 00122 * @param type_pattern pattern with shell like globs (* for any number of 00123 * characters, ? for exactly one character) to match the interface type. 00124 * @param id_pattern pattern with shell like globs (* for any number of 00125 * characters, ? for exactly one character) to match the interface ID. 00126 */ 00127 void 00128 InterfaceChooserDialog::init(BlackBoard *blackboard, 00129 const char *type_pattern, 00130 const char *id_pattern) 00131 { 00132 __model = Gtk::ListStore::create(record()); 00133 00134 set_default_size(360, 240); 00135 00136 __treeview.set_model(__model); 00137 init_columns(); 00138 __scrollwin.add(__treeview); 00139 __scrollwin.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); 00140 __treeview.show(); 00141 00142 Gtk::Box *vbox = get_vbox(); 00143 vbox->pack_start(__scrollwin); 00144 __scrollwin.show(); 00145 00146 add_button(Gtk::Stock::CANCEL, 0); 00147 add_button(Gtk::Stock::OK, 1); 00148 00149 set_default_response(1); 00150 00151 __treeview.signal_row_activated().connect(sigc::bind(sigc::hide<0>(sigc::hide<0>(sigc::mem_fun(*this, &InterfaceChooserDialog::response))), 1)); 00152 00153 __bb = blackboard; 00154 00155 InterfaceInfoList *infl = __bb->list(type_pattern, id_pattern); 00156 for (InterfaceInfoList::iterator i = infl->begin(); i != infl->end(); ++i) { 00157 Gtk::TreeModel::Row row = *__model->append(); 00158 init_row(row, *i); 00159 } 00160 delete infl; 00161 } 00162 00163 00164 /** Destructor. */ 00165 InterfaceChooserDialog::~InterfaceChooserDialog() 00166 { 00167 if (__record) { 00168 delete __record; 00169 } 00170 } 00171 00172 00173 /** Returns the Record of this chooser dialog. 00174 * Subclasses of InterfaceChooserDialog might want to override this method. 00175 * @return Record implementation. 00176 */ 00177 const InterfaceChooserDialog::Record& 00178 InterfaceChooserDialog::record() const 00179 { 00180 if (!__record) { 00181 InterfaceChooserDialog* this_nonconst = const_cast<InterfaceChooserDialog*>(this); 00182 this_nonconst->__record = new Record(); 00183 } 00184 return *__record; 00185 } 00186 00187 00188 /** Initializes the columns GUI-wise. 00189 * Called in the ctor. 00190 * Subclasses of InterfaceChooserDialog might want to override this method, 00191 * but should probably still call their super-class's implementation 00192 * (i.e., this one). 00193 * @return The number of columns added. 00194 */ 00195 int 00196 InterfaceChooserDialog::init_columns() 00197 { 00198 __treeview.append_column("Type", record().type); 00199 __treeview.append_column("ID", record().id); 00200 __treeview.append_column("Writer?", record().has_writer); 00201 __treeview.append_column("Readers", record().num_readers); 00202 return 4; 00203 } 00204 00205 00206 /** Initializes a row with the given interface. 00207 * Called in the ctor. 00208 * Subclasses of InterfaceChooserDialog might want to override this method, 00209 * but should probably still call their super-class's implementation 00210 * (i.e., this one). 00211 * @param row The row whose content is to be set. 00212 * @param ii The interface info that should populate the row. 00213 */ 00214 void 00215 InterfaceChooserDialog::init_row(Gtk::TreeModel::Row& row, 00216 const InterfaceInfo& ii) 00217 { 00218 row[record().type] = ii.type(); 00219 row[record().id] = ii.id(); 00220 row[record().has_writer] = ii.has_writer(); 00221 row[record().num_readers] = ii.num_readers(); 00222 } 00223 00224 00225 /** Get selected interface type and ID. 00226 * If an interface has been selected use this method to get the 00227 * type and ID. 00228 * Only applicable if get_multi() == false. 00229 * @param type upon return contains the type of the interface 00230 * @param id upon return contains the ID of the interface 00231 * @exception Exception thrown if no interface has been selected 00232 */ 00233 void 00234 InterfaceChooserDialog::get_selected_interface(Glib::ustring &type, 00235 Glib::ustring &id) 00236 { 00237 const Glib::RefPtr<Gtk::TreeSelection> treesel = __treeview.get_selection(); 00238 const Gtk::TreeModel::iterator iter = treesel->get_selected(); 00239 if (iter) { 00240 const Gtk::TreeModel::Row row = *iter; 00241 type = row[record().type]; 00242 id = row[record().id]; 00243 } else { 00244 throw Exception("No interface selected"); 00245 } 00246 } 00247 00248 00249 /** Run dialog and try to connect. 00250 * This runs the service chooser dialog and connects to the given service 00251 * with the attached FawkesNetworkClient. If the connection couldn't be established 00252 * an error dialog is shown. You should not rely on the connection to be 00253 * active after calling this method, rather you should use a ConnectionDispatcher 00254 * to get the "connected" signal. 00255 * @return interface instant of the selected interface. Note that this is only 00256 * an untyped interface instance which is useful for instrospection purposes 00257 * only. 00258 */ 00259 fawkes::Interface * 00260 InterfaceChooserDialog::run_and_open_for_reading() 00261 { 00262 if (__bb->is_alive()) throw Exception("BlackBoard is not alive"); 00263 00264 if ( run() ) { 00265 try { 00266 Glib::ustring type; 00267 Glib::ustring id; 00268 00269 return __bb->open_for_reading(type.c_str(), id.c_str()); 00270 } catch (Exception &e) { 00271 Glib::ustring message = *(e.begin()); 00272 Gtk::MessageDialog md(__parent, message, /* markup */ false, 00273 Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 00274 /* modal */ true); 00275 md.set_title("Opening Interface failed"); 00276 md.run(); 00277 throw; 00278 } 00279 } else { 00280 return NULL; 00281 } 00282 } 00283 00284 } // end of namespace fawkes