service_selector_cbe.cpp

00001
00002 /***************************************************************************
00003  *  service_selector_cbe.cpp - Manages list of discovered services of given type
00004  *
00005  *  Created: Mon Sep 29 17:46:44 2008
00006  *  Copyright  2008  Daniel Beck
00007  *             2008  Tim Niemueller [www.niemueller.de]
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/service_selector_cbe.h>
00026 #include <gui_utils/service_model.h>
00027 #include <gui_utils/utils.h>
00028 #include <gui_utils/connection_dispatcher.h>
00029 #include <netcomm/fawkes/client.h>
00030
00031 #include <sstream>
00032
00033 using namespace fawkes;
00034 
00035 /** @class fawkes::ServiceSelectorCBE gui_utils/service_selector_cbe.h
00036  * This widget consists of a Gtk::ComboBoxEntry and a Gtk::Button. The
00037  * combo box contains all detected services of a given type; upon
00038  * click the button opens a network connection to the selected service.
00039  *
00040  * @author Daniel Beck
00041  * @author Tim Niemueller
00042  */
00043 
00044 /** @var fawkes::ServiceSelectorCBE::m_cbe_services
00045  * A Gtk::ComboBoxEntry that lists all available services.
00046  */
00047 
00048 /** @var fawkes::ServiceSelectorCBE::m_btn_connect
00049  * A Gtk::Button that triggers the connection.
00050  */
00051 
00052 /** @var fawkes::ServiceSelectorCBE::m_tbtn_connect
00053  * A Gtk::ToolButton that triggers the connection.
00054  */
00055 
00056 /** @var fawkes::ServiceSelectorCBE::m_parent
00057  * The parent Gtk::Window.
00058  */
00059 
00060 /** @var fawkes::ServiceSelectorCBE::m_service_model
00061  * A liststore which contains information about detected services.
00062  */
00063 
00064 /** @var fawkes::ServiceSelectorCBE::m_dispatcher
00065  * A ConnectionDispatcher which dispatches connection signals.
00066  */
00067 
00068 /** Construtor.
00069  * @param services the combo box to hold the list of services
00070  * @param connect the button to trigger the network connection
00071  * @param parent the parent window. Used for error dialogs.
00072  * @param service a service identifier
00073  */
00074 ServiceSelectorCBE::ServiceSelectorCBE( Gtk::ComboBoxEntry* services,
00075                                         Gtk::Button* connect,
00076                                         Gtk::Window* parent,
00077                                         const char* service )
00078 {
00079   m_service_model = new ServiceModel(service);
00080
00081   m_cbe_services  = services;
00082   m_btn_connect   = connect;
00083   m_tbtn_connect  = NULL;
00084   m_parent        = parent;
00085
00086   initialize();
00087 }
00088 
00089 /** Construtor.
00090  * @param services the combo box to hold the list of services
00091  * @param connect the button to trigger the network connection
00092  * @param parent the parent window. Used for error dialogs.
00093  * @param service a service identifier
00094  */
00095 ServiceSelectorCBE::ServiceSelectorCBE( Gtk::ComboBoxEntry* services,
00096                                         Gtk::ToolButton* connect,
00097                                         Gtk::Window* parent,
00098                                         const char* service )
00099 {
00100   m_service_model = new ServiceModel(service);
00101
00102   m_cbe_services  = services;
00103   m_btn_connect   = NULL;
00104   m_tbtn_connect  = connect;
00105   m_parent        = parent;
00106
00107   initialize();
00108 }
00109 
00110 /** Constructor.
00111  * @param ref_xml Glade XML file
00112  * @param cbe_name name of the combo box
00113  * @param btn_name name of the button
00114  * @param wnd_name name of the parent window
00115  * @param service service identifier
00116  */
00117 ServiceSelectorCBE::ServiceSelectorCBE( Glib::RefPtr<Gnome::Glade::Xml> ref_xml,
00118                                         const char* cbe_name,
00119                                         const char* btn_name,
00120                                         const char* wnd_name,
00121                                         const char* service )
00122 {
00123   m_service_model = new ServiceModel(service);
00124
00125   ref_xml->get_widget(wnd_name, m_parent);
00126   ref_xml->get_widget(cbe_name, m_cbe_services);
00127   ref_xml->get_widget(btn_name, m_btn_connect);
00128
00129   initialize();
00130 }
00131 
00132 /** Initializer method. */
00133 void
00134 ServiceSelectorCBE::initialize()
00135 {
00136   m_cbe_services->set_model( m_service_model->get_list_store() );
00137   m_cbe_services->set_text_column(m_service_model->get_column_record().name);
00138   m_cbe_services->get_entry()->set_activates_default(true);
00139   m_cbe_services->signal_changed().connect( sigc::mem_fun( *this, &ServiceSelectorCBE::on_service_selected) );
00140
00141   Gtk::Entry *ent = static_cast<Gtk::Entry *>(m_cbe_services->get_child());
00142   if (ent)
00143   {
00144     char * fawkes_ip = getenv("FAWKES_IP");
00145     if (fawkes_ip) ent->set_text(fawkes_ip);
00146     else ent->set_text("localhost");
00147   }
00148
00149   if ( m_btn_connect )
00150   {
00151     m_btn_connect->signal_clicked().connect( sigc::mem_fun( *this, &ServiceSelectorCBE::on_btn_connect_clicked) );
00152     m_btn_connect->set_label("gtk-connect");
00153     m_btn_connect->set_use_stock(true);
00154     m_btn_connect->grab_default();
00155   }
00156   else
00157   {
00158     m_tbtn_connect->signal_clicked().connect( sigc::mem_fun( *this, &ServiceSelectorCBE::on_btn_connect_clicked) );
00159     m_tbtn_connect->set_stock_id( Gtk::StockID("gtk-connect") );
00160     m_tbtn_connect->grab_default();
00161   }
00162
00163   m_dispatcher = new ConnectionDispatcher();
00164   m_dispatcher->signal_connected().connect(sigc::mem_fun(*this, &ServiceSelectorCBE::on_connected));
00165   m_dispatcher->signal_disconnected().connect(sigc::mem_fun(*this, &ServiceSelectorCBE::on_disconnected));
00166
00167   __hostname = "";
00168   __port = 0;
00169 }
00170 
00171 /** Destructor. */
00172 ServiceSelectorCBE::~ServiceSelectorCBE()
00173 {
00174   delete m_dispatcher;
00175   delete m_service_model;
00176 }
00177 
00178 /** Access the current network client.
00179  * @return the current network client
00180  */
00181 FawkesNetworkClient*
00182 ServiceSelectorCBE::get_network_client()
00183 {
00184   return m_dispatcher->get_client();
00185 }
00186 
00187 /**
00188  * Returns the currently selected hostname (after connect)
00189  * @return the hostname
00190  */
00191 Glib::ustring
00192 ServiceSelectorCBE::get_hostname()
00193 {
00194   return __hostname;
00195 }
00196 
00197 /**
00198  * Returns the currently selected service name (after connect)
00199  * @return the service name
00200  */
00201 Glib::ustring
00202 ServiceSelectorCBE::get_name()
00203 {
00204   return __servicename;
00205 }
00206 
00207 /**
00208  * Returns the currently used port (after connect)
00209  * @return the port
00210  */
00211 unsigned int
00212 ServiceSelectorCBE::get_port()
00213 {
00214   return __port;
00215 }
00216 
00217 /** This signal is emitted whenever a network connection is established.
00218  * @return reference to the corresponding dispatcher
00219  */
00220 sigc::signal<void>
00221 ServiceSelectorCBE::signal_connected()
00222 {
00223   return m_dispatcher->signal_connected();
00224 }
00225 
00226 /** This signal is emitted whenever a network connection is terminated.
00227  * @return reference to the corresponding dispatcher
00228  */
00229 sigc::signal<void>
00230 ServiceSelectorCBE::signal_disconnected()
00231 {
00232   return m_dispatcher->signal_disconnected();
00233 }
00234 
00235 /** Signal handler that is called whenever the connect button is
00236  * clicked or an entry in the combo box is selected.
00237  */
00238 void
00239 ServiceSelectorCBE::on_btn_connect_clicked()
00240 {
00241   FawkesNetworkClient *client = m_dispatcher->get_client();
00242
00243   if (client->connected())
00244   {
00245     client->disconnect();
00246     if ( m_btn_connect )
00247     { m_btn_connect->set_label("gtk-connect"); }
00248     else
00249     { m_tbtn_connect->set_label("gtk-connect"); }
00250   }
00251   else
00252   {
00253     if ( -1 == m_cbe_services->get_active_row_number() )
00254     {
00255       Gtk::Entry* entry = m_cbe_services->get_entry();
00256       __hostname = entry->get_text();
00257
00258       Glib::ustring::size_type pos;
00259       if ((pos = __hostname.find(':')) != Glib::ustring::npos)
00260       {
00261         Glib::ustring host = "";
00262         unsigned int port = 1234567; //Greater than max port num (i.e. 65535)
00263         std::istringstream is(__hostname.replace(pos, 1, " "));
00264         is >> host;
00265         is >> port;
00266
00267         if (port != 1234567 && host.size())
00268         {
00269           __hostname = host;
00270           __port = port;
00271         }
00272       }
00273       else __port = 1910;
00274       __servicename = __hostname;
00275     }
00276     else
00277     {
00278       Gtk::TreeModel::Row row = *m_cbe_services->get_active();
00279       __hostname = row[m_service_model->get_column_record().hostname];
00280       __servicename = row[m_service_model->get_column_record().name];
00281       __port = row[m_service_model->get_column_record().port];
00282     }
00283
00284     try
00285     {
00286       client->connect( __hostname.c_str(), __port );
00287     }
00288     catch (Exception& e)
00289     {
00290       Glib::ustring message = *(e.begin());
00291       Gtk::MessageDialog md(*m_parent, message, /* markup */ false,
00292                             Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
00293                             /* modal */ true);
00294       md.set_title("Connection failed");
00295       md.run();
00296     }
00297   }
00298 }
00299 
00300 /** Signal handler that is called whenever an entry is selected from
00301  * the combo box.
00302  */
00303 void
00304 ServiceSelectorCBE::on_service_selected()
00305 {
00306   if ( -1 == m_cbe_services->get_active_row_number() )  return;
00307
00308   FawkesNetworkClient *client = m_dispatcher->get_client();
00309   if ( client->connected() )
00310   {
00311     client->disconnect();
00312   }
00313
00314   Gtk::TreeModel::Row row = *m_cbe_services->get_active();
00315   __hostname = row[m_service_model->get_column_record().hostname];
00316   __servicename = row[m_service_model->get_column_record().name];
00317   __port = row[m_service_model->get_column_record().port];
00318
00319   m_cbe_services->get_entry()->set_text(__hostname);
00320
00321   try
00322   {
00323     client->connect( __hostname.c_str(), __port );
00324   }
00325   catch (Exception& e)
00326   {
00327     Glib::ustring message = *(e.begin());
00328     Gtk::MessageDialog md(*m_parent, message, /* markup */ false,
00329                           Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
00330                           /* modal */ true);
00331     md.set_title("Connection failed");
00332     md.run();
00333   }
00334 }
00335 
00336 /** Signal handler for the connection established signal. */
00337 void
00338 ServiceSelectorCBE::on_connected()
00339 {
00340   if ( m_btn_connect )
00341   { m_btn_connect->set_label("gtk-disconnect"); }
00342   else
00343   { m_tbtn_connect->set_stock_id( Gtk::StockID("gtk-disconnect") ); }
00344 }
00345 
00346 /** Signal handler for the connection terminated signal. */
00347 void
00348 ServiceSelectorCBE::on_disconnected()
00349 {
00350   if ( m_btn_connect )
00351   { m_btn_connect->set_label("gtk-connect"); }
00352   else
00353   { m_tbtn_connect->set_stock_id( Gtk::StockID("gtk-connect") ); }
00354 }