Fawkes API  Fawkes Development Version
netloggui.cpp
1 
2 /***************************************************************************
3  * netloggui.cpp - NetLog GUI
4  *
5  * Created: Wed Nov 05 11:03:56 2008
6  * Copyright 2008 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "netloggui.h"
24 
25 #include <gui_utils/logview.h>
26 #include <gui_utils/avahi_dispatcher.h>
27 #include <gui_utils/connection_dispatcher.h>
28 #include <gui_utils/service_chooser_dialog.h>
29 #include <netcomm/fawkes/client.h>
30 #include <netcomm/dns-sd/avahi_thread.h>
31 
32 #include <netinet/in.h>
33 
34 using namespace fawkes;
35 
36 
37 /** @class NetLogGuiGtkWindow "netloggui.h"
38  * NetLog GUI main window.
39  * The NetLog GUI provides shows log viewers for Fawkes instances on the
40  * network.
41  * @author Tim Niemueller
42  */
43 
44 /** Constructor.
45  * @param cobject C base object
46  * @param builder Gtk builder
47  */
49  const Glib::RefPtr<Gtk::Builder> &builder)
50  : Gtk::Window(cobject)
51 {
52  builder->get_widget("vbox_main", vbox_main);
53  builder->get_widget("lab_no_connection", lab_no_connection);
54  builder->get_widget("tb_connection", tb_connection);
55  builder->get_widget("tb_exit", tb_exit);
56  builder->get_widget("tb_clear", tb_clear);
57 
58  vbox_main->pack_end(ntb_logviewers);
59 
60  avahi_dispatcher = new AvahiDispatcher();
61  avahi_dispatcher->signal_service_added().connect(sigc::retype_return<void>(sigc::mem_fun(*this, &NetLogGuiGtkWindow::on_service_added)));
62  avahi_dispatcher->signal_service_removed().connect(sigc::mem_fun(*this, &NetLogGuiGtkWindow::on_service_removed));
63 
64  avahi_thread = new AvahiThread();
65  avahi_thread->start();
66  avahi_thread->watch_service("_fawkes._tcp", avahi_dispatcher);
67 
68  tb_connection->signal_clicked().connect(sigc::mem_fun(*this, &NetLogGuiGtkWindow::on_connection_clicked));
69  tb_exit->signal_clicked().connect(sigc::mem_fun(*this, &NetLogGuiGtkWindow::on_exit_clicked));
70  tb_clear->signal_clicked().connect(sigc::mem_fun(*this, &NetLogGuiGtkWindow::on_clear_clicked));
71 }
72 
73 
74 /** Destructor. */
76 {
77  avahi_thread->cancel();
78  avahi_thread->join();
79  delete avahi_dispatcher;
80  delete avahi_thread;
81 }
82 
83 
84 /** Event handler for connection button. */
85 void
86 NetLogGuiGtkWindow::on_connection_clicked()
87 {
88  ServiceChooserDialog ssd(*this);
89  if (ssd.run() ) {
90  struct sockaddr_in saddr;
91  socklen_t saddr_size = sizeof(struct sockaddr_in);
92  Glib::ustring name, hostname;
93  unsigned short int port = 1910;
94  std::list<std::string> txt;
95  int page = -1;
96 
97  try {
98  ssd.get_selected_service (name, hostname, port);
99  ssd.get_raw_address((struct sockaddr *)&saddr, saddr_size);
100  NetworkService *service = new NetworkService(name.c_str(), "_fawkes._tcp", "",
101  hostname.c_str(), port,
102  (struct sockaddr *)&saddr,
103  saddr_size, txt);
104  page = on_service_added(service);
105  delete service;
106 
107  if ( page >= 0 ) {
108  Gtk::ScrolledWindow *scrolled = dynamic_cast<Gtk::ScrolledWindow *>(ntb_logviewers.get_nth_page(page));
109  LogView *logview = dynamic_cast<LogView *>(scrolled->get_child());
110  logview->get_client()->connect(hostname.c_str(), port);
111  }
112  } catch (Exception &e) {
113  Glib::ustring message = *(e.begin());
114  Gtk::MessageDialog md(*this, message, /* markup */ false,
115  Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
116  /* modal */ true);
117  md.set_title("Connection failed");
118  md.run();
119 
120  ntb_logviewers.remove_page(page);
121  }
122  }
123 }
124 
125 
126 void
127 NetLogGuiGtkWindow::on_exit_clicked()
128 {
129  Gtk::Main::quit();
130 }
131 
132 
133 void
134 NetLogGuiGtkWindow::on_clear_clicked()
135 {
136  int page = ntb_logviewers.get_current_page();
137  if (page >= 0) {
138  Gtk::ScrolledWindow *scrolled = dynamic_cast<Gtk::ScrolledWindow *>(ntb_logviewers.get_nth_page(page));
139  LogView *lv = dynamic_cast<LogView *>(scrolled->get_child());
140  lv->clear();
141  }
142 }
143 
144 
145 int
146 NetLogGuiGtkWindow::on_service_added(fawkes::NetworkService *service)
147 {
148  if ( ntb_logviewers.get_n_pages() == 0 ) {
149  lab_no_connection->hide();
150  //Gtk::Container *thiscon = this;
151  //thiscon->remove(lab_no_connection);
152  //add(ntb_logviewers);
153  ntb_logviewers.show();
154  }
155 
156  Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, 4));
157  Gtk::Button *button = Gtk::manage(new Gtk::Button());
158  Gtk::Image *image = Gtk::manage(new Gtk::Image(Gtk::Stock::CONNECT, Gtk::ICON_SIZE_BUTTON));
159  button->add(*image);
160  button->set_relief(Gtk::RELIEF_NONE);
161  Gtk::Label *label = Gtk::manage(new Gtk::Label());
162  label->set_markup(Glib::ustring("<b>") + service->host() + "</b>\n" + service->addr_string());
163  label->set_line_wrap();
164  Gtk::Label *invisible = Gtk::manage(new Gtk::Label(Glib::ustring(service->name()) + "::" + service->type() + "::" + service->domain()));
165  Gtk::ScrolledWindow *scrolled = Gtk::manage(new Gtk::ScrolledWindow());
166  scrolled->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
167  LogView *logview =
168  Gtk::manage(new LogView(service->addr_string().c_str(), service->port()));
169  //scrolled->add(*logview);
170 
171  hbox->pack_start(*button);
172  hbox->pack_start(*label);
173  hbox->pack_start(*invisible);
174 
175  button->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &NetLogGuiGtkWindow::on_connbut_clicked), image, logview));
176  logview->get_connection_dispatcher()->signal_connected().connect(sigc::bind(sigc::mem_fun(*this, &NetLogGuiGtkWindow::on_connected), image));
177  logview->get_connection_dispatcher()->signal_disconnected().connect(sigc::bind(sigc::mem_fun(*this, &NetLogGuiGtkWindow::on_disconnected), image));
178 
179  scrolled->show();
180  label->show();
181  image->show();
182  button->show();
183  logview->show();
184  hbox->show();
185 
186  int rv = ntb_logviewers.append_page(*logview, *hbox);
187 
188  return rv;
189 }
190 
191 
192 void
193 NetLogGuiGtkWindow::on_service_removed(fawkes::NetworkService *service)
194 {
195  bool removed = false;
196  do {
197  removed = false;
198 
199  for (int i = 0; ! removed && (i < ntb_logviewers.get_n_pages()); ++i) {
200  Gtk::Widget *child = ntb_logviewers.get_nth_page(i);
201  Gtk::Widget *tab_label = ntb_logviewers.get_tab_label(*child);
202  Gtk::HBox *hbox = dynamic_cast<Gtk::HBox *>(tab_label);
203 
204  if ( hbox ) {
205  std::vector<Gtk::Widget *> children = hbox->get_children();
206  Gtk::Widget *w = children[2];
207  if (w) {
208  Gtk::Label *label = dynamic_cast<Gtk::Label *>(w);
209  if ( label ) {
210  Glib::ustring s = Glib::ustring(service->name()) + "::" + service->type() + "::" + service->domain();
211  if (label->get_text() == s) {
212  ntb_logviewers.remove_page(i);
213  removed = true;
214  }
215  }
216  }
217  }
218  }
219  } while (removed);
220 
221  if ( ntb_logviewers.get_n_pages() == 0 ) {
222  ntb_logviewers.hide();
223  //Gtk::Container *thiscon = this;
224  //thiscon->remove(ntb_logviewers);
225  //add(lab_no_connection);
226  lab_no_connection->show();
227  }
228 }
229 
230 
231 void
232 NetLogGuiGtkWindow::on_connbut_clicked(Gtk::Image *image, fawkes::LogView *logview)
233 {
234  FawkesNetworkClient *client = logview->get_client();
235  if ( client->connected() ) {
236  client->disconnect();
237  } else {
238  try {
239  client->connect();
240  } catch (Exception &e) {
241  Glib::ustring message = *(e.begin());
242  Gtk::MessageDialog md(*this, message, /* markup */ false,
243  Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
244  /* modal */ true);
245  md.set_title("Connection failed");
246  md.run();
247  }
248  }
249 }
250 
251 
252 void
253 NetLogGuiGtkWindow::on_connected(Gtk::Image *image)
254 {
255  image->set(Gtk::Stock::DISCONNECT, Gtk::ICON_SIZE_BUTTON);
256 }
257 
258 
259 void
260 NetLogGuiGtkWindow::on_disconnected(Gtk::Image *image)
261 {
262  image->set(Gtk::Stock::CONNECT, Gtk::ICON_SIZE_BUTTON);
263 }
Log View widget.
Definition: logview.h:40
sigc::signal< void > signal_disconnected()
Get "disconnected" signal.
sigc::signal< void > signal_connected()
Get "connected" signal.
ConnectionDispatcher * get_connection_dispatcher() const
Get ConnectionDispatcher instance that is used internally.
Definition: logview.cpp:192
Simple Fawkes network client.
Definition: client.h:52
void clear()
Clear all records.
Definition: logview.cpp:200
Avahi dispatcher.
FawkesNetworkClient * get_client()
Get the used FawkesNetworkClient.
Definition: logview.cpp:182
Fawkes library namespace.
void disconnect()
Disconnect socket.
Definition: client.cpp:529
const char * host() const
Get host of service.
Definition: service.cpp:368
void connect()
Connect to remote.
Definition: client.cpp:417
std::string addr_string() const
Get IP address of entry as string.
Definition: service.cpp:389
unsigned short int port() const
Get port of service.
Definition: service.cpp:378
sigc::signal< void, NetworkService * > signal_service_removed()
Get "service remove" signal.
Base class for exceptions in Fawkes.
Definition: exception.h:36
~NetLogGuiGtkWindow()
Destructor.
Definition: netloggui.cpp:75
void watch_service(const char *service_type, ServiceBrowseHandler *h)
Add a result handler.
iterator begin()
Get iterator for messages.
Definition: exception.cpp:700
void get_raw_address(struct sockaddr *addr, socklen_t addr_size)
Get raw address.
Avahi main thread.
Definition: avahi_thread.h:54
Representation of a service announced or found via service discovery (i.e.
Definition: service.h:37
void cancel()
Cancel a thread.
Definition: thread.cpp:651
const char * domain() const
Get domain of service.
Definition: service.cpp:358
void join()
Join the thread.
Definition: thread.cpp:610
bool connected() const
Check if connection is alive.
Definition: client.cpp:823
void get_selected_service(Glib::ustring &name, Glib::ustring &hostname, unsigned short int &port)
Get selected service.
sigc::signal< void, NetworkService * > signal_service_added()
Get "service added" signal.
const char * type() const
Get type of service.
Definition: service.cpp:348
NetLogGuiGtkWindow(BaseObjectType *cobject, const Glib::RefPtr< Gtk::Builder > &builder)
Constructor.
Definition: netloggui.cpp:48
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:511
const char * name() const
Get name of service.
Definition: service.cpp:312