Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * worldinfo_viewer.cpp - World Info Viewer 00004 * 00005 * Created: Wed April 09 20:13:08 2008 00006 * Copyright 2008 Daniel Beck 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 "worldinfo_viewer.h" 00024 #include "field_view.h" 00025 00026 #include <worldinfo_utils/data_container.h> 00027 #include <blackboard/remote.h> 00028 00029 #include <vector> 00030 #include <map> 00031 #include <string> 00032 #include <cstdio> 00033 #include <cstring> 00034 00035 using namespace std; 00036 using namespace fawkes; 00037 00038 00039 /** @class WorldInfoViewer <tools/worldinfo_viewer/worldinfo_viewer.h> 00040 * Main class of the WorldInfoViewer application. 00041 * @author Daniel Beck 00042 */ 00043 00044 00045 /** Constructor. 00046 * @param builder Gtk Builder 00047 * @param data_container pointer to the central instance of the 00048 * WorldInfoDataContainer 00049 */ 00050 WorldInfoViewer::WorldInfoViewer(Glib::RefPtr<Gtk::Builder> builder, 00051 WorldInfoDataContainer* data_container ) 00052 { 00053 builder->get_widget("wndMain", m_wnd_main); 00054 builder->get_widget("vbxField", m_vbx_field); 00055 builder->get_widget("trvRobots", m_trv_robots); 00056 builder->get_widget("stbStatus", m_stb_status); 00057 00058 m_field_view = new FieldView( data_container, true, true, false ); 00059 m_vbx_field->pack_start( *m_field_view ); 00060 m_field_view->show(); 00061 00062 m_robots_list = Gtk::ListStore::create( m_robot_record ); 00063 m_trv_robots->set_model( m_robots_list ); 00064 m_trv_robots->append_column( "Name", m_robot_record.hostname ); 00065 m_trv_robots->append_column_editable( "Pose", m_robot_record.show_pose ); 00066 m_trv_robots->append_column_editable( "Ball", m_robot_record.show_ball ); 00067 m_trv_robots->append_column_editable( "Opponents", m_robot_record.show_opponents ); 00068 00069 Gtk::CellRendererToggle* renderer; 00070 renderer = dynamic_cast< Gtk::CellRendererToggle* >( m_trv_robots->get_column_cell_renderer(1) ); 00071 renderer->signal_toggled().connect( sigc::mem_fun( *this, 00072 &WorldInfoViewer::on_show_pose_toggled ) ); 00073 renderer = dynamic_cast< Gtk::CellRendererToggle* >( m_trv_robots->get_column_cell_renderer(2) ); 00074 renderer->signal_toggled().connect( sigc::mem_fun( *this, 00075 &WorldInfoViewer::on_show_ball_toggled ) ); 00076 renderer = dynamic_cast< Gtk::CellRendererToggle* >( m_trv_robots->get_column_cell_renderer(3) ); 00077 renderer->signal_toggled().connect( sigc::mem_fun( *this, 00078 &WorldInfoViewer::on_show_opponents_toggled ) ); 00079 00080 m_data_container = data_container; 00081 00082 m_stb_message_id = m_stb_status->push( "No game state information available." ); 00083 00084 // create timer 00085 sigc::connection conn = 00086 Glib::signal_timeout().connect( sigc::mem_fun( *this, &WorldInfoViewer::update ), 200 ); 00087 } 00088 00089 00090 /** Destructor. */ 00091 WorldInfoViewer::~WorldInfoViewer() 00092 { 00093 delete m_field_view; 00094 delete m_wnd_main; 00095 } 00096 00097 00098 /** Obtain the main window of the application. 00099 * @return reference to the main window 00100 */ 00101 Gtk::Window& 00102 WorldInfoViewer::get_window() const 00103 { 00104 return *m_wnd_main; 00105 } 00106 00107 00108 /** Update the GUI. 00109 * @return always true 00110 */ 00111 bool 00112 WorldInfoViewer::update() 00113 { 00114 bool robot_removed = false; 00115 00116 if ( m_data_container->check_timeout() ) 00117 { 00118 robot_removed = true; 00119 list<string> timedout_hosts = m_data_container->get_timedout_hosts(); 00120 00121 #ifdef DEBUG_PRINT 00122 printf( "Removing %zu timed out host.\n", timedout_hosts.size() ); 00123 #endif /* DEBUG_PRINT */ 00124 00125 // remove timed out hosts 00126 for ( list<string>::iterator hit = timedout_hosts.begin(); 00127 hit != timedout_hosts.end(); 00128 ++hit ) 00129 { 00130 m_field_view->remove_host( Glib::ustring( *hit ) ); 00131 00132 Gtk::TreeModel::Children children = m_robots_list->children(); 00133 Gtk::TreeModel::iterator cit = children.begin(); 00134 while ( cit != children.end() ) 00135 { 00136 Gtk::TreeModel::Row row = *cit; 00137 if ( Glib::ustring( *hit ) == row[ m_robot_record.fqdn ] ) 00138 { cit = m_robots_list->erase( cit ); } 00139 else 00140 { ++cit; } 00141 } 00142 } 00143 } 00144 00145 // return if no new data is available 00146 if ( !m_data_container->new_data_available() ) 00147 { 00148 if ( robot_removed ) 00149 { m_field_view->queue_draw(); } 00150 return true; 00151 } 00152 00153 list<string> hosts = m_data_container->get_hosts(); 00154 00155 // check that all hosts are in the treeview 00156 for ( list<string>::iterator hit = hosts.begin(); 00157 hit != hosts.end(); 00158 ++hit ) 00159 { 00160 bool found = false; 00161 00162 Gtk::TreeModel::Children children = m_robots_list->children(); 00163 for ( Gtk::TreeModel::iterator i = children.begin(); 00164 i != children.end(); 00165 ++i ) 00166 { 00167 Gtk::TreeModel::Row row = *i; 00168 if ( Glib::ustring( *hit ) == row[ m_robot_record.fqdn ] ) 00169 { 00170 found = true; 00171 break; 00172 } 00173 } 00174 00175 if ( !found ) 00176 { 00177 char* fqdn; 00178 char* hostname; 00179 char delim ='.'; 00180 Glib::ustring fqdn_str = Glib::ustring( *hit ); 00181 00182 fqdn = strdup( hit->c_str() ); 00183 hostname = strtok( fqdn, &delim ); 00184 int i = atoi( hostname ); 00185 00186 Gtk::TreeModel::Row row = *m_robots_list->append(); 00187 00188 if ( 0 == i ) /* fqdn is not an IP address */ 00189 { row[ m_robot_record.hostname ] = Glib::ustring( hostname ); } 00190 else 00191 { row[ m_robot_record.hostname ] = fqdn_str; } 00192 row[ m_robot_record.fqdn ] = fqdn_str; 00193 row[ m_robot_record.show_pose ] = m_field_view->toggle_show_pose( fqdn_str ); 00194 row[ m_robot_record.show_ball ] = m_field_view->toggle_show_ball( fqdn_str ); 00195 row[ m_robot_record.show_opponents ] = m_field_view->toggle_show_opponents( fqdn_str ); 00196 00197 free(fqdn); 00198 } 00199 } 00200 00201 m_field_view->queue_draw(); 00202 00203 return true; 00204 } 00205 00206 /** Call this method whenever the game state changes. */ 00207 void 00208 WorldInfoViewer::gamestate_changed() 00209 { 00210 char* status_string; 00211 if ( asprintf( &status_string, 00212 "Team color: %s Goal color: %s Mode: %s Score: %d:%d Half: %s", 00213 m_data_container->get_own_team_color_string().c_str(), 00214 m_data_container->get_own_goal_color_string().c_str(), 00215 m_data_container->get_game_state_string().c_str(), 00216 m_data_container->get_own_score(), 00217 m_data_container->get_other_score(), 00218 m_data_container->get_half_string().c_str() ) != -1 ) 00219 { 00220 m_stb_status->remove_message(m_stb_message_id); 00221 m_stb_message_id = m_stb_status->push( Glib::ustring(status_string) ); 00222 00223 free(status_string); 00224 } 00225 } 00226 00227 void 00228 WorldInfoViewer::on_show_pose_toggled( const Glib::ustring& path ) 00229 { 00230 Gtk::TreeModel::Row row = *m_robots_list->get_iter( path ); 00231 Glib::ustring fqdn = row[ m_robot_record.fqdn ]; 00232 00233 row[ m_robot_record.show_pose ] = m_field_view->toggle_show_pose( fqdn ); 00234 00235 m_field_view->queue_draw(); 00236 } 00237 00238 void 00239 WorldInfoViewer::on_show_ball_toggled( const Glib::ustring& path ) 00240 { 00241 Gtk::TreeModel::Row row = *m_robots_list->get_iter( path ); 00242 Glib::ustring fqdn = row[ m_robot_record.fqdn ]; 00243 00244 row[ m_robot_record.show_ball ] = m_field_view->toggle_show_ball( fqdn ); 00245 00246 m_field_view->queue_draw(); 00247 } 00248 00249 void 00250 WorldInfoViewer::on_show_opponents_toggled( const Glib::ustring& path ) 00251 { 00252 Gtk::TreeModel::Row row = *m_robots_list->get_iter( path ); 00253 Glib::ustring fqdn = row[ m_robot_record.fqdn ]; 00254 00255 row[ m_robot_record.show_opponents ] = m_field_view->toggle_show_opponents( fqdn ); 00256 00257 m_field_view->queue_draw(); 00258 }