Fawkes API  Fawkes Development Version
service_selector_cbe.cpp
1 
2 /***************************************************************************
3  * service_selector_cbe.cpp - Manages list of discovered services of given type
4  *
5  * Created: Mon Sep 29 17:46:44 2008
6  * Copyright 2008 Daniel Beck
7  * 2008 Tim Niemueller [www.niemueller.de]
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version. A runtime exception applies to
15  * this software (see LICENSE.GPL_WRE file mentioned below for details).
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Library General Public License for more details.
21  *
22  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23  */
24 
25 #include <gui_utils/service_selector_cbe.h>
26 #include <gui_utils/service_model.h>
27 #include <gui_utils/connection_dispatcher.h>
28 #include <netcomm/fawkes/client.h>
29 
30 #include <sstream>
31 
32 using namespace fawkes;
33 
34 /** @class fawkes::ServiceSelectorCBE gui_utils/service_selector_cbe.h
35  * This widget consists of a Gtk::ComboBox and a Gtk::Button. The
36  * combo box contains all detected services of a given type; upon
37  * click the button opens a network connection to the selected service.
38  *
39  * @author Daniel Beck
40  * @author Tim Niemueller
41  */
42 
43 /** @var fawkes::ServiceSelectorCBE::m_cbe_services
44  * A Gtk::ComboBox that lists all available services.
45  */
46 
47 /** @var fawkes::ServiceSelectorCBE::m_btn_connect
48  * A Gtk::Button that triggers the connection.
49  */
50 
51 /** @var fawkes::ServiceSelectorCBE::m_tbtn_connect
52  * A Gtk::ToolButton that triggers the connection.
53  */
54 
55 /** @var fawkes::ServiceSelectorCBE::m_parent
56  * The parent Gtk::Window.
57  */
58 
59 /** @var fawkes::ServiceSelectorCBE::m_service_model
60  * A liststore which contains information about detected services.
61  */
62 
63 /** @var fawkes::ServiceSelectorCBE::m_dispatcher
64  * A ConnectionDispatcher which dispatches connection signals.
65  */
66 
67 /** Construtor.
68  * @param services the combo box to hold the list of services
69  * @param connect the button to trigger the network connection
70  * @param parent the parent window. Used for error dialogs.
71  * @param service a service identifier
72  */
73 #if GTK_VERSION_GE(3,0)
74 ServiceSelectorCBE::ServiceSelectorCBE( Gtk::ComboBox* services,
75 #else
76 ServiceSelectorCBE::ServiceSelectorCBE( Gtk::ComboBoxEntry* services,
77 #endif
78  Gtk::Button* connect,
79  Gtk::Window* parent,
80  const char* service )
81 {
82  m_service_model = new ServiceModel(service);
83 
84  m_cbe_services = services;
85  m_btn_connect = connect;
86  m_tbtn_connect = NULL;
87  m_parent = parent;
88 
89  initialize();
90 }
91 
92 /** Construtor.
93  * @param services the combo box to hold the list of services
94  * @param connect the button to trigger the network connection
95  * @param parent the parent window. Used for error dialogs.
96  * @param service a service identifier
97  */
98 #if GTK_VERSION_GE(3,0)
99 ServiceSelectorCBE::ServiceSelectorCBE( Gtk::ComboBox* services,
100 #else
101 ServiceSelectorCBE::ServiceSelectorCBE( Gtk::ComboBoxEntry* services,
102 #endif
103  Gtk::ToolButton* connect,
104  Gtk::Window* parent,
105  const char* service )
106 {
107  m_service_model = new ServiceModel(service);
108 
109  m_cbe_services = services;
110  m_btn_connect = NULL;
111  m_tbtn_connect = connect;
112  m_parent = parent;
113 
114  initialize();
115 }
116 
117 /** Constructor.
118  * @param builder Gtk builder
119  * @param cbe_name name of the combo box
120  * @param btn_name name of the button
121  * @param wnd_name name of the parent window
122  * @param service service identifier
123  */
124 ServiceSelectorCBE::ServiceSelectorCBE( Glib::RefPtr<Gtk::Builder> builder,
125  const char* cbe_name,
126  const char* btn_name,
127  const char* wnd_name,
128  const char* service )
129 {
130  m_service_model = new ServiceModel(service);
131 
132  builder->get_widget(wnd_name, m_parent);
133  builder->get_widget(cbe_name, m_cbe_services);
134  builder->get_widget(btn_name, m_btn_connect);
135 
136  initialize();
137 }
138 
139 /** Initializer method. */
140 void
142 {
143 #if GTK_VERSION_GE(3,0)
144  if (! m_cbe_services->get_has_entry()) {
145  throw Exception("Service combo box does not have an entry, fix UI file?");
146  }
147 #endif
149 #if GTK_VERSION_GE(3,0)
150  m_cbe_services->set_entry_text_column(m_service_model->get_column_record().name);
151 #else
153 #endif
154  m_cbe_services->get_entry()->set_activates_default(true);
155  m_cbe_services->signal_changed().connect( sigc::mem_fun( *this, &ServiceSelectorCBE::on_service_selected) );
156 
157  Gtk::Entry *ent = static_cast<Gtk::Entry *>(m_cbe_services->get_child());
158  if (ent)
159  {
160  char * fawkes_ip = getenv("FAWKES_IP");
161  if (fawkes_ip) ent->set_text(fawkes_ip);
162  else ent->set_text("localhost");
163  }
164 
165  if ( m_btn_connect )
166  {
167  m_btn_connect->signal_clicked().connect( sigc::mem_fun( *this, &ServiceSelectorCBE::on_btn_connect_clicked) );
168  m_btn_connect->set_label("gtk-connect");
169  m_btn_connect->set_use_stock(true);
170  m_btn_connect->grab_default();
171  }
172  else
173  {
174  m_tbtn_connect->signal_clicked().connect( sigc::mem_fun( *this, &ServiceSelectorCBE::on_btn_connect_clicked) );
175  m_tbtn_connect->set_stock_id( Gtk::StockID("gtk-connect") );
176  m_tbtn_connect->grab_default();
177  }
178 
180  m_dispatcher->signal_connected().connect(sigc::mem_fun(*this, &ServiceSelectorCBE::on_connected));
181  m_dispatcher->signal_disconnected().connect(sigc::mem_fun(*this, &ServiceSelectorCBE::on_disconnected));
182 
183  __hostname = "";
184  __port = 0;
185 }
186 
187 /** Destructor. */
189 {
190  delete m_dispatcher;
191  delete m_service_model;
192 }
193 
194 /** Access the current network client.
195  * @return the current network client
196  */
199 {
200  return m_dispatcher->get_client();
201 }
202 
203 /**
204  * Returns the currently selected hostname (after connect)
205  * @return the hostname
206  */
207 Glib::ustring
209 {
210  return __hostname;
211 }
212 
213 /**
214  * Returns the currently selected service name (after connect)
215  * @return the service name
216  */
217 Glib::ustring
219 {
220  return __servicename;
221 }
222 
223 /**
224  * Returns the currently used port (after connect)
225  * @return the port
226  */
227 unsigned int
229 {
230  return __port;
231 }
232 
233 /** This signal is emitted whenever a network connection is established.
234  * @return reference to the corresponding dispatcher
235  */
236 sigc::signal<void>
238 {
239  return m_dispatcher->signal_connected();
240 }
241 
242 /** This signal is emitted whenever a network connection is terminated.
243  * @return reference to the corresponding dispatcher
244  */
245 sigc::signal<void>
247 {
249 }
250 
251 /** Signal handler that is called whenever the connect button is
252  * clicked or an entry in the combo box is selected.
253  */
254 void
256 {
258 
259  if (client->connected())
260  {
261  client->disconnect();
262  if ( m_btn_connect )
263  { m_btn_connect->set_label("gtk-connect"); }
264  else
265  { m_tbtn_connect->set_label("gtk-connect"); }
266  }
267  else
268  {
269  if ( -1 == m_cbe_services->get_active_row_number() )
270  {
271  Gtk::Entry* entry = m_cbe_services->get_entry();
272  __hostname = entry->get_text();
273 
274  Glib::ustring::size_type pos;
275  if ((pos = __hostname.find(':')) != Glib::ustring::npos)
276  {
277  Glib::ustring host = "";
278  unsigned int port = 1234567; //Greater than max port num (i.e. 65535)
279  std::istringstream is(__hostname.replace(pos, 1, " "));
280  is >> host;
281  is >> port;
282 
283  if (port != 1234567 && host.size())
284  {
285  __hostname = host;
286  __port = port;
287  }
288  }
289  else __port = 1910;
290  __servicename = __hostname;
291  }
292  else
293  {
294  Gtk::TreeModel::Row row = *m_cbe_services->get_active();
295  __hostname = row[m_service_model->get_column_record().hostname];
296  __servicename = row[m_service_model->get_column_record().name];
297  __port = row[m_service_model->get_column_record().port];
298  }
299 
300  try
301  {
302  client->connect( __hostname.c_str(), __port );
303  }
304  catch (Exception& e)
305  {
306  Glib::ustring message = *(e.begin());
307  Gtk::MessageDialog md(*m_parent, message, /* markup */ false,
308  Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
309  /* modal */ true);
310  md.set_title("Connection failed");
311  md.run();
312  }
313  }
314 }
315 
316 /** Signal handler that is called whenever an entry is selected from
317  * the combo box.
318  */
319 void
321 {
322  if ( -1 == m_cbe_services->get_active_row_number() ) return;
323 
325  if ( client->connected() )
326  {
327  client->disconnect();
328  }
329 
330  Gtk::TreeModel::Row row = *m_cbe_services->get_active();
331  __hostname = row[m_service_model->get_column_record().hostname];
332  __servicename = row[m_service_model->get_column_record().name];
333  __port = row[m_service_model->get_column_record().port];
334 
335  m_cbe_services->get_entry()->set_text(__hostname);
336 
337  try
338  {
339  client->connect( __hostname.c_str(), __port );
340  }
341  catch (Exception& e)
342  {
343  Glib::ustring message = *(e.begin());
344  Gtk::MessageDialog md(*m_parent, message, /* markup */ false,
345  Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
346  /* modal */ true);
347  md.set_title("Connection failed");
348  md.run();
349  }
350 }
351 
352 /** Signal handler for the connection established signal. */
353 void
355 {
356  if ( m_btn_connect )
357  { m_btn_connect->set_label("gtk-disconnect"); }
358  else
359  { m_tbtn_connect->set_stock_id( Gtk::StockID("gtk-disconnect") ); }
360 }
361 
362 /** Signal handler for the connection terminated signal. */
363 void
365 {
366  if ( m_btn_connect )
367  { m_btn_connect->set_label("gtk-connect"); }
368  else
369  { m_tbtn_connect->set_stock_id( Gtk::StockID("gtk-connect") ); }
370 }
Abstract base class for widgets that allow to view the detected services of a certain type...
Definition: service_model.h:34
ServiceRecord & get_column_record()
Access the column record.
sigc::signal< void > signal_disconnected()
Get "disconnected" signal.
sigc::signal< void > signal_connected()
Get "connected" signal.
Gtk::TreeModelColumn< Glib::ustring > hostname
The name of the host the service is running on.
Definition: service_model.h:62
void on_btn_connect_clicked()
Signal handler that is called whenever the connect button is clicked or an entry in the combo box is ...
Simple Fawkes network client.
Definition: client.h:52
Gtk::Window * m_parent
The parent Gtk::Window.
sigc::signal< void > signal_disconnected()
This signal is emitted whenever a network connection is terminated.
void on_disconnected()
Signal handler for the connection terminated signal.
Fawkes library namespace.
void disconnect()
Disconnect socket.
Definition: client.cpp:529
void connect()
Connect to remote.
Definition: client.cpp:417
Glib::RefPtr< Gtk::ListStore > & get_list_store()
Get a reference to the model.
void initialize()
Initializer method.
unsigned int get_port()
Returns the currently used port (after connect)
ServiceModel * m_service_model
A liststore which contains information about detected services.
Gtk::ComboBoxEntry * m_cbe_services
A Gtk::ComboBox that lists all available services.
Base class for exceptions in Fawkes.
Definition: exception.h:36
ServiceSelectorCBE(Gtk::ComboBoxEntry *services, Gtk::Button *connect, Gtk::Window *parent, const char *service="_fawkes._tcp")
Construtor.
Glib::ustring get_name()
Returns the currently selected service name (after connect)
void on_service_selected()
Signal handler that is called whenever an entry is selected from the combo box.
iterator begin()
Get iterator for messages.
Definition: exception.cpp:700
Glib::ustring get_hostname()
Returns the currently selected hostname (after connect)
Gtk::TreeModelColumn< unsigned short > port
The port the service is running on.
Definition: service_model.h:65
ConnectionDispatcher * m_dispatcher
A ConnectionDispatcher which dispatches connection signals.
FawkesNetworkClient * get_network_client()
Access the current network client.
void on_connected()
Signal handler for the connection established signal.
Gtk::ToolButton * m_tbtn_connect
A Gtk::ToolButton that triggers the connection.
sigc::signal< void > signal_connected()
This signal is emitted whenever a network connection is established.
Gtk::TreeModelColumn< Glib::ustring > name
The name of the service.
Definition: service_model.h:59
Gtk::Button * m_btn_connect
A Gtk::Button that triggers the connection.
bool connected() const
Check if connection is alive.
Definition: client.cpp:823
FawkesNetworkClient * get_client()
Get client.
Watches network client events and dispatches them as signals.
virtual ~ServiceSelectorCBE()
Destructor.