Fawkes API  Fawkes Development Version
skillgui.cpp
00001 
00002 /***************************************************************************
00003  *  skillgui.cpp - Skill GUI
00004  *
00005  *  Created: Mon Nov 03 13:37:33 2008
00006  *  Copyright  2008  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include "skillgui.h"
00024 #ifdef USE_PAPYRUS
00025 #  include "graph_viewport.h"
00026 #else
00027 #  include "graph_drawing_area.h"
00028 #endif
00029 
00030 #include <utils/system/argparser.h>
00031 #include <blackboard/remote.h>
00032 #include <netcomm/fawkes/client.h>
00033 
00034 #include <gui_utils/logview.h>
00035 #include <gui_utils/throbber.h>
00036 #include <gui_utils/service_chooser_dialog.h>
00037 #include <gui_utils/interface_dispatcher.h>
00038 #include <gui_utils/plugin_tree_view.h>
00039 
00040 #include <cstring>
00041 #include <string>
00042 
00043 #include <gvc.h>
00044 
00045 using namespace fawkes;
00046 
00047 #define ACTIVE_SKILL "Active Skill"
00048 
00049 /** @class SkillGuiGtkWindow "skillgui.h"
00050  * Skill GUI main window.
00051  * The Skill GUI provides shows Skiller log messages and allows for
00052  * executing skills.
00053  * @author Tim Niemueller
00054  */
00055 
00056 /** Constructor.
00057  * @param cobject C base object
00058  * @param refxml Glade XML
00059  */
00060 SkillGuiGtkWindow::SkillGuiGtkWindow(BaseObjectType* cobject,
00061                                  const Glib::RefPtr<Gnome::Glade::Xml> &refxml)
00062   : Gtk::Window(cobject)
00063 {
00064   bb = NULL;
00065   __skiller_if = NULL;
00066   __skdbg_if = NULL;
00067   __agdbg_if = NULL;
00068 
00069 #ifdef HAVE_GCONFMM
00070   __gconf = Gnome::Conf::Client::get_default_client();
00071   __gconf->add_dir(GCONF_PREFIX);
00072 #endif
00073 
00074   refxml->get_widget_derived("trv_log", __logview);
00075   refxml->get_widget("tb_connection", tb_connection);
00076   refxml->get_widget("but_continuous", but_continuous);
00077   refxml->get_widget("but_clearlog", but_clearlog);
00078   refxml->get_widget("tb_exit", tb_exit);
00079   refxml->get_widget("cbe_skillstring", cbe_skillstring);
00080   refxml->get_widget("but_exec", but_exec);
00081   refxml->get_widget("but_stop", but_stop);
00082   refxml->get_widget("lab_status", lab_status);
00083   refxml->get_widget("lab_alive", lab_alive);
00084   refxml->get_widget("lab_continuous", lab_continuous);
00085   refxml->get_widget("lab_skillstring", lab_skillstring);
00086   refxml->get_widget("lab_error", lab_error);
00087   refxml->get_widget("scw_graph", scw_graph);
00088   //refxml->get_widget("drw_graph", drw_graph);
00089   refxml->get_widget("ntb_tabs", ntb_tabs);
00090   refxml->get_widget("tb_skiller", tb_skiller);
00091   refxml->get_widget("tb_agent", tb_agent);
00092   refxml->get_widget("tb_graphlist", tb_graphlist);
00093   refxml->get_widget("tb_controller", tb_controller);
00094   refxml->get_widget("tb_graphsave", tb_graphsave);
00095   refxml->get_widget("tb_graphopen", tb_graphopen);
00096   refxml->get_widget("tb_graphupd", tb_graphupd);
00097   refxml->get_widget("tb_graphrecord", tb_graphrecord);
00098   refxml->get_widget("tb_zoomin", tb_zoomin);
00099   refxml->get_widget("tb_zoomout", tb_zoomout);
00100   refxml->get_widget("tb_zoomfit", tb_zoomfit);
00101   refxml->get_widget("tb_zoomreset", tb_zoomreset);
00102   refxml->get_widget("tb_graphdir", tb_graphdir);
00103   refxml->get_widget("tb_graphcolored", tb_graphcolored);
00104   refxml->get_widget("mi_graphdir_title", mi_graphdir);
00105   refxml->get_widget("mi_top_bottom", mi_top_bottom);
00106   refxml->get_widget("mi_bottom_top", mi_bottom_top);
00107   refxml->get_widget("mi_left_right", mi_left_right);
00108   refxml->get_widget("mi_right_left", mi_right_left);
00109 
00110   refxml->get_widget_derived("img_throbber", __throbber);
00111   refxml->get_widget_derived("trv_plugins",  __trv_plugins);
00112   
00113   Gtk::SeparatorToolItem *spacesep;
00114   refxml->get_widget("tb_spacesep", spacesep);
00115   spacesep->set_expand();
00116 
00117   Gtk::Label *mi_graphdir_label = dynamic_cast<Gtk::Label *>(mi_graphdir->get_child());
00118   if ( mi_graphdir_label ) {
00119     mi_graphdir_label->set_markup("<b>Graph Direction</b>");
00120   }
00121   mi_graphdir->set_sensitive(false);
00122 
00123   // This should be in the Glade file, but is not restored for some reason
00124   tb_graphsave->set_homogeneous(false);
00125   tb_graphopen->set_homogeneous(false);
00126   tb_graphupd->set_homogeneous(false);
00127   tb_graphrecord->set_homogeneous(false);
00128   tb_zoomin->set_homogeneous(false);
00129   tb_zoomout->set_homogeneous(false);
00130   tb_zoomfit->set_homogeneous(false);
00131   tb_zoomreset->set_homogeneous(false);
00132   tb_graphdir->set_homogeneous(false);
00133   tb_graphcolored->set_homogeneous(false);
00134 
00135   __sks_list = Gtk::ListStore::create(__sks_record);
00136   cbe_skillstring->set_model(__sks_list);
00137   cbe_skillstring->set_text_column(__sks_record.skillstring);
00138 
00139   __trv_plugins->set_network_client(connection_dispatcher.get_client());
00140 #ifdef HAVE_GCONFMM
00141   __trv_plugins->set_gconf_prefix(GCONF_PREFIX);
00142 #endif
00143 
00144 #ifdef USE_PAPYRUS
00145   pvp_graph = Gtk::manage(new SkillGuiGraphViewport());
00146   scw_graph->add(*pvp_graph);
00147   pvp_graph->show();
00148 #else
00149   gda = Gtk::manage(new SkillGuiGraphDrawingArea());
00150   scw_graph->add(*gda);
00151   gda->show();
00152 #endif
00153 
00154   cb_graphlist = Gtk::manage(new Gtk::ComboBoxText());
00155   cb_graphlist->append_text(ACTIVE_SKILL);
00156   cb_graphlist->set_active_text(ACTIVE_SKILL);
00157   tb_graphlist->add(*cb_graphlist);
00158   cb_graphlist->show();
00159 
00160   //ntb_tabs->set_current_page(1);
00161 
00162   connection_dispatcher.signal_connected().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_connect));
00163   connection_dispatcher.signal_disconnected().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_disconnect));
00164 
00165   tb_connection->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_connection_clicked));
00166   but_exec->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_exec_clicked));
00167   tb_controller->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_controller_clicked));
00168   tb_exit->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_exit_clicked));
00169   but_stop->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_stop_clicked));
00170   but_continuous->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_contexec_toggled));
00171   but_clearlog->signal_clicked().connect(sigc::mem_fun(*__logview, &LogView::clear));
00172   tb_skiller->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skdbg_data_changed));
00173   tb_skiller->signal_toggled().connect(sigc::bind(sigc::mem_fun(*cb_graphlist, &Gtk::ComboBoxText::set_sensitive),true));
00174   tb_agent->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_agdbg_data_changed));
00175   tb_agent->signal_toggled().connect(sigc::bind(sigc::mem_fun(*cb_graphlist, &Gtk::ComboBoxText::set_sensitive),false));
00176   cb_graphlist->signal_changed().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skill_changed));
00177   tb_graphupd->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphupd_clicked));
00178   tb_graphdir->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_clicked));
00179   mi_top_bottom->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_changed), SkillerDebugInterface::GD_TOP_BOTTOM));
00180   mi_bottom_top->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_changed), SkillerDebugInterface::GD_BOTTOM_TOP));
00181   mi_left_right->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_changed), SkillerDebugInterface::GD_LEFT_RIGHT));
00182   mi_right_left->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_changed), SkillerDebugInterface::GD_RIGHT_LEFT));
00183   tb_graphcolored->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphcolor_toggled));
00184 #ifdef USE_PAPYRUS
00185   tb_graphsave->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::save));
00186   tb_zoomin->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_in));
00187   tb_zoomout->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_out));
00188   tb_zoomfit->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_fit));
00189   tb_zoomreset->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_reset));
00190 #else
00191   tb_graphsave->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::save));
00192   tb_graphopen->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::open));
00193   tb_zoomin->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_in));
00194   tb_zoomout->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_out));
00195   tb_zoomfit->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_fit));
00196   tb_zoomreset->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_reset));
00197   tb_graphrecord->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_recording_toggled));
00198   gda->signal_update_disabled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_update_disabled));
00199 #endif
00200 
00201 #ifdef HAVE_GCONFMM
00202   __gconf->signal_value_changed().connect(sigc::hide(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_config_changed))));
00203   on_config_changed();
00204 #endif
00205 }
00206 
00207 
00208 /** Destructor. */
00209 SkillGuiGtkWindow::~SkillGuiGtkWindow()
00210 {
00211 #ifdef HAVE_GCONFMM
00212   __gconf->remove_dir(GCONF_PREFIX);
00213 #endif
00214   __logview->set_client(NULL);
00215   __trv_plugins->set_network_client(NULL);
00216 }
00217 
00218 
00219 void
00220 SkillGuiGtkWindow::on_config_changed()
00221 {
00222 #ifdef HAVE_GCONFMM
00223   Gnome::Conf::SListHandle_ValueString l(__gconf->get_string_list(GCONF_PREFIX"/command_history"));
00224 
00225   __sks_list->clear();
00226   for (Gnome::Conf::SListHandle_ValueString::const_iterator i = l.begin(); i != l.end(); ++i) {
00227     Gtk::TreeModel::Row row  = *__sks_list->append();
00228     row[__sks_record.skillstring] = *i;    
00229   }
00230 
00231 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00232   bool continuous = __gconf->get_bool(GCONF_PREFIX"/continuous_exec");
00233   bool colored    = __gconf->get_bool(GCONF_PREFIX"/graph_colored");
00234 #else
00235   std::auto_ptr<Glib::Error> error;
00236   bool continuous = __gconf->get_bool(GCONF_PREFIX"/continuous_exec", error);
00237   bool colored    = __gconf->get_bool(GCONF_PREFIX"/graph_colored", error);
00238 #endif
00239   but_continuous->set_active(continuous);
00240   tb_graphcolored->set_active(colored);
00241 #endif
00242 }
00243 
00244 
00245 void
00246 SkillGuiGtkWindow::on_skill_changed()
00247 {
00248   Glib::ustring skill = cb_graphlist->get_active_text();
00249   if ( skill == ACTIVE_SKILL ) {
00250     skill = "ACTIVE";
00251   }
00252   SkillerDebugInterface::SetGraphMessage *sgm = new SkillerDebugInterface::SetGraphMessage(skill.c_str());
00253   __skdbg_if->msgq_enqueue(sgm);
00254 }
00255 
00256 void
00257 SkillGuiGtkWindow::on_contexec_toggled()
00258 {
00259 #ifdef HAVE_GCONFMM
00260   __gconf->set(GCONF_PREFIX"/continuous_exec", but_continuous->get_active());
00261 #endif
00262 }
00263 
00264 /** Event handler for connection button. */
00265 void
00266 SkillGuiGtkWindow::on_connection_clicked()
00267 {
00268   if ( ! connection_dispatcher.get_client()->connected() ) {
00269     ServiceChooserDialog ssd(*this, connection_dispatcher.get_client());
00270     ssd.run_and_connect();
00271   } else {
00272     connection_dispatcher.get_client()->disconnect();
00273   } 
00274 }
00275 
00276 
00277 void
00278 SkillGuiGtkWindow::on_exit_clicked()
00279 {
00280   Gtk::Main::quit();
00281 }
00282 
00283 
00284 void
00285 SkillGuiGtkWindow::on_controller_clicked()
00286 {
00287   if (__skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() &&
00288       __skiller_if->exclusive_controller() == __skiller_if->serial()) {
00289     // we are exclusive controller, release control
00290     SkillerInterface::ReleaseControlMessage *rcm = new SkillerInterface::ReleaseControlMessage();
00291     __skiller_if->msgq_enqueue(rcm);
00292   } else if (__skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() &&
00293              __skiller_if->exclusive_controller() == 0) {
00294     // there is no exclusive controller, try to acquire control
00295     SkillerInterface::AcquireControlMessage *acm = new SkillerInterface::AcquireControlMessage();
00296     __skiller_if->msgq_enqueue(acm);
00297   } else {
00298     Gtk::MessageDialog md(*this,
00299                           "Another component already acquired the exclusive "
00300                           "control for the Skiller; not acquiring exclusive control.",
00301                           /* markup */ false,
00302                           Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
00303                           /* modal */ true);
00304     md.set_title("Control Acquisition Failed");
00305     md.run();
00306   }
00307 }
00308 
00309 void
00310 SkillGuiGtkWindow::on_stop_clicked()
00311 {
00312   if ( bb && __skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() ) {
00313     SkillerInterface::StopExecMessage *sem = new SkillerInterface::StopExecMessage();
00314     __skiller_if->msgq_enqueue(sem);
00315   }
00316 }
00317 
00318 void
00319 SkillGuiGtkWindow::close_bb()
00320 {
00321   if ( bb ) {
00322     bb->unregister_listener(__skiller_ifd);
00323     bb->unregister_listener(__skdbg_ifd);
00324     bb->unregister_listener(__agdbg_ifd);
00325     delete __skiller_ifd;
00326     delete __skdbg_ifd;
00327     delete __agdbg_ifd;
00328     if ( __skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() &&
00329          (__skiller_if->exclusive_controller() == __skiller_if->serial()) ) {
00330       SkillerInterface::ReleaseControlMessage *rcm = new SkillerInterface::ReleaseControlMessage();
00331       __skiller_if->msgq_enqueue(rcm);
00332     }
00333     bb->close(__skiller_if);
00334     bb->close(__skdbg_if);
00335     bb->close(__agdbg_if);
00336     delete bb;
00337     __skiller_if = NULL;
00338     __skdbg_if = NULL;
00339     __agdbg_if = NULL;
00340     bb = NULL;
00341   }
00342 }
00343 
00344 /** Event handler for connected event. */
00345 void
00346 SkillGuiGtkWindow::on_connect()
00347 {
00348   try {
00349     if ( ! bb ) {
00350       bb           = new RemoteBlackBoard(connection_dispatcher.get_client());
00351       __skiller_if = bb->open_for_reading<SkillerInterface>("Skiller");
00352       __skdbg_if   = bb->open_for_reading<SkillerDebugInterface>("Skiller");
00353       __agdbg_if   = bb->open_for_reading<SkillerDebugInterface>("LuaAgent");
00354       on_skiller_data_changed();
00355       on_skdbg_data_changed();
00356       on_agdbg_data_changed();
00357 
00358       __skiller_ifd = new InterfaceDispatcher("Skiller IFD", __skiller_if);
00359       __skdbg_ifd   = new InterfaceDispatcher("SkillerDebug IFD", __skdbg_if);
00360       __agdbg_ifd   = new InterfaceDispatcher("LuaAgent SkillerDebug IFD", __agdbg_if);
00361       bb->register_listener(__skiller_ifd, BlackBoard::BBIL_FLAG_DATA);
00362       bb->register_listener(__skdbg_ifd, BlackBoard::BBIL_FLAG_DATA);
00363       bb->register_listener(__agdbg_ifd, BlackBoard::BBIL_FLAG_DATA);
00364       __skiller_ifd->signal_data_changed().connect(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skiller_data_changed)));
00365       __skdbg_ifd->signal_data_changed().connect(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skdbg_data_changed)));
00366       __agdbg_ifd->signal_data_changed().connect(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_agdbg_data_changed)));
00367 
00368       // always try to acquire control on connect, this may well fail, for
00369       // example if agent is running, but we don't care
00370       __skiller_if->read();
00371       if (__skiller_if->has_writer() && __skiller_if->exclusive_controller() == 0) {
00372         SkillerInterface::AcquireControlMessage *aqm = new SkillerInterface::AcquireControlMessage();
00373         __skiller_if->msgq_enqueue(aqm);
00374       }
00375       if (__skdbg_if->has_writer()) {
00376         SkillerDebugInterface::SetGraphMessage *sgm = new SkillerDebugInterface::SetGraphMessage("LIST");
00377         __skdbg_if->msgq_enqueue(sgm);
00378       }
00379     }
00380     tb_connection->set_stock_id(Gtk::Stock::DISCONNECT);
00381     __logview->set_client(connection_dispatcher.get_client());
00382 
00383     but_continuous->set_sensitive(true);
00384     tb_controller->set_sensitive(true);
00385     cbe_skillstring->set_sensitive(true);
00386 
00387     this->set_title(std::string("Skill GUI @ ") + connection_dispatcher.get_client()->get_hostname());
00388   } catch (Exception &e) {
00389     Glib::ustring message = *(e.begin());
00390     Gtk::MessageDialog md(*this, message, /* markup */ false,
00391                           Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
00392                           /* modal */ true);
00393     md.set_title("BlackBoard connection failed");
00394     md.run();
00395 
00396     close_bb();
00397     connection_dispatcher.get_client()->disconnect();
00398   }
00399 }
00400 
00401 /** Event handler for disconnected event. */
00402 void
00403 SkillGuiGtkWindow::on_disconnect()
00404 {
00405   but_continuous->set_sensitive(false);
00406   tb_controller->set_sensitive(false);
00407   cbe_skillstring->set_sensitive(false);
00408   but_exec->set_sensitive(false);
00409   but_stop->set_sensitive(false);
00410 
00411   close_bb();
00412 
00413   tb_connection->set_stock_id(Gtk::Stock::CONNECT);
00414 #ifdef USE_PAPYRUS
00415   pvp_graph->queue_draw();
00416 #endif
00417   __logview->set_client(NULL);
00418 
00419   this->set_title("Skill GUI");
00420 }
00421 
00422 
00423 void
00424 SkillGuiGtkWindow::on_exec_clicked()
00425 {
00426   Glib::ustring sks = "";
00427   if ( cbe_skillstring->get_active_row_number() == -1 ) {
00428     Gtk::Entry *entry = cbe_skillstring->get_entry();
00429     sks = entry->get_text();
00430   } else {
00431     Gtk::TreeModel::Row row = *cbe_skillstring->get_active();
00432     row.get_value(cbe_skillstring->get_text_column(), sks);
00433   }
00434 
00435   if ( sks != "" ) {
00436     __throbber->set_timeout(80);
00437 
00438     if (__skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() &&
00439         __skiller_if->exclusive_controller() == __skiller_if->serial()) {
00440 
00441       if ( but_continuous->get_active() ) {
00442         SkillerInterface::ExecSkillContinuousMessage *escm = new SkillerInterface::ExecSkillContinuousMessage(sks.c_str());
00443         __skiller_if->msgq_enqueue(escm);
00444       } else {
00445         SkillerInterface::ExecSkillMessage *esm = new SkillerInterface::ExecSkillMessage(sks.c_str());
00446         __skiller_if->msgq_enqueue(esm);
00447       }
00448 
00449       Gtk::TreeModel::Children children = __sks_list->children();
00450       bool ok = true;
00451       if ( ! children.empty() ) {
00452         size_t num = 0;
00453         Gtk::TreeIter i = children.begin();
00454         while (ok && (i != children.end())) {
00455           if ( num >= 9 ) {
00456             i = __sks_list->erase(i);
00457         } else {
00458             Gtk::TreeModel::Row row = *i;
00459             ok = (row[__sks_record.skillstring] != sks);
00460             ++num;
00461             ++i;
00462           }
00463         }
00464       }
00465       if (ok) {
00466         Gtk::TreeModel::Row row  = *__sks_list->prepend();
00467         row[__sks_record.skillstring] = sks;
00468         
00469         std::list<Glib::ustring> l;
00470         for (Gtk::TreeIter i = children.begin(); i != children.end(); ++i) {
00471           Gtk::TreeModel::Row row = *i;
00472           l.push_back(row[__sks_record.skillstring]);
00473         }
00474 
00475 #ifdef HAVE_GCONFMM
00476         __gconf->set_string_list(GCONF_PREFIX"/command_history", l);
00477 #endif
00478       }
00479     } else {
00480       Gtk::MessageDialog md(*this, "The exclusive control over the skiller has "
00481                             "not been acquired yet and skills cannot be executed",
00482                             /* markup */ false,
00483                             Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
00484                             /* modal */ true);
00485       md.set_title("Skill Execution Failure");
00486       md.run();
00487     }
00488   }
00489 }
00490 
00491 
00492 void
00493 SkillGuiGtkWindow::on_skiller_data_changed()
00494 {
00495   try {
00496     __skiller_if->read();
00497 
00498     switch (__skiller_if->status()) {
00499     case SkillerInterface::S_INACTIVE:
00500       __throbber->stop_anim();
00501       lab_status->set_text("S_INACTIVE");
00502       break;
00503     case SkillerInterface::S_FINAL:
00504       __throbber->stop_anim();
00505       __throbber->set_stock(Gtk::Stock::APPLY);
00506       lab_status->set_text("S_FINAL");
00507       break;
00508     case SkillerInterface::S_RUNNING:
00509       __throbber->start_anim();
00510       lab_status->set_text("S_RUNNING");
00511       break;
00512     case SkillerInterface::S_FAILED:
00513       __throbber->stop_anim();
00514       __throbber->set_stock(Gtk::Stock::DIALOG_WARNING);
00515       lab_status->set_text("S_FAILED");
00516       break;
00517     }
00518 
00519     lab_skillstring->set_text(__skiller_if->skill_string());
00520     lab_error->set_text(__skiller_if->error());
00521 #if GTKMM_MAJOR_VERSION > 2 || ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12 )
00522     lab_skillstring->set_tooltip_text(__skiller_if->skill_string());
00523     lab_error->set_tooltip_text(__skiller_if->error());
00524 #endif
00525     lab_continuous->set_text(__skiller_if->is_continuous() ? "Yes" : "No");
00526     lab_alive->set_text(__skiller_if->has_writer() ? "Yes" : "No");
00527 
00528     if ( __skiller_if->exclusive_controller() == __skiller_if->serial() ) {
00529       if ( tb_controller->get_stock_id() == Gtk::Stock::NO.id ) {
00530         tb_controller->set_stock_id(Gtk::Stock::YES);
00531 #if GTKMM_MAJOR_VERSION > 2 || ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12 )
00532         tb_controller->set_tooltip_text("Release exclusive control");
00533 #endif
00534       }
00535       but_exec->set_sensitive(true);
00536       but_stop->set_sensitive(true);
00537     } else {
00538       if ( tb_controller->get_stock_id() == Gtk::Stock::YES.id ) {
00539         tb_controller->set_stock_id(Gtk::Stock::NO);
00540 #if GTKMM_MAJOR_VERSION > 2 || ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12 )
00541         tb_controller->set_tooltip_text("Gain exclusive control");
00542 #endif
00543       }
00544       but_exec->set_sensitive(false);
00545       but_stop->set_sensitive(false);
00546     }
00547 
00548 
00549   } catch (Exception &e) {
00550     __throbber->stop_anim();
00551   }
00552 }
00553 
00554 
00555 void
00556 SkillGuiGtkWindow::on_skdbg_data_changed()
00557 {
00558   if (tb_skiller->get_active() && __skdbg_if) {
00559     try {
00560       __skdbg_if->read();
00561 
00562       if (strcmp(__skdbg_if->graph_fsm(), "LIST") == 0) {
00563         Glib::ustring list = __skdbg_if->graph();
00564         cb_graphlist->clear_items();
00565         cb_graphlist->append_text(ACTIVE_SKILL);
00566         cb_graphlist->set_active_text(ACTIVE_SKILL);
00567 #if GLIBMM_MAJOR_VERSION > 2 || ( GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 14 )
00568         Glib::RefPtr<Glib::Regex> regex = Glib::Regex::create("\n");
00569         std::list<std::string> skills = regex->split(list);
00570         for (std::list<std::string>::iterator i = skills.begin(); i != skills.end(); ++i) {
00571           if (*i != "")  cb_graphlist->append_text(*i);
00572         }
00573 #endif
00574         if (__skdbg_if->has_writer()) {
00575           SkillerDebugInterface::SetGraphMessage *sgm = new SkillerDebugInterface::SetGraphMessage("ACTIVE");
00576           __skdbg_if->msgq_enqueue(sgm);
00577         }
00578       } else {
00579 #ifdef USE_PAPYRUS
00580         pvp_graph->set_graph_fsm(__skdbg_if->graph_fsm());
00581         pvp_graph->set_graph(__skdbg_if->graph());
00582         pvp_graph->render();
00583 #else
00584         gda->set_graph_fsm(__skdbg_if->graph_fsm());
00585         gda->set_graph(__skdbg_if->graph());
00586 #endif
00587       }
00588 
00589       switch (__skdbg_if->graph_dir()) {
00590       case SkillerDebugInterface::GD_TOP_BOTTOM:
00591         tb_graphdir->set_stock_id(Gtk::Stock::GO_DOWN); break;
00592       case SkillerDebugInterface::GD_BOTTOM_TOP:
00593         tb_graphdir->set_stock_id(Gtk::Stock::GO_UP); break;
00594       case SkillerDebugInterface::GD_LEFT_RIGHT:
00595         tb_graphdir->set_stock_id(Gtk::Stock::GO_FORWARD); break;
00596       case SkillerDebugInterface::GD_RIGHT_LEFT:
00597         tb_graphdir->set_stock_id(Gtk::Stock::GO_BACK); break;
00598       }
00599     } catch (Exception &e) {
00600       // ignored
00601     }
00602   }
00603 }
00604 
00605 
00606 void
00607 SkillGuiGtkWindow::on_agdbg_data_changed()
00608 {
00609   if (tb_agent->get_active() && __agdbg_if) {
00610     try {
00611       __agdbg_if->read();
00612 #ifdef USE_PAPYRUS
00613       pvp_graph->set_graph_fsm(__agdbg_if->graph_fsm());
00614       pvp_graph->set_graph(__agdbg_if->graph());
00615       pvp_graph->render();
00616 #else
00617       gda->set_graph_fsm(__agdbg_if->graph_fsm());
00618       gda->set_graph(__agdbg_if->graph());
00619 #endif
00620 
00621       switch (__agdbg_if->graph_dir()) {
00622       case SkillerDebugInterface::GD_TOP_BOTTOM:
00623         tb_graphdir->set_stock_id(Gtk::Stock::GO_DOWN); break;
00624       case SkillerDebugInterface::GD_BOTTOM_TOP:
00625         tb_graphdir->set_stock_id(Gtk::Stock::GO_UP); break;
00626       case SkillerDebugInterface::GD_LEFT_RIGHT:
00627         tb_graphdir->set_stock_id(Gtk::Stock::GO_FORWARD); break;
00628       case SkillerDebugInterface::GD_RIGHT_LEFT:
00629         tb_graphdir->set_stock_id(Gtk::Stock::GO_BACK); break;
00630       }
00631     } catch (Exception &e) {
00632       // ignored
00633     }
00634   }
00635 }
00636 
00637 
00638 void
00639 SkillGuiGtkWindow::on_graphupd_clicked()
00640 {
00641 #ifdef USE_PAPYRUS
00642   if ( pvp_graph->get_update_graph() ) {
00643     pvp_graph->set_update_graph(false);
00644     tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP);
00645   } else {
00646     pvp_graph->set_update_graph(true);
00647     tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_PLAY);
00648     pvp_graph->render();
00649   }
00650 #else
00651   if ( gda->get_update_graph() ) {
00652     gda->set_update_graph(false);
00653     tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP);
00654   } else {
00655     gda->set_update_graph(true);
00656     tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_PLAY);
00657   }
00658 #endif
00659 }
00660 
00661 
00662 void
00663 SkillGuiGtkWindow::on_graphdir_clicked()
00664 {
00665   SkillerDebugInterface *iface = __skdbg_if;
00666   if (tb_agent->get_active()) {
00667     iface = __agdbg_if;
00668   }
00669 
00670   Glib::ustring stockid = tb_graphdir->get_stock_id();
00671   if (stockid == Gtk::Stock::GO_DOWN.id) {
00672     send_graphdir_message(iface, SkillerDebugInterface::GD_BOTTOM_TOP);
00673   } else if (stockid == Gtk::Stock::GO_UP.id) {
00674     send_graphdir_message(iface, SkillerDebugInterface::GD_LEFT_RIGHT);
00675   } else if (stockid == Gtk::Stock::GO_FORWARD.id) {
00676     send_graphdir_message(iface, SkillerDebugInterface::GD_RIGHT_LEFT);
00677   } else if (stockid == Gtk::Stock::GO_BACK.id) {
00678     send_graphdir_message(iface, SkillerDebugInterface::GD_TOP_BOTTOM);
00679   }
00680 }
00681 
00682 void
00683 SkillGuiGtkWindow::send_graphdir_message(SkillerDebugInterface *iface,
00684                                          SkillerDebugInterface::GraphDirectionEnum gd)
00685 {
00686   try {
00687     if (iface) {
00688       SkillerDebugInterface::SetGraphDirectionMessage *m;
00689       m = new SkillerDebugInterface::SetGraphDirectionMessage(gd);
00690       iface->msgq_enqueue(m);
00691     } else {
00692       throw Exception("Not connected to Fawkes.");
00693     }
00694   } catch (Exception &e) {
00695     Gtk::MessageDialog md(*this,
00696                           Glib::ustring("Setting graph direction failed: ") + e.what(),
00697                           /* markup */ false,
00698                           Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
00699                           /* modal */ true);
00700     md.set_title("Communication Failure");
00701     md.run();
00702   }
00703 }
00704 
00705 void
00706 SkillGuiGtkWindow::on_graphdir_changed(SkillerDebugInterface::GraphDirectionEnum gd)
00707 {
00708   if (tb_agent->get_active()) {
00709     send_graphdir_message(__agdbg_if, gd);
00710   } else {
00711     send_graphdir_message(__skdbg_if, gd);
00712   }
00713 }
00714 
00715 
00716 void
00717 SkillGuiGtkWindow::on_graphcolor_toggled()
00718 {
00719 #ifdef HAVE_GCONFMM
00720   __gconf->set(GCONF_PREFIX"/graph_colored", tb_graphcolored->get_active());
00721 #endif
00722 
00723   SkillerDebugInterface *iface = __skdbg_if;
00724   if (tb_agent->get_active()) {
00725     iface = __agdbg_if;
00726   }
00727 
00728   try {
00729     if (iface) {
00730       SkillerDebugInterface::SetGraphColoredMessage *m;
00731       m = new SkillerDebugInterface::SetGraphColoredMessage(tb_graphcolored->get_active());
00732       iface->msgq_enqueue(m);
00733     } else {
00734       throw Exception("Not connected to Fawkes.");
00735     }
00736   } catch (Exception &e) {
00737     /* Ignore for now, causes error message on startup
00738     Gtk::MessageDialog md(*this,
00739                           Glib::ustring("Setting graph color failed: ") + e.what(),
00740                           / markup / false,
00741                           Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
00742                           / modal / true);
00743     md.set_title("Communication Failure");
00744     md.run();
00745     */
00746   }
00747 }
00748 
00749 
00750 SkillGuiGtkWindow::SkillStringRecord::SkillStringRecord()
00751 {
00752   add(skillstring);
00753 }
00754 
00755 
00756 void
00757 SkillGuiGtkWindow::on_update_disabled()
00758 {
00759 #ifdef USE_PAPYRUS
00760 #else
00761   tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP);
00762 #endif
00763 }
00764 
00765 
00766 void
00767 SkillGuiGtkWindow::on_recording_toggled()
00768 {
00769 #ifdef USE_PAPYRUS
00770 #else
00771   bool active = tb_graphrecord->get_active();
00772   if (gda->set_recording(active) != active) {
00773     tb_graphrecord->set_active(!active);
00774   }
00775 #endif
00776 }