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