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
43using 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 */
60SkillGuiGtkWindow::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
238void
239SkillGuiGtkWindow::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
255void
256SkillGuiGtkWindow::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 }
266 skdbg_if_->msgq_enqueue(sgm);
267}
268
269/** Event handler for connection button. */
270void
271SkillGuiGtkWindow::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
281void
282SkillGuiGtkWindow::on_exit_clicked()
283{
284 Gtk::Main::quit();
285}
286
287void
288SkillGuiGtkWindow::on_controller_clicked()
289{
290 if (skiller_if_ && skiller_if_->is_valid() && skiller_if_->has_writer()
291 && skiller_if_->exclusive_controller() == skiller_if_->serial().get_string()) {
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 && strcmp(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
313void
314SkillGuiGtkWindow::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
322void
323SkillGuiGtkWindow::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().get_string()) {
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. */
349void
350SkillGuiGtkWindow::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() && strcmp(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. */
414void
415SkillGuiGtkWindow::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
433void
434SkillGuiGtkWindow::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().get_string()) {
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
503void
504SkillGuiGtkWindow::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().get_string()) {
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
573void
574SkillGuiGtkWindow::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
647void
648SkillGuiGtkWindow::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
682void
683SkillGuiGtkWindow::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
705void
706SkillGuiGtkWindow::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
725void
726SkillGuiGtkWindow::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
749void
750SkillGuiGtkWindow::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
759void
760SkillGuiGtkWindow::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. */
793SkillGuiGtkWindow::SkillStringRecord::SkillStringRecord()
794{
795 add(skillstring);
796}
797
798void
799SkillGuiGtkWindow::on_update_disabled()
800{
801#ifdef USE_PAPYRUS
802#else
803 tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP);
804#endif
805}
806
807void
808SkillGuiGtkWindow::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
virtual const char * what() const noexcept
Get primary string.
Definition: exception.cpp:639
iterator begin() noexcept
Get iterator for messages.
Definition: exception.cpp:676
const char * get_hostname() const
Get the client's hostname.
Definition: client.cpp:859
void disconnect()
Disconnect socket.
Definition: client.cpp:539
bool connected() const noexcept
Check if connection is alive.
Definition: client.cpp:828
Interface listener with dispatcher.
sigc::signal< void, Interface * > signal_data_changed()
Get "data changed" signal.
unsigned int msgq_enqueue(Message *message, bool proxy=false)
Enqueue message at end of queue.
Definition: interface.cpp:915
Uuid serial() const
Get instance serial of interface.
Definition: interface.cpp:695
bool is_valid() const
Check validity of interface.
Definition: interface.cpp:469
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:479
bool has_writer() const
Check if there is a writer for the interface.
Definition: interface.cpp:848
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:50
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.
SkillStatusEnum status() const
Get status value.
char * skill_string() const
Get skill_string value.
char * exclusive_controller() const
Get exclusive_controller value.
std::string get_string() const
Get the string representation of the Uuid.
Definition: uuid.cpp:107
Fawkes library namespace.