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/connection_dispatcher.h>
26 #include <gui_utils/service_model.h>
27 #include <gui_utils/service_selector_cbe.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(
156  sigc::mem_fun(*this, &ServiceSelectorCBE::on_service_selected));
157 
158  Gtk::Entry *ent = static_cast<Gtk::Entry *>(m_cbe_services->get_child());
159  if (ent) {
160  char *fawkes_ip = getenv("FAWKES_IP");
161  if (fawkes_ip)
162  ent->set_text(fawkes_ip);
163  else
164  ent->set_text("localhost");
165  }
166 
167  if (m_btn_connect) {
168  m_btn_connect->signal_clicked().connect(
169  sigc::mem_fun(*this, &ServiceSelectorCBE::on_btn_connect_clicked));
170  m_btn_connect->set_label("gtk-connect");
171  m_btn_connect->set_use_stock(true);
172  m_btn_connect->grab_default();
173  } else {
174  m_tbtn_connect->signal_clicked().connect(
175  sigc::mem_fun(*this, &ServiceSelectorCBE::on_btn_connect_clicked));
176  m_tbtn_connect->set_stock_id(Gtk::StockID("gtk-connect"));
177  m_tbtn_connect->grab_default();
178  }
179 
181  m_dispatcher->signal_connected().connect(sigc::mem_fun(*this, &ServiceSelectorCBE::on_connected));
183  sigc::mem_fun(*this, &ServiceSelectorCBE::on_disconnected));
184 
185  hostname_ = "";
186  port_ = 0;
187 }
188 
189 /** Destructor. */
191 {
192  delete m_dispatcher;
193  delete m_service_model;
194 }
195 
196 /** Access the current network client.
197  * @return the current network client
198  */
201 {
202  return m_dispatcher->get_client();
203 }
204 
205 /**
206  * Returns the currently selected hostname (after connect)
207  * @return the hostname
208  */
209 Glib::ustring
211 {
212  return hostname_;
213 }
214 
215 /**
216  * Returns the currently selected service name (after connect)
217  * @return the service name
218  */
219 Glib::ustring
221 {
222  return servicename_;
223 }
224 
225 /**
226  * Returns the currently used port (after connect)
227  * @return the port
228  */
229 unsigned int
231 {
232  return port_;
233 }
234 
235 /** This signal is emitted whenever a network connection is established.
236  * @return reference to the corresponding dispatcher
237  */
238 sigc::signal<void>
240 {
241  return m_dispatcher->signal_connected();
242 }
243 
244 /** This signal is emitted whenever a network connection is terminated.
245  * @return reference to the corresponding dispatcher
246  */
247 sigc::signal<void>
249 {
251 }
252 
253 /** Signal handler that is called whenever the connect button is
254  * clicked or an entry in the combo box is selected.
255  */
256 void
258 {
260 
261  if (client->connected()) {
262  client->disconnect();
263  if (m_btn_connect) {
264  m_btn_connect->set_label("gtk-connect");
265  } else {
266  m_tbtn_connect->set_label("gtk-connect");
267  }
268  } else {
269  if (-1 == m_cbe_services->get_active_row_number()) {
270  Gtk::Entry *entry = m_cbe_services->get_entry();
271  hostname_ = entry->get_text();
272 
273  Glib::ustring::size_type pos;
274  if ((pos = hostname_.find(':')) != Glib::ustring::npos) {
275  Glib::ustring host = "";
276  unsigned int port = 1234567; //Greater than max port num (i.e. 65535)
277  std::istringstream is(hostname_.replace(pos, 1, " "));
278  is >> host;
279  is >> port;
280 
281  if (port != 1234567 && host.size()) {
282  hostname_ = host;
283  port_ = port;
284  }
285  } else
286  port_ = 1910;
287  servicename_ = hostname_;
288  } else {
289  Gtk::TreeModel::Row row = *m_cbe_services->get_active();
290  hostname_ = row[m_service_model->get_column_record().hostname];
291  servicename_ = row[m_service_model->get_column_record().name];
292  port_ = row[m_service_model->get_column_record().port];
293  }
294 
295  try {
296  client->connect(hostname_.c_str(), port_);
297  } catch (Exception &e) {
298  Glib::ustring message = *(e.begin());
299  Gtk::MessageDialog md(*m_parent,
300  message,
301  /* markup */ false,
302  Gtk::MESSAGE_ERROR,
303  Gtk::BUTTONS_OK,
304  /* modal */ true);
305  md.set_title("Connection failed");
306  md.run();
307  }
308  }
309 }
310 
311 /** Signal handler that is called whenever an entry is selected from
312  * the combo box.
313  */
314 void
316 {
317  if (-1 == m_cbe_services->get_active_row_number())
318  return;
319 
321  if (client->connected()) {
322  client->disconnect();
323  }
324 
325  Gtk::TreeModel::Row row = *m_cbe_services->get_active();
326  hostname_ = row[m_service_model->get_column_record().hostname];
327  servicename_ = row[m_service_model->get_column_record().name];
328  port_ = row[m_service_model->get_column_record().port];
329 
330  m_cbe_services->get_entry()->set_text(hostname_);
331 
332  try {
333  client->connect(hostname_.c_str(), port_);
334  } catch (Exception &e) {
335  Glib::ustring message = *(e.begin());
336  Gtk::MessageDialog md(*m_parent,
337  message,
338  /* markup */ false,
339  Gtk::MESSAGE_ERROR,
340  Gtk::BUTTONS_OK,
341  /* modal */ true);
342  md.set_title("Connection failed");
343  md.run();
344  }
345 }
346 
347 /** Signal handler for the connection established signal. */
348 void
350 {
351  if (m_btn_connect) {
352  m_btn_connect->set_label("gtk-disconnect");
353  } else {
354  m_tbtn_connect->set_stock_id(Gtk::StockID("gtk-disconnect"));
355  }
356 }
357 
358 /** Signal handler for the connection terminated signal. */
359 void
361 {
362  if (m_btn_connect) {
363  m_btn_connect->set_label("gtk-connect");
364  } else {
365  m_tbtn_connect->set_stock_id(Gtk::StockID("gtk-connect"));
366  }
367 }
Watches network client events and dispatches them as signals.
sigc::signal< void > signal_connected()
Get "connected" signal.
FawkesNetworkClient * get_client()
Get client.
sigc::signal< void > signal_disconnected()
Get "disconnected" signal.
Base class for exceptions in Fawkes.
Definition: exception.h:36
iterator begin() noexcept
Get iterator for messages.
Definition: exception.cpp:676
Simple Fawkes network client.
Definition: client.h:52
void connect()
Connect to remote.
Definition: client.cpp:424
void disconnect()
Disconnect socket.
Definition: client.cpp:539
bool connected() const noexcept
Check if connection is alive.
Definition: client.cpp:828
Gtk::TreeModelColumn< unsigned short > port
The port the service is running on.
Definition: service_model.h:69
Gtk::TreeModelColumn< Glib::ustring > name
The name of the service.
Definition: service_model.h:60
Gtk::TreeModelColumn< Glib::ustring > hostname
The name of the host the service is running on.
Definition: service_model.h:64
Abstract base class for widgets that allow to view the detected services of a certain type.
Definition: service_model.h:36
ServiceRecord & get_column_record()
Access the column record.
Glib::RefPtr< Gtk::ListStore > & get_list_store()
Get a reference to the model.
void on_btn_connect_clicked()
Signal handler that is called whenever the connect button is clicked or an entry in the combo box is ...
void initialize()
Initializer method.
Glib::ustring get_name()
Returns the currently selected service name (after connect)
void on_disconnected()
Signal handler for the connection terminated signal.
Gtk::Window * m_parent
The parent Gtk::Window.
void on_connected()
Signal handler for the connection established signal.
Gtk::ToolButton * m_tbtn_connect
A Gtk::ToolButton that triggers the connection.
Gtk::Button * m_btn_connect
A Gtk::Button that triggers the connection.
ServiceSelectorCBE(Gtk::ComboBoxEntry *services, Gtk::Button *connect, Gtk::Window *parent, const char *service="_fawkes._tcp")
Construtor.
unsigned int get_port()
Returns the currently used port (after connect)
sigc::signal< void > signal_connected()
This signal is emitted whenever a network connection is established.
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.
ConnectionDispatcher * m_dispatcher
A ConnectionDispatcher which dispatches connection signals.
void on_service_selected()
Signal handler that is called whenever an entry is selected from the combo box.
FawkesNetworkClient * get_network_client()
Access the current network client.
sigc::signal< void > signal_disconnected()
This signal is emitted whenever a network connection is terminated.
Glib::ustring get_hostname()
Returns the currently selected hostname (after connect)
virtual ~ServiceSelectorCBE()
Destructor.
Fawkes library namespace.