Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
worldinfo_viewer.cpp
1 
2 /***************************************************************************
3  * worldinfo_viewer.cpp - World Info Viewer
4  *
5  * Created: Wed April 09 20:13:08 2008
6  * Copyright 2008 Daniel Beck
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 "worldinfo_viewer.h"
24 #include "field_view.h"
25 
26 #include <worldinfo_utils/data_container.h>
27 #include <blackboard/remote.h>
28 
29 #include <vector>
30 #include <map>
31 #include <string>
32 #include <cstdio>
33 #include <cstring>
34 
35 using namespace std;
36 using namespace fawkes;
37 
38 
39 /** @class WorldInfoViewer <tools/worldinfo_viewer/worldinfo_viewer.h>
40  * Main class of the WorldInfoViewer application.
41  * @author Daniel Beck
42  */
43 
44 
45 /** Constructor.
46  * @param builder Gtk Builder
47  * @param data_container pointer to the central instance of the
48  * WorldInfoDataContainer
49  */
50 WorldInfoViewer::WorldInfoViewer(Glib::RefPtr<Gtk::Builder> builder,
51  WorldInfoDataContainer* data_container )
52 {
53  builder->get_widget("wndMain", m_wnd_main);
54  builder->get_widget("vbxField", m_vbx_field);
55  builder->get_widget("trvRobots", m_trv_robots);
56  builder->get_widget("stbStatus", m_stb_status);
57 
58  m_field_view = new FieldView( data_container, true, true, false );
59  m_vbx_field->pack_start( *m_field_view );
60  m_field_view->show();
61 
62  m_robots_list = Gtk::ListStore::create( m_robot_record );
63  m_trv_robots->set_model( m_robots_list );
64  m_trv_robots->append_column( "Name", m_robot_record.hostname );
65  m_trv_robots->append_column_editable( "Pose", m_robot_record.show_pose );
66  m_trv_robots->append_column_editable( "Ball", m_robot_record.show_ball );
67  m_trv_robots->append_column_editable( "Opponents", m_robot_record.show_opponents );
68 
69  Gtk::CellRendererToggle* renderer;
70  renderer = dynamic_cast< Gtk::CellRendererToggle* >( m_trv_robots->get_column_cell_renderer(1) );
71  renderer->signal_toggled().connect( sigc::mem_fun( *this,
72  &WorldInfoViewer::on_show_pose_toggled ) );
73  renderer = dynamic_cast< Gtk::CellRendererToggle* >( m_trv_robots->get_column_cell_renderer(2) );
74  renderer->signal_toggled().connect( sigc::mem_fun( *this,
75  &WorldInfoViewer::on_show_ball_toggled ) );
76  renderer = dynamic_cast< Gtk::CellRendererToggle* >( m_trv_robots->get_column_cell_renderer(3) );
77  renderer->signal_toggled().connect( sigc::mem_fun( *this,
78  &WorldInfoViewer::on_show_opponents_toggled ) );
79 
80  m_data_container = data_container;
81 
82  m_stb_message_id = m_stb_status->push( "No game state information available." );
83 
84  // create timer
85  sigc::connection conn =
86  Glib::signal_timeout().connect( sigc::mem_fun( *this, &WorldInfoViewer::update ), 200 );
87 }
88 
89 
90 /** Destructor. */
92 {
93  delete m_field_view;
94  delete m_wnd_main;
95 }
96 
97 
98 /** Obtain the main window of the application.
99  * @return reference to the main window
100  */
101 Gtk::Window&
103 {
104  return *m_wnd_main;
105 }
106 
107 
108 /** Update the GUI.
109  * @return always true
110  */
111 bool
113 {
114  bool robot_removed = false;
115 
116  if ( m_data_container->check_timeout() )
117  {
118  robot_removed = true;
119  list<string> timedout_hosts = m_data_container->get_timedout_hosts();
120 
121 #ifdef DEBUG_PRINT
122  printf( "Removing %zu timed out host.\n", timedout_hosts.size() );
123 #endif /* DEBUG_PRINT */
124 
125  // remove timed out hosts
126  for ( list<string>::iterator hit = timedout_hosts.begin();
127  hit != timedout_hosts.end();
128  ++hit )
129  {
130  m_field_view->remove_host( Glib::ustring( *hit ) );
131 
132  Gtk::TreeModel::Children children = m_robots_list->children();
133  Gtk::TreeModel::iterator cit = children.begin();
134  while ( cit != children.end() )
135  {
136  Gtk::TreeModel::Row row = *cit;
137  if ( Glib::ustring( *hit ) == row[ m_robot_record.fqdn ] )
138  { cit = m_robots_list->erase( cit ); }
139  else
140  { ++cit; }
141  }
142  }
143  }
144 
145  // return if no new data is available
146  if ( !m_data_container->new_data_available() )
147  {
148  if ( robot_removed )
149  { m_field_view->queue_draw(); }
150  return true;
151  }
152 
153  list<string> hosts = m_data_container->get_hosts();
154 
155  // check that all hosts are in the treeview
156  for ( list<string>::iterator hit = hosts.begin();
157  hit != hosts.end();
158  ++hit )
159  {
160  bool found = false;
161 
162  Gtk::TreeModel::Children children = m_robots_list->children();
163  for ( Gtk::TreeModel::iterator i = children.begin();
164  i != children.end();
165  ++i )
166  {
167  Gtk::TreeModel::Row row = *i;
168  if ( Glib::ustring( *hit ) == row[ m_robot_record.fqdn ] )
169  {
170  found = true;
171  break;
172  }
173  }
174 
175  if ( !found )
176  {
177  char* fqdn;
178  char* hostname;
179  char delim ='.';
180  Glib::ustring fqdn_str = Glib::ustring( *hit );
181 
182  fqdn = strdup( hit->c_str() );
183  hostname = strtok( fqdn, &delim );
184  int i = atoi( hostname );
185 
186  Gtk::TreeModel::Row row = *m_robots_list->append();
187 
188  if ( 0 == i ) /* fqdn is not an IP address */
189  { row[ m_robot_record.hostname ] = Glib::ustring( hostname ); }
190  else
191  { row[ m_robot_record.hostname ] = fqdn_str; }
192  row[ m_robot_record.fqdn ] = fqdn_str;
193  row[ m_robot_record.show_pose ] = m_field_view->toggle_show_pose( fqdn_str );
194  row[ m_robot_record.show_ball ] = m_field_view->toggle_show_ball( fqdn_str );
195  row[ m_robot_record.show_opponents ] = m_field_view->toggle_show_opponents( fqdn_str );
196 
197  free(fqdn);
198  }
199  }
200 
201  m_field_view->queue_draw();
202 
203  return true;
204 }
205 
206 /** Call this method whenever the game state changes. */
207 void
209 {
210  char* status_string;
211  if ( asprintf( &status_string,
212  "Team color: %s Goal color: %s Mode: %s Score: %d:%d Half: %s",
213  m_data_container->get_own_team_color_string().c_str(),
214  m_data_container->get_own_goal_color_string().c_str(),
215  m_data_container->get_game_state_string().c_str(),
216  m_data_container->get_own_score(),
217  m_data_container->get_other_score(),
218  m_data_container->get_half_string().c_str() ) != -1 )
219  {
220  m_stb_status->remove_message(m_stb_message_id);
221  m_stb_message_id = m_stb_status->push( Glib::ustring(status_string) );
222 
223  free(status_string);
224  }
225 }
226 
227 void
228 WorldInfoViewer::on_show_pose_toggled( const Glib::ustring& path )
229 {
230  Gtk::TreeModel::Row row = *m_robots_list->get_iter( path );
231  Glib::ustring fqdn = row[ m_robot_record.fqdn ];
232 
233  row[ m_robot_record.show_pose ] = m_field_view->toggle_show_pose( fqdn );
234 
235  m_field_view->queue_draw();
236 }
237 
238 void
239 WorldInfoViewer::on_show_ball_toggled( const Glib::ustring& path )
240 {
241  Gtk::TreeModel::Row row = *m_robots_list->get_iter( path );
242  Glib::ustring fqdn = row[ m_robot_record.fqdn ];
243 
244  row[ m_robot_record.show_ball ] = m_field_view->toggle_show_ball( fqdn );
245 
246  m_field_view->queue_draw();
247 }
248 
249 void
250 WorldInfoViewer::on_show_opponents_toggled( const Glib::ustring& path )
251 {
252  Gtk::TreeModel::Row row = *m_robots_list->get_iter( path );
253  Glib::ustring fqdn = row[ m_robot_record.fqdn ];
254 
255  row[ m_robot_record.show_opponents ] = m_field_view->toggle_show_opponents( fqdn );
256 
257  m_field_view->queue_draw();
258 }
Data container to store and exchange worldinfo data.
Gtk::Window & get_window() const
Obtain the main window of the application.
virtual ~WorldInfoViewer()
Destructor.
void gamestate_changed()
Call this method whenever the game state changes.
WorldInfoViewer(Glib::RefPtr< Gtk::Builder > builder, fawkes::WorldInfoDataContainer *data_container)
Constructor.
Drawing widget that draws an (MSL-) soccer field with robots, opponents, and balls.
Definition: field_view.h:33
bool update()
Update the GUI.