Fawkes API  Fawkes Development Version
skillgui.cpp
1 
2 /***************************************************************************
3  * skillgui.cpp - Skill GUI
4  *
5  * Created: Mon Nov 03 13:37:33 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 "skillgui.h"
24 #ifdef USE_PAPYRUS
25 # include "graph_viewport.h"
26 #else
27 # include "graph_drawing_area.h"
28 #endif
29 
30 #include <blackboard/remote.h>
31 #include <gui_utils/interface_dispatcher.h>
32 #include <gui_utils/logview.h>
33 #include <gui_utils/plugin_tree_view.h>
34 #include <gui_utils/service_chooser_dialog.h>
35 #include <netcomm/fawkes/client.h>
36 #include <utils/system/argparser.h>
37 
38 #include <cstring>
39 #include <gvc.h>
40 #include <iostream>
41 #include <string>
42 
43 using namespace fawkes;
44 
45 #define ACTIVE_SKILL "Active Skill"
46 #define SKILL_DOT "Skills dot graph"
47 #define SKILL_SEP_LINE "----------------"
48 
49 /** @class SkillGuiGtkWindow "skillgui.h"
50  * Skill GUI main window.
51  * The Skill GUI provides shows Skiller log messages and allows for
52  * executing skills.
53  * @author Tim Niemueller
54  */
55 
56 /** Constructor.
57  * @param cobject C base object
58  * @param builder Gtk Builder
59  */
60 SkillGuiGtkWindow::SkillGuiGtkWindow(BaseObjectType * cobject,
61  const Glib::RefPtr<Gtk::Builder> &builder)
62 : Gtk::Window(cobject)
63 {
64  bb = NULL;
65  skiller_if_ = NULL;
66  skdbg_if_ = NULL;
67  agdbg_if_ = NULL;
68 
69 #ifdef HAVE_GCONFMM
70  try {
71  gconf_ = Gnome::Conf::Client::get_default_client();
72  gconf_->add_dir(GCONF_PREFIX);
73  } catch (Gnome::Conf::Error &e) {
74  std::cerr << e.what() << std::endl;
75  throw;
76  }
77 #endif
78 
79  builder->get_widget_derived("trv_log", logview_);
80  builder->get_widget("tb_connection", tb_connection);
81  builder->get_widget("but_clearlog", but_clearlog);
82  builder->get_widget("tb_exit", tb_exit);
83  builder->get_widget("cbe_skillstring", cbe_skillstring);
84  builder->get_widget("but_exec", but_exec);
85  builder->get_widget("but_stop", but_stop);
86  builder->get_widget("lab_status", lab_status);
87  builder->get_widget("lab_alive", lab_alive);
88  builder->get_widget("lab_skillstring", lab_skillstring);
89  builder->get_widget("lab_error", lab_error);
90  builder->get_widget("scw_graph", scw_graph);
91  //builder->get_widget("drw_graph", drw_graph);
92  builder->get_widget("ntb_tabs", ntb_tabs);
93  builder->get_widget("tb_skiller", tb_skiller);
94  builder->get_widget("tb_agent", tb_agent);
95  builder->get_widget("tb_graphlist", tb_graphlist);
96  builder->get_widget("tb_controller", tb_controller);
97  builder->get_widget("tb_graphsave", tb_graphsave);
98  builder->get_widget("tb_graphopen", tb_graphopen);
99  builder->get_widget("tb_graphupd", tb_graphupd);
100  builder->get_widget("tb_graphrecord", tb_graphrecord);
101  builder->get_widget("tb_zoomin", tb_zoomin);
102  builder->get_widget("tb_zoomout", tb_zoomout);
103  builder->get_widget("tb_zoomfit", tb_zoomfit);
104  builder->get_widget("tb_zoomreset", tb_zoomreset);
105  builder->get_widget("tb_graphdir", tb_graphdir);
106  builder->get_widget("tb_graphcolored", tb_graphcolored);
107 
108 #if GTKMM_VERSION_GE(2, 20)
109  builder->get_widget("tb_spinner", tb_spinner);
110 #endif
111  builder->get_widget_derived("trv_plugins", trv_plugins_);
112 
113  Gtk::SeparatorToolItem *spacesep;
114  builder->get_widget("tb_spacesep", spacesep);
115  spacesep->set_expand();
116 
117  // This should be in the Glade file, but is not restored for some reason
118  tb_graphsave->set_homogeneous(false);
119  tb_graphopen->set_homogeneous(false);
120  tb_graphupd->set_homogeneous(false);
121  tb_graphrecord->set_homogeneous(false);
122  tb_zoomin->set_homogeneous(false);
123  tb_zoomout->set_homogeneous(false);
124  tb_zoomfit->set_homogeneous(false);
125  tb_zoomreset->set_homogeneous(false);
126  tb_graphdir->set_homogeneous(false);
127  tb_graphcolored->set_homogeneous(false);
128 
129 #if GTK_VERSION_GE(3, 0)
130  if (!cbe_skillstring->get_has_entry()) {
131  throw Exception("Skill string combo box has no entry, invalid UI file?");
132  }
133 #endif
134  sks_list_ = Gtk::ListStore::create(sks_record_);
135  cbe_skillstring->set_model(sks_list_);
136 #if GTK_VERSION_GE(3, 0)
137  cbe_skillstring->set_entry_text_column(sks_record_.skillstring);
138 #else
139  cbe_skillstring->set_text_column(sks_record_.skillstring);
140 #endif
141 
142  cbe_skillstring->get_entry()->set_activates_default(true);
143 
144  trv_plugins_->set_network_client(connection_dispatcher.get_client());
145 #ifdef HAVE_GCONFMM
146  trv_plugins_->set_gconf_prefix(GCONF_PREFIX);
147 #endif
148 
149 #ifdef USE_PAPYRUS
150  pvp_graph = Gtk::manage(new SkillGuiGraphViewport());
151  scw_graph->add(*pvp_graph);
152  pvp_graph->show();
153 #else
154  gda = Gtk::manage(new SkillGuiGraphDrawingArea());
155  scw_graph->add(*gda);
156  gda->show();
157 #endif
158 
159  cb_graphlist = Gtk::manage(new Gtk::ComboBoxText());
160 #if GTK_VERSION_GE(3, 0)
161  cb_graphlist->append(ACTIVE_SKILL);
162 #else
163  cb_graphlist->append_text(ACTIVE_SKILL);
164 #endif
165  cb_graphlist->set_active_text(ACTIVE_SKILL);
166  tb_graphlist->add(*cb_graphlist);
167  cb_graphlist->show();
168 
169  //ntb_tabs->set_current_page(1);
170 
171  connection_dispatcher.signal_connected().connect(
172  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_connect));
173  connection_dispatcher.signal_disconnected().connect(
174  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_disconnect));
175 
176  tb_connection->signal_clicked().connect(
177  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_connection_clicked));
178  but_exec->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_exec_clicked));
179  tb_controller->signal_clicked().connect(
180  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_controller_clicked));
181  tb_exit->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_exit_clicked));
182  but_stop->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_stop_clicked));
183  but_clearlog->signal_clicked().connect(sigc::mem_fun(*logview_, &LogView::clear));
184  tb_skiller->signal_toggled().connect(
185  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skdbg_data_changed));
186  tb_skiller->signal_toggled().connect(
187  sigc::bind(sigc::mem_fun(*cb_graphlist, &Gtk::ComboBoxText::set_sensitive), true));
188  tb_agent->signal_toggled().connect(
189  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_agdbg_data_changed));
190  tb_agent->signal_toggled().connect(
191  sigc::bind(sigc::mem_fun(*cb_graphlist, &Gtk::ComboBoxText::set_sensitive), false));
192  cb_graphlist->signal_changed().connect(
193  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skill_changed));
194  tb_graphupd->signal_clicked().connect(
195  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphupd_clicked));
196  tb_graphdir->signal_clicked().connect(
197  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_clicked));
198  tb_graphcolored->signal_toggled().connect(
199  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphcolor_toggled));
200 #ifdef USE_PAPYRUS
201  tb_graphsave->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::save));
202  tb_zoomin->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_in));
203  tb_zoomout->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_out));
204  tb_zoomfit->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_fit));
205  tb_zoomreset->signal_clicked().connect(
206  sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_reset));
207 #else
208  tb_graphsave->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::save));
209  tb_graphopen->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::open));
210  tb_zoomin->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_in));
211  tb_zoomout->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_out));
212  tb_zoomfit->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_fit));
213  tb_zoomreset->signal_clicked().connect(
214  sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_reset));
215  tb_graphrecord->signal_clicked().connect(
216  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_recording_toggled));
217  gda->signal_update_disabled().connect(
218  sigc::mem_fun(*this, &SkillGuiGtkWindow::on_update_disabled));
219 #endif
220 
221 #ifdef HAVE_GCONFMM
222  gconf_->signal_value_changed().connect(
223  sigc::hide(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_config_changed))));
224  on_config_changed();
225 #endif
226 }
227 
228 /** Destructor. */
230 {
231 #ifdef HAVE_GCONFMM
232  gconf_->remove_dir(GCONF_PREFIX);
233 #endif
234  logview_->set_client(NULL);
235  trv_plugins_->set_network_client(NULL);
236 }
237 
238 void
239 SkillGuiGtkWindow::on_config_changed()
240 {
241 #ifdef HAVE_GCONFMM
242  Gnome::Conf::SListHandle_ValueString l(gconf_->get_string_list(GCONF_PREFIX "/command_history"));
243 
244  sks_list_->clear();
245  for (Gnome::Conf::SListHandle_ValueString::const_iterator i = l.begin(); i != l.end(); ++i) {
246  Gtk::TreeModel::Row row = *sks_list_->append();
247  row[sks_record_.skillstring] = *i;
248  }
249 
250  bool colored = gconf_->get_bool(GCONF_PREFIX "/graph_colored");
251  tb_graphcolored->set_active(colored);
252 #endif
253 }
254 
255 void
256 SkillGuiGtkWindow::on_skill_changed()
257 {
258  Glib::ustring skill = cb_graphlist->get_active_text();
259  if (skill == ACTIVE_SKILL || skill == SKILL_SEP_LINE) {
260  skill = "ACTIVE";
261  } else if (skill == SKILL_DOT) {
262  skill = "SKILL_DEP";
263  }
265  new SkillerDebugInterface::SetGraphMessage(skill.c_str());
266  skdbg_if_->msgq_enqueue(sgm);
267 }
268 
269 /** Event handler for connection button. */
270 void
271 SkillGuiGtkWindow::on_connection_clicked()
272 {
273  if (!connection_dispatcher.get_client()->connected()) {
274  ServiceChooserDialog ssd(*this, connection_dispatcher.get_client());
275  ssd.run_and_connect();
276  } else {
277  connection_dispatcher.get_client()->disconnect();
278  }
279 }
280 
281 void
282 SkillGuiGtkWindow::on_exit_clicked()
283 {
284  Gtk::Main::quit();
285 }
286 
287 void
288 SkillGuiGtkWindow::on_controller_clicked()
289 {
290  if (skiller_if_ && skiller_if_->is_valid() && skiller_if_->has_writer()
291  && skiller_if_->exclusive_controller() == skiller_if_->serial()) {
292  // we are exclusive controller, release control
294  skiller_if_->msgq_enqueue(rcm);
295  } else if (skiller_if_ && skiller_if_->is_valid() && skiller_if_->has_writer()
296  && skiller_if_->exclusive_controller() == 0) {
297  // there is no exclusive controller, try to acquire control
299  skiller_if_->msgq_enqueue(acm);
300  } else {
301  Gtk::MessageDialog md(*this,
302  "Another component already acquired the exclusive "
303  "control for the Skiller; not acquiring exclusive control.",
304  /* markup */ false,
305  Gtk::MESSAGE_ERROR,
306  Gtk::BUTTONS_OK,
307  /* modal */ true);
308  md.set_title("Control Acquisition Failed");
309  md.run();
310  }
311 }
312 
313 void
314 SkillGuiGtkWindow::on_stop_clicked()
315 {
316  if (bb && skiller_if_ && skiller_if_->is_valid() && skiller_if_->has_writer()) {
318  skiller_if_->msgq_enqueue(sem);
319  }
320 }
321 
322 void
323 SkillGuiGtkWindow::close_bb()
324 {
325  if (bb) {
326  bb->unregister_listener(skiller_ifd_);
327  bb->unregister_listener(skdbg_ifd_);
328  bb->unregister_listener(agdbg_ifd_);
329  delete skiller_ifd_;
330  delete skdbg_ifd_;
331  delete agdbg_ifd_;
332  if (skiller_if_ && skiller_if_->is_valid() && skiller_if_->has_writer()
333  && (skiller_if_->exclusive_controller() == skiller_if_->serial())) {
335  skiller_if_->msgq_enqueue(rcm);
336  }
337  bb->close(skiller_if_);
338  bb->close(skdbg_if_);
339  bb->close(agdbg_if_);
340  delete bb;
341  skiller_if_ = NULL;
342  skdbg_if_ = NULL;
343  agdbg_if_ = NULL;
344  bb = NULL;
345  }
346 }
347 
348 /** Event handler for connected event. */
349 void
350 SkillGuiGtkWindow::on_connect()
351 {
352  try {
353  if (!bb) {
354  bb = new RemoteBlackBoard(connection_dispatcher.get_client());
355  skiller_if_ = bb->open_for_reading<SkillerInterface>("Skiller");
356  skdbg_if_ = bb->open_for_reading<SkillerDebugInterface>("Skiller");
357  agdbg_if_ = bb->open_for_reading<SkillerDebugInterface>("LuaAgent");
358  on_skiller_data_changed();
359  on_skdbg_data_changed();
360  on_agdbg_data_changed();
361 
362  skiller_ifd_ = new InterfaceDispatcher("Skiller IFD", skiller_if_);
363  skdbg_ifd_ = new InterfaceDispatcher("SkillerDebug IFD", skdbg_if_);
364  agdbg_ifd_ = new InterfaceDispatcher("LuaAgent SkillerDebug IFD", agdbg_if_);
365  bb->register_listener(skiller_ifd_, BlackBoard::BBIL_FLAG_DATA);
366  bb->register_listener(skdbg_ifd_, BlackBoard::BBIL_FLAG_DATA);
367  bb->register_listener(agdbg_ifd_, BlackBoard::BBIL_FLAG_DATA);
368  skiller_ifd_->signal_data_changed().connect(
369  sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skiller_data_changed)));
370  skdbg_ifd_->signal_data_changed().connect(
371  sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skdbg_data_changed)));
372  agdbg_ifd_->signal_data_changed().connect(
373  sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_agdbg_data_changed)));
374 
375  // always try to acquire control on connect, this may well fail, for
376  // example if agent is running, but we don't care
377  skiller_if_->read();
378  if (skiller_if_->has_writer() && skiller_if_->exclusive_controller() == 0) {
381  skiller_if_->msgq_enqueue(aqm);
382  }
383  if (skdbg_if_->has_writer()) {
386  skdbg_if_->msgq_enqueue(sgm);
387  }
388  }
389  tb_connection->set_stock_id(Gtk::Stock::DISCONNECT);
390  logview_->set_client(connection_dispatcher.get_client());
391 
392  tb_controller->set_sensitive(true);
393  cbe_skillstring->set_sensitive(true);
394 
395  this->set_title(std::string("Skill GUI @ ")
396  + connection_dispatcher.get_client()->get_hostname());
397  } catch (Exception &e) {
398  Glib::ustring message = *(e.begin());
399  Gtk::MessageDialog md(*this,
400  message,
401  /* markup */ false,
402  Gtk::MESSAGE_ERROR,
403  Gtk::BUTTONS_OK,
404  /* modal */ true);
405  md.set_title("BlackBoard connection failed");
406  md.run();
407 
408  close_bb();
409  connection_dispatcher.get_client()->disconnect();
410  }
411 }
412 
413 /** Event handler for disconnected event. */
414 void
415 SkillGuiGtkWindow::on_disconnect()
416 {
417  tb_controller->set_sensitive(false);
418  cbe_skillstring->set_sensitive(false);
419  but_exec->set_sensitive(false);
420  but_stop->set_sensitive(false);
421 
422  close_bb();
423 
424  tb_connection->set_stock_id(Gtk::Stock::CONNECT);
425 #ifdef USE_PAPYRUS
426  pvp_graph->queue_draw();
427 #endif
428  logview_->set_client(NULL);
429 
430  this->set_title("Skill GUI");
431 }
432 
433 void
434 SkillGuiGtkWindow::on_exec_clicked()
435 {
436  Glib::ustring sks = "";
437  if (cbe_skillstring->get_active_row_number() == -1) {
438  Gtk::Entry *entry = cbe_skillstring->get_entry();
439  sks = entry->get_text();
440  } else {
441  Gtk::TreeModel::Row row = *cbe_skillstring->get_active();
442 #if GTK_VERSION_GE(3, 0)
443  row.get_value(cbe_skillstring->get_entry_text_column(), sks);
444 #else
445  row.get_value(cbe_skillstring->get_text_column(), sks);
446 #endif
447  }
448 
449  if (sks != "") {
450 #if GTKMM_VERSION_GE(2, 20)
451  tb_spinner->start();
452 #endif
453 
454  if (skiller_if_ && skiller_if_->is_valid() && skiller_if_->has_writer()
455  && skiller_if_->exclusive_controller() == skiller_if_->serial()) {
457  skiller_if_->msgq_enqueue(esm);
458 
459  Gtk::TreeModel::Children children = sks_list_->children();
460  bool ok = true;
461  if (!children.empty()) {
462  size_t num = 0;
463  Gtk::TreeIter i = children.begin();
464  while (ok && (i != children.end())) {
465  if (num >= 9) {
466  i = sks_list_->erase(i);
467  } else {
468  Gtk::TreeModel::Row row = *i;
469  ok = (row[sks_record_.skillstring] != sks);
470  ++num;
471  ++i;
472  }
473  }
474  }
475  if (ok) {
476  Gtk::TreeModel::Row row = *sks_list_->prepend();
477  row[sks_record_.skillstring] = sks;
478 
479  std::list<Glib::ustring> l;
480  for (Gtk::TreeIter i = children.begin(); i != children.end(); ++i) {
481  Gtk::TreeModel::Row row = *i;
482  l.push_back(row[sks_record_.skillstring]);
483  }
484 
485 #ifdef HAVE_GCONFMM
486  gconf_->set_string_list(GCONF_PREFIX "/command_history", l);
487 #endif
488  }
489  } else {
490  Gtk::MessageDialog md(*this,
491  "The exclusive control over the skiller has "
492  "not been acquired yet and skills cannot be executed",
493  /* markup */ false,
494  Gtk::MESSAGE_ERROR,
495  Gtk::BUTTONS_OK,
496  /* modal */ true);
497  md.set_title("Skill Execution Failure");
498  md.run();
499  }
500  }
501 }
502 
503 void
504 SkillGuiGtkWindow::on_skiller_data_changed()
505 {
506  try {
507  skiller_if_->read();
508 
509  switch (skiller_if_->status()) {
510  case SkillerInterface::S_INACTIVE:
511 #if GTKMM_VERSION_GE(2, 20)
512  tb_spinner->stop();
513 #endif
514  lab_status->set_text("S_INACTIVE");
515  break;
516  case SkillerInterface::S_FINAL:
517 #if GTKMM_VERSION_GE(2, 20)
518  tb_spinner->stop();
519 #endif
520  //throbber_->set_stock(Gtk::Stock::APPLY);
521  lab_status->set_text("S_FINAL");
522  break;
523  case SkillerInterface::S_RUNNING:
524 #if GTKMM_VERSION_GE(2, 20)
525  tb_spinner->start();
526 #endif
527  lab_status->set_text("S_RUNNING");
528  break;
529  case SkillerInterface::S_FAILED:
530 #if GTKMM_VERSION_GE(2, 20)
531  tb_spinner->stop();
532 #endif
533  //throbber_->set_stock(Gtk::Stock::DIALOG_WARNING);
534  lab_status->set_text("S_FAILED");
535  break;
536  }
537 
538  lab_skillstring->set_text(skiller_if_->skill_string());
539  lab_error->set_text(skiller_if_->error());
540 #if GTKMM_MAJOR_VERSION > 2 || (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12)
541  lab_skillstring->set_tooltip_text(skiller_if_->skill_string());
542  lab_error->set_tooltip_text(skiller_if_->error());
543 #endif
544  lab_alive->set_text(skiller_if_->has_writer() ? "Yes" : "No");
545 
546  if (skiller_if_->exclusive_controller() == skiller_if_->serial()) {
547  if (tb_controller->get_stock_id() == Gtk::Stock::NO.id) {
548  tb_controller->set_stock_id(Gtk::Stock::YES);
549 #if GTKMM_MAJOR_VERSION > 2 || (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12)
550  tb_controller->set_tooltip_text("Release exclusive control");
551 #endif
552  }
553  but_exec->set_sensitive(true);
554  but_stop->set_sensitive(true);
555  } else {
556  if (tb_controller->get_stock_id() == Gtk::Stock::YES.id) {
557  tb_controller->set_stock_id(Gtk::Stock::NO);
558 #if GTKMM_MAJOR_VERSION > 2 || (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12)
559  tb_controller->set_tooltip_text("Gain exclusive control");
560 #endif
561  }
562  but_exec->set_sensitive(false);
563  but_stop->set_sensitive(false);
564  }
565 
566  } catch (Exception &e) {
567 #if GTKMM_VERSION_GE(2, 20)
568  tb_spinner->stop();
569 #endif
570  }
571 }
572 
573 void
574 SkillGuiGtkWindow::on_skdbg_data_changed()
575 {
576  if (tb_skiller->get_active() && skdbg_if_) {
577  try {
578  skdbg_if_->read();
579 
580  if (strcmp(skdbg_if_->graph_fsm(), "LIST") == 0) {
581  Glib::ustring list = skdbg_if_->graph();
582 #if GTK_VERSION_GE(3, 0)
583  cb_graphlist->remove_all();
584  cb_graphlist->append(ACTIVE_SKILL);
585  cb_graphlist->append(SKILL_DOT);
586  cb_graphlist->append(SKILL_SEP_LINE);
587 #else
588  cb_graphlist->clear_items();
589  cb_graphlist->append_text(ACTIVE_SKILL);
590  cb_graphlist->append_text(SKILL_DOT);
591  cb_graphlist->append_text(SKILL_SEP_LINE);
592 #endif
593  cb_graphlist->set_active_text(ACTIVE_SKILL);
594 #if GTK_VERSION_GE(2, 14)
595  Glib::RefPtr<Glib::Regex> regex = Glib::Regex::create("\n");
596  std::list<std::string> skills = regex->split(list);
597  for (std::list<std::string>::iterator i = skills.begin(); i != skills.end(); ++i) {
598 # if GTK_VERSION_GE(3, 0)
599  if (*i != "")
600  cb_graphlist->append(*i);
601 # else
602  if (*i != "")
603  cb_graphlist->append_text(*i);
604 # endif
605  }
606 #endif
607  if (skdbg_if_->has_writer()) {
610  skdbg_if_->msgq_enqueue(sgm);
611  }
612  } else {
613 #ifdef USE_PAPYRUS
614  pvp_graph->set_graph_fsm(skdbg_if_->graph_fsm());
615  pvp_graph->set_graph(skdbg_if_->graph());
616  pvp_graph->render();
617 #else
618  gda->set_graph_fsm(skdbg_if_->graph_fsm());
619  gda->set_graph(skdbg_if_->graph());
620 #endif
621  }
622 
623  switch (skdbg_if_->graph_dir()) {
624  case SkillerDebugInterface::GD_TOP_BOTTOM:
625  tb_graphdir->set_stock_id(Gtk::Stock::GO_DOWN);
626  break;
627  case SkillerDebugInterface::GD_BOTTOM_TOP:
628  tb_graphdir->set_stock_id(Gtk::Stock::GO_UP);
629  break;
630  case SkillerDebugInterface::GD_LEFT_RIGHT:
631  tb_graphdir->set_stock_id(Gtk::Stock::GO_FORWARD);
632  break;
633  case SkillerDebugInterface::GD_RIGHT_LEFT:
634  tb_graphdir->set_stock_id(Gtk::Stock::GO_BACK);
635  break;
636  }
637 
638  if (skdbg_if_->is_graph_colored() != tb_graphcolored->get_active()) {
639  tb_graphcolored->set_active(skdbg_if_->is_graph_colored());
640  }
641  } catch (Exception &e) {
642  // ignored
643  }
644  }
645 }
646 
647 void
648 SkillGuiGtkWindow::on_agdbg_data_changed()
649 {
650  if (tb_agent->get_active() && agdbg_if_) {
651  try {
652  agdbg_if_->read();
653 #ifdef USE_PAPYRUS
654  pvp_graph->set_graph_fsm(agdbg_if_->graph_fsm());
655  pvp_graph->set_graph(agdbg_if_->graph());
656  pvp_graph->render();
657 #else
658  gda->set_graph_fsm(agdbg_if_->graph_fsm());
659  gda->set_graph(agdbg_if_->graph());
660 #endif
661 
662  switch (agdbg_if_->graph_dir()) {
663  case SkillerDebugInterface::GD_TOP_BOTTOM:
664  tb_graphdir->set_stock_id(Gtk::Stock::GO_DOWN);
665  break;
666  case SkillerDebugInterface::GD_BOTTOM_TOP:
667  tb_graphdir->set_stock_id(Gtk::Stock::GO_UP);
668  break;
669  case SkillerDebugInterface::GD_LEFT_RIGHT:
670  tb_graphdir->set_stock_id(Gtk::Stock::GO_FORWARD);
671  break;
672  case SkillerDebugInterface::GD_RIGHT_LEFT:
673  tb_graphdir->set_stock_id(Gtk::Stock::GO_BACK);
674  break;
675  }
676  } catch (Exception &e) {
677  // ignored
678  }
679  }
680 }
681 
682 void
683 SkillGuiGtkWindow::on_graphupd_clicked()
684 {
685 #ifdef USE_PAPYRUS
686  if (pvp_graph->get_update_graph()) {
687  pvp_graph->set_update_graph(false);
688  tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP);
689  } else {
690  pvp_graph->set_update_graph(true);
691  tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_PLAY);
692  pvp_graph->render();
693  }
694 #else
695  if (gda->get_update_graph()) {
696  gda->set_update_graph(false);
697  tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP);
698  } else {
699  gda->set_update_graph(true);
700  tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_PLAY);
701  }
702 #endif
703 }
704 
705 void
706 SkillGuiGtkWindow::on_graphdir_clicked()
707 {
708  SkillerDebugInterface *iface = skdbg_if_;
709  if (tb_agent->get_active()) {
710  iface = agdbg_if_;
711  }
712 
713  Glib::ustring stockid = tb_graphdir->get_stock_id();
714  if (stockid == Gtk::Stock::GO_DOWN.id) {
715  send_graphdir_message(iface, SkillerDebugInterface::GD_BOTTOM_TOP);
716  } else if (stockid == Gtk::Stock::GO_UP.id) {
717  send_graphdir_message(iface, SkillerDebugInterface::GD_LEFT_RIGHT);
718  } else if (stockid == Gtk::Stock::GO_FORWARD.id) {
719  send_graphdir_message(iface, SkillerDebugInterface::GD_RIGHT_LEFT);
720  } else if (stockid == Gtk::Stock::GO_BACK.id) {
721  send_graphdir_message(iface, SkillerDebugInterface::GD_TOP_BOTTOM);
722  }
723 }
724 
725 void
726 SkillGuiGtkWindow::send_graphdir_message(SkillerDebugInterface * iface,
728 {
729  try {
730  if (iface) {
733  iface->msgq_enqueue(m);
734  } else {
735  throw Exception("Not connected to Fawkes.");
736  }
737  } catch (Exception &e) {
738  Gtk::MessageDialog md(*this,
739  Glib::ustring("Setting graph direction failed: ") + e.what(),
740  /* markup */ false,
741  Gtk::MESSAGE_ERROR,
742  Gtk::BUTTONS_OK,
743  /* modal */ true);
744  md.set_title("Communication Failure");
745  md.run();
746  }
747 }
748 
749 void
750 SkillGuiGtkWindow::on_graphdir_changed(SkillerDebugInterface::GraphDirectionEnum gd)
751 {
752  if (tb_agent->get_active()) {
753  send_graphdir_message(agdbg_if_, gd);
754  } else {
755  send_graphdir_message(skdbg_if_, gd);
756  }
757 }
758 
759 void
760 SkillGuiGtkWindow::on_graphcolor_toggled()
761 {
762 #ifdef HAVE_GCONFMM
763  gconf_->set(GCONF_PREFIX "/graph_colored", tb_graphcolored->get_active());
764 #endif
765 
766  SkillerDebugInterface *iface = skdbg_if_;
767  if (tb_agent->get_active()) {
768  iface = agdbg_if_;
769  }
770 
771  try {
772  if (iface) {
774  m = new SkillerDebugInterface::SetGraphColoredMessage(tb_graphcolored->get_active());
775  iface->msgq_enqueue(m);
776  } else {
777  throw Exception("Not connected to Fawkes.");
778  }
779  } catch (Exception &e) {
780  /* Ignore for now, causes error message on startup
781  Gtk::MessageDialog md(*this,
782  Glib::ustring("Setting graph color failed: ") + e.what(),
783  / markup / false,
784  Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
785  / modal / true);
786  md.set_title("Communication Failure");
787  md.run();
788  */
789  }
790 }
791 
792 /** Constructor. */
793 SkillGuiGtkWindow::SkillStringRecord::SkillStringRecord()
794 {
795  add(skillstring);
796 }
797 
798 void
799 SkillGuiGtkWindow::on_update_disabled()
800 {
801 #ifdef USE_PAPYRUS
802 #else
803  tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP);
804 #endif
805 }
806 
807 void
808 SkillGuiGtkWindow::on_recording_toggled()
809 {
810 #ifdef USE_PAPYRUS
811 #else
812  bool active = tb_graphrecord->get_active();
813  if (gda->set_recording(active) != active) {
814  tb_graphrecord->set_active(!active);
815  }
816 #endif
817 }
sigc::signal< void > signal_update_disabled()
Get "update disabled" signal.
void set_graph(const std::string &graph)
Set graph.
void open()
Open a dot graph and display it.
bool get_update_graph()
Check if graph is being updated.
void save()
save current graph.
void set_update_graph(bool update)
Set if the graph should be updated on new data.
void set_graph_fsm(const std::string &fsm_name)
Set graph's FSM name.
bool set_recording(bool recording)
Enable/disable recording.
Skill FSM Graph Viewport.
void zoom_fit()
Zoom to fit.
void save()
Render current graph.
void zoom_out()
Zoom out.
void zoom_reset()
Zoom reset.
SkillGuiGtkWindow(BaseObjectType *cobject, const Glib::RefPtr< Gtk::Builder > &builder)
Constructor.
Definition: skillgui.cpp:60
~SkillGuiGtkWindow()
Destructor.
Definition: skillgui.cpp:229
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: blackboard.cpp:212
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:185
virtual void close(Interface *interface)=0
Close interface.
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()
Get iterator for messages.
Definition: exception.cpp:676
virtual const char * what() const
Get primary string.
Definition: exception.cpp:639
bool connected() const
Check if connection is alive.
Definition: client.cpp:828
const char * get_hostname() const
Get the client's hostname.
Definition: client.cpp:859
void disconnect()
Disconnect socket.
Definition: client.cpp:539
Interface listener with dispatcher.
sigc::signal< void, Interface * > signal_data_changed()
Get "data changed" signal.
bool is_valid() const
Check validity of interface.
Definition: interface.cpp:462
unsigned short serial() const
Get instance serial of interface.
Definition: interface.cpp:686
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:472
bool has_writer() const
Check if there is a writer for the interface.
Definition: interface.cpp:817
unsigned int msgq_enqueue(Message *message)
Enqueue message at end of queue.
Definition: interface.cpp:882
void set_client(FawkesNetworkClient *client)
Set FawkesNetworkClient instance.
Definition: logview.cpp:149
void set_network_client(fawkes::FawkesNetworkClient *client)
Set the network client.
void set_gconf_prefix(Glib::ustring gconf_prefix)
Set Gconf prefix.
Remote BlackBoard.
Definition: remote.h:49
SetGraphColoredMessage Fawkes BlackBoard Interface Message.
SetGraphDirectionMessage Fawkes BlackBoard Interface Message.
SetGraphMessage Fawkes BlackBoard Interface Message.
SkillerDebugInterface Fawkes BlackBoard Interface.
GraphDirectionEnum
Primary direction of the graph.
char * graph_fsm() const
Get graph_fsm value.
char * graph() const
Get graph value.
GraphDirectionEnum graph_dir() const
Get graph_dir value.
AcquireControlMessage Fawkes BlackBoard Interface Message.
ExecSkillMessage Fawkes BlackBoard Interface Message.
ReleaseControlMessage Fawkes BlackBoard Interface Message.
StopExecMessage Fawkes BlackBoard Interface Message.
SkillerInterface Fawkes BlackBoard Interface.
char * error() const
Get error value.
uint32_t exclusive_controller() const
Get exclusive_controller value.
SkillStatusEnum status() const
Get status value.
char * skill_string() const
Get skill_string value.
Fawkes library namespace.