evorobotviewer.cpp
1 /********************************************************************************
2  * FARSA Experiments Library *
3  * Copyright (C) 2007-2012 *
4  * Stefano Nolfi <stefano.nolfi@istc.cnr.it> *
5  * Onofrio Gigliotta <onofrio.gigliotta@istc.cnr.it> *
6  * Gianluca Massera <emmegian@yahoo.it> *
7  * Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it> *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the Free Software *
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
22  ********************************************************************************/
23 
24 #include "evorobotviewer.h"
25 #include "abstracttest.h"
26 #include "tests.h"
27 #include "total99resources.h"
28 #include <QGridLayout>
29 #include <QPushButton>
30 #include <QCheckBox>
31 #include <QFileDialog>
32 #include <QVBoxLayout>
33 #include <QDir>
34 #include <QFileInfo>
35 #include <QFile>
36 #include <QEvent>
37 #include <QCoreApplication>
38 #include <QTimer>
39 #include <QSlider>
40 #include <cmath>
41 
42 using namespace qglviewer;
43 
44 // All the suff below is to avoid warnings on Windows about the use of unsafe
45 // functions. This should be only a temporary workaround, the solution is stop
46 // using C string and file functions...
47 #if defined(_MSC_VER)
48  #pragma warning(push)
49  #pragma warning(disable:4996)
50 #endif
51 
52 namespace farsa {
53 
54 EvoRobotViewer::EvoRobotViewer( EvoRobotComponent* component )
56  evorobot = component;
57  ga = evorobot->getGA();
59 
60  // Declaring which resources we will need to use
61  usableResources(QStringList() << "world" << "experiment");
62 
63  QTimer* timer = new QTimer(this);
64  timer->setInterval( 40 );
65  timer->setSingleShot( false );
66  timer->start();
67 
68  // !! DO NOT CONNECT TO THE advanced SIGNAL to update the renderworld becuase that signals may be
69  // emitted so fast that the GUI will freeze !!
70  //connect( world, SIGNAL(advanced()), this, SLOT(onWorldAdvance()), Qt::QueuedConnection );
71  connect( timer, SIGNAL(timeout()), this, SLOT(onWorldAdvance()) );
72 
73  // Global connections
74  ResourcesLocker locker(this);
75  connect( evorobot, SIGNAL(actionFinished()), this, SLOT(onActionFinished()) );
76 }
77 
79 {
80  // Nothing to do
81  // --- All objects are destroyed in others parts because none of them are owend by this object
82 }
83 
84 void EvoRobotViewer::fillActionsMenu( QMenu* actionsMenu ) {
85  actionsMenu->addAction( "Evolve", evorobot, SLOT(evolve()) );
86  actionsMenu->addAction( "Stop", evorobot, SLOT(stop()) );
87 }
88 
89 QList<ParameterSettableUIViewer> EvoRobotViewer::getViewers( QWidget* parent, Qt::WindowFlags flags ) {
90  QList<ParameterSettableUIViewer> viewsList;
91  viewsList.append( evogaControls( parent, flags ) );
92 // viewsList.append( icubview( parent, flags ) );
93  viewsList.append( fitview( parent, flags ) );
94  viewsList.append( statview( parent, flags ) );
95  viewsList.append( renderWorld( parent, flags ) );
96  //--- check if there are some special view for the testing actions
97  QStringList testsList = AvailableTestList::getList();
98  for (int i = 0; i < testsList.size(); i++) {
99  TestIndividual* testIndividual = dynamic_cast<TestIndividual*>(AvailableTestList::getTest(testsList[i]));
100  if ( testIndividual ) {
101  viewsList.append( testIndividualUI( testIndividual, parent, flags ) );
102  }
103  }
104  return viewsList;
105 }
106 
107 void EvoRobotViewer::addAdditionalMenus( QMenuBar* menuBar ) {
108  QMenu* testMenu = menuBar->addMenu( "Tests" );
109  QStringList testsList = AvailableTestList::getList();
110  for (int i = 0; i < testsList.size(); i++) {
111  AbstractTest* test = AvailableTestList::getTest(testsList[i]);
112  QAction* action = testMenu->addAction( test->menuText(), evorobot, SLOT(runTestFromQAction()) );
113  action->setData( QVariant(testsList[i]) );
114  action->setToolTip( test->tooltip() );
115  action->setIcon( QIcon( test->iconFilename() ) );
116  }
117 }
118 
119 ParameterSettableUIViewer EvoRobotViewer::renderWorld( QWidget* parent, Qt::WindowFlags flags )
120 {
121  // Creating the wrapper class for RenderWorld and sharing resources
122  renderworldwrapper = new RenderWorldWrapperWidget(parent, flags);
123  renderworldwrapper->shareResourcesWith(this);
124 
125  return ParameterSettableUIViewer(renderworldwrapper, "RenderWorld");
126 }
127 
128 ParameterSettableUIViewer EvoRobotViewer::evogaControls( QWidget* parent, Qt::WindowFlags flags ) {
129  QWidget* widget = new QWidget( parent, flags );
130  QGridLayout* lay = new QGridLayout( widget );
131  //lay->setContentsMargins(0,0,0,0);
132 
133  // --- visualizzaione del trial corrente, e step corrente
134  infoEvoga = new QLabel( "Information", widget );
135  infoEvoga->setStyleSheet( "QLabel { font: bold normal large \"Courier\" }" );
136  lay->addWidget( infoEvoga, 0, 0, 1, 2 );
137 
138  QPushButton* bt = new QPushButton( "Do Step", widget );
139  bt->setAutoRepeat(true);
140  bt->setEnabled( false );
141  connect( bt, SIGNAL(clicked(bool)), ga, SLOT(doNextStep()) );
142 
143  QCheckBox* cb = new QCheckBox( "Step by Step Mode", widget );
144  connect( cb, SIGNAL(clicked(bool)), ga, SLOT(enableStepByStep(bool)) );
145  connect( cb, SIGNAL(clicked(bool)), bt, SLOT(setEnabled(bool)) );
146 
147  lay->addWidget( cb, 1, 0 );
148  lay->addWidget( bt, 1, 1 );
149 
150  bt = new QPushButton( "Next Trial", widget );
151  connect( bt, SIGNAL(clicked()), this, SLOT(evogaNextTrial()) );
152  lay->addWidget( bt, 2, 0, 1, 2 );
153 
154  //----- Skip Trial... Go to Trial number N
155 
156  // slider to setup the delay for slowing down the simulation
157  QLabel* lb = new QLabel( "Simulation Throttle - speed regulator", widget );
158  lay->addWidget( lb, 3, 0, 1, 2 );
159  simulationThrottle = new QSlider( widget );
160  simulationThrottle->setMinimum( 0 );
161  simulationThrottle->setMaximum( 100 );
162  simulationThrottle->setMinimumHeight( 200 );
163  simulationThrottle->setOrientation( Qt::Vertical );
164  int currDelay = ga->getEvoRobotExperiment()->getStepDelay();
165  simulationThrottle->setValue( floor(13.0*std::log((float)currDelay)) );
166  connect( simulationThrottle, SIGNAL(valueChanged(int)), this, SLOT(onSimulationThrottleChanges(int)) );
167  lay->addWidget( simulationThrottle, 4, 0, 3, 1 );
168  lb = new QLabel( "slow", widget );
169  lay->addWidget( lb, 4, 1 );
170 
171  QString str = "Running as fast as possible";
172  if ( currDelay > 0 ) {
173  QString extra;
174  if ( fabs( currDelay/1000.0 - ga->getEvoRobotExperiment()->getWorldTimeStep() ) < 0.01 ) {
175  extra = "Running approximately at real time";
176  }
177  str = QString("Speed: %1 frames/second [%2 ms]\n%3")
178  .arg(1000.0/currDelay)
179  .arg(currDelay)
180  .arg(extra);
181  }
182  simulationSpeed = new QLabel( str, widget );
183  lay->addWidget( simulationSpeed, 5, 1 );
184  lb = new QLabel( "fast", widget );
185  lay->addWidget( lb, 6, 1 );
186 
187  return ParameterSettableUIViewer( widget, "Evoga Controls" );
188 }
189 
190 void EvoRobotViewer::evogaNextTrial() {
192 }
193 
194 void EvoRobotViewer::onSimulationThrottleChanges( int newvalue ) {
195  // mapping with an exponential in order to get more sensitivity for small values
196  int delay = ceil(std::exp( newvalue/13.0 )-1.0);
197  ga->getEvoRobotExperiment()->setStepDelay( delay );
198  if ( delay > 0 ) {
199  QString extra;
200  if ( fabs( delay/1000.0 - ga->getEvoRobotExperiment()->getWorldTimeStep() ) < 0.01 ) {
201  extra = "Running approximately at real time";
202  }
203  simulationSpeed->setText( QString("Speed: %1 frames/second [%2 ms]\n%3")
204  .arg(1000.0/delay)
205  .arg(delay)
206  .arg(extra) );
207  } else {
208  simulationSpeed->setText( "Running as fast as possible" );
209  }
210 }
211 
212 ParameterSettableUIViewer EvoRobotViewer::fitview( QWidget* parent, Qt::WindowFlags flags )
213 {
214  // Here we also create the fitness viewer
215  ftv = new FitViewer(3,4000,parent,flags);
216  ftv->setChunkProperties(0, "MaxFit", Qt::red, true);
217  ftv->setChunkProperties(1, "AverageFit", Qt::green, true);
218  ftv->setChunkProperties(2, "MinFit", Qt::blue, true);
219  ftv->setLabels(QString("EvoICub Fitness Monitor"), QString("Generations"), QString("Fitness"));
220  ftv->setGeometry(50, 50, 500, 500);
221  ftv->setWindowTitle( "Fitness Curves" );
222  connect( ga, SIGNAL(startingReplication(int)),
223  this, SLOT(onEvogaStartingReplication(int)), Qt::QueuedConnection );
224  connect( ga, SIGNAL(recoveredInterruptedEvolution(QString)),
225  this, SLOT(onEvogaRecoveredInterruptedEvolution(QString)), Qt::QueuedConnection );
226  connect( ga, SIGNAL(endGeneration(int,double,double,double)),
227  this, SLOT(onEvogaEndGeneration(int,double,double,double)), Qt::QueuedConnection );
228  return ParameterSettableUIViewer( ftv, "Fitness monitor" );
229 }
230 
231 // ParameterSettableUIViewer EvoRobotViewer::icubview( QWidget* parent, Qt::WindowFlags flags )
232 // {
233 // m_icubview = new VisionMapSensorGui(parent,flags);
234 // m_icubview->setWindowTitle( "iCub Camera" );
235 // m_icubview->resize( 200, 200 );
236 // m_icubview->hide();
237 // return ParameterSettableUIViewer( m_icubview, "iCub camera" );
238 // }
239 
240 ParameterSettableUIViewer EvoRobotViewer::statview( QWidget* parent, Qt::WindowFlags flags )
241 {
242  statViewer = new QWidget( parent, flags );
243  statViewer->setWindowTitle( "Statictis Viewer" );
244  QGridLayout* lay = new QGridLayout( statViewer );
245  QPushButton* but = new QPushButton( "Load a Stat File", statViewer );
246  connect( but, SIGNAL(clicked()), this, SLOT(loadStat()) );
247  lay->addWidget( but, 0, 0 );
248  but = new QPushButton( "Load All Stat", statViewer );
249  connect( but, SIGNAL(clicked()), this, SLOT(loadAllStat()) );
250  lay->addWidget( but, 0, 1 );
251  return ParameterSettableUIViewer( statViewer, "Statistic Viewer" );
252 }
253 
254 void EvoRobotViewer::loadStat() {
255  QString filename = QFileDialog::getOpenFileName(statViewer, tr("Open Stat File"), ".", tr("Files with statistics (*.fit *.ini)"));
256  if (filename.isEmpty()) {
257  return;
258  }
259  FitViewer* fitViewer = statViewer->findChild<FitViewer*>( "statFitViewer" );
260  if ( fitViewer ) {
261  delete fitViewer;
262  }
263  fitViewer = new FitViewer(3, 4000, statViewer);
264  fitViewer->setObjectName( "statFitViewer" );
265  fitViewer->setLabels(QString("Stat monitor. File: ").append(filename), QString("Generation"), QString("Fitnes"));
266  fitViewer->setChunkProperties(0, "MaxFit", Qt::red,true);
267  fitViewer->setChunkProperties(1, "Average", Qt::green,true);
268  fitViewer->setChunkProperties(2, "Minimum", Qt::blue,true);
269  fitViewer->loadRawData(0, filename, 0);
270  fitViewer->loadRawData(1, filename, 1);
271  fitViewer->loadRawData(2, filename, 2);
272  QGridLayout* lay = qobject_cast<QGridLayout*>( statViewer->layout() );
273  lay->addWidget( fitViewer, 1, 0, 1, 2 );
274  lay->setRowStretch( 1, 2 );
275  fitViewer->show();
276 }
277 
278 void EvoRobotViewer::loadAllStat()
279 {
280  FitViewer* fitViewer = statViewer->findChild<FitViewer*>( "statFitViewer" );
281  if ( fitViewer ) {
282  delete fitViewer;
283  }
284 
285  QDir currentDir;
286  QFileInfoList statFiles = currentDir.entryInfoList( QStringList() << "*.fit", QDir::Files, QDir::Name );
287 
288  fitViewer = new FitViewer(statFiles.size(), ga->getNumOfGenerations(), statViewer);
289  fitViewer->setObjectName( "statFitViewer" );
290  QString title = QString("Stat monitor");
291  fitViewer->setLabels(title, QString("Generation"), QString("Fitness"));
292 
293  QColor colors[10] = { QColor(Qt::red), QColor(Qt::green), QColor(Qt::blue), QColor(Qt::cyan),
294  QColor(Qt::magenta), QColor(Qt::darkYellow), QColor(Qt::gray), QColor(255, 140, 0, 255),
295  QColor(153, 50, 204, 255), QColor(Qt::black) };
296  for(int i=0; i<statFiles.size(); i++ ) {
297  QFileInfo statFile = statFiles[i];
298  QColor col = colors[i%10];
299  fitViewer->setChunkProperties( i, QString("Seed:").append(statFile.baseName().split("S").last()), col, true );
300  fitViewer->loadRawData( i, statFile.fileName(), 0 );
301  }
302  fitViewer->sortchunks();
303  QGridLayout* lay = qobject_cast<QGridLayout*>( statViewer->layout() );
304  lay->addWidget( fitViewer, 1, 0, 1, 2 );
305  lay->setRowStretch( 1, 2 );
306  fitViewer->show();
307 }
308 
309 ParameterSettableUIViewer EvoRobotViewer::testIndividualUI( TestIndividual* test, QWidget* parent, Qt::WindowFlags flags ) {
310  TestIndividualGUI* testIndUI = new TestIndividualGUI( test, parent, flags );
311  testIndUI->setWindowTitle( "Select the Individual to Test" );
312  return ParameterSettableUIViewer( testIndUI, "Individual to Test", QString(), "From this view you can select an individual to test using the \"TestIndividual\" from the \"Tests\" menu" );
313 }
314 
315 void EvoRobotViewer::onWorldAdvance() {
316  ResourcesLocker locker(this);
317 
318  EvoRobotExperiment* exp = getResource<EvoRobotExperiment>("experiment");
319 
320  renderworldwrapper->updateRenderWorld();
321 
322  if ( exp->getActivityPhase() == EvoRobotExperiment::INTEST ) {
323 // if (m_icubview != NULL) {
324 // m_icubview->setImage( exp->getResource<PhyiCub>( "robot" ) ); // update the iCub camera widget
325 // }
326  }
327  // visualizza su EvoGa Controls informazioni su step e trial
328  infoEvoga->setText( QString( "Step %1 of %2 --- Trial %3 of %4" )
329  .arg( exp->getCurStep(), 5 ).arg( exp->getNSteps() )
330  .arg( exp->getCurTrial(), 5 ).arg( exp->getNTrials() ) );
331 }
332 
333 void EvoRobotViewer::onEvogaStartingReplication( int /*replication*/ ) {
334  ftv->reset();
335 }
336 
337 void EvoRobotViewer::onEvogaRecoveredInterruptedEvolution( QString statfile ) {
338  ftv->loadRawData(0,statfile,0);
339  ftv->loadRawData(1,statfile,1);
340  ftv->loadRawData(2,statfile,2);
341 }
342 
343 void EvoRobotViewer::onEvogaEndGeneration( int generation, double fmax, double faverage, double fmin ) {
344  ftv->setChunkValue(0,generation,fmax);
345  ftv->setChunkValue(1,generation,faverage);
346  ftv->setChunkValue(2,generation,fmin);
347  ftv->diplayUntilStep(generation);
348  ftv->update();
349 }
350 
351 void EvoRobotViewer::onActionFinished() {
352  infoEvoga->setText( evorobot->status() );
353 }
354 
355 namespace {
356  // A custom QEvent to force update of RenderWorldWrapperWidget
357  class ForceRenderWorldUpdateEvent : public QEvent
358  {
359  public:
360  ForceRenderWorldUpdateEvent() :
361  QEvent(QEvent::User)
362  {
363  }
364 
365  virtual ~ForceRenderWorldUpdateEvent()
366  {
367  }
368  };
369 }
370 
371 RenderWorldWrapperWidget::RenderWorldWrapperWidget(QWidget* parent, Qt::WindowFlags flags) :
372  QWidget(parent, flags),
374  m_renderWorld(new RenderWorld(this, "world")),
375  m_layout(new QVBoxLayout(this)),
376  m_renderWorldStateRestored(false),
377  m_setCameraToLookAtRobot(false),
378  m_robotTm(wMatrix::identity())
379 {
380  // Setting some window property and creating the layout that will contain renderworld
381  setWindowTitle("3D World");
382  m_layout->setContentsMargins(0, 0, 0, 0);
383  m_layout->addWidget(m_renderWorld);
384  const QString stateFileName = ".evolver.xml";
385  m_renderWorld->setStateFileName(stateFileName);
386  if (QFile::exists(stateFileName)) {
387  m_renderWorldStateRestored = true;
388  m_renderWorld->restoreStateFromFile();
389  }
390 
391  // Declaring which resources we will need to use
392  usableResources(QStringList() << "robot");
393 }
394 
396 {
397  // Nothing to do here
398 }
399 
401 {
402  if (m_setCameraToLookAtRobot) {
403  lookAtRobot();
404 
405  m_setCameraToLookAtRobot = false;
406  // Setting this to true so that the next time the robot changes we don't move camera
407  m_renderWorldStateRestored = true;
408  }
409 
410  m_renderWorld->update();
411 }
412 
414 {
415  // First of all calling parent function
417 
418  // Now sharing with RenderWorld
419  m_renderWorld->shareResourcesWith(buddy);
420 }
421 
422 void RenderWorldWrapperWidget::resourceChanged(QString resourceName, ResourceChangeType changeType)
423 {
424  if (resourceName == "robot") {
425  if ((changeType != Deleted) && (!m_renderWorldStateRestored)) {
426  try {
427  m_robotTm = getResource<WObject>()->matrix();
428  } catch (const ResourceTypeMismatchException&) {
429  }
430 
431  m_setCameraToLookAtRobot = true;
432  }
433  } else {
434  Logger::info("Unknown resource " + resourceName + " for RenderWorldWrapperWidget widget");
435  }
436 
437  // Forcing renderworld update
438  QCoreApplication::postEvent(this, new ForceRenderWorldUpdateEvent());
439 }
440 
441 void RenderWorldWrapperWidget::customEvent(QEvent* event)
442 {
443  if (event->type() == QEvent::User) {
444  // Forcing RenderWorld update
446  }
447 }
448 
449 void RenderWorldWrapperWidget::lookAtRobot()
450 {
451  wVector cameraDefaultPosition = m_robotTm.transformVector(wVector(-0.8f, 0.0f, +0.6f));
452  m_renderWorld->camera()->setPosition(Vec(cameraDefaultPosition[0], cameraDefaultPosition[1], cameraDefaultPosition[2]));
453  m_renderWorld->camera()->setUpVector(Vec(0.0f, 0.0f, 1.0f));
454  m_renderWorld->camera()->lookAt(Vec(m_robotTm.w_pos[0], m_robotTm.w_pos[1], m_robotTm.w_pos[2]));
455 }
456 
457 // #include <QPainter>
458 // #include <QPen>
459 // #include <QBrush>
460 // #include <QTransform>
461 // #include <QVBoxLayout>
462 //
463 // namespace VisionMapSensorGuiInternal {
464 // /**
465 // * \brief An helper class to display an image
466 // *
467 // * This takes a pointer to the image to show and also resizes itself to
468 // * match the image dimension
469 // */
470 // class ImageDisplayer : public QWidget
471 // {
472 // public:
473 // ImageDisplayer(QWidget* parent = NULL) :
474 // QWidget(parent),
475 // m_image(NULL)
476 // {
477 // }
478 //
479 // ~ImageDisplayer()
480 // {
481 // }
482 //
483 // void setImage(QImage* image)
484 // {
485 // // Saving image
486 // m_image = image;
487 //
488 // // Also resetting widget dimensions
489 // setMinimumSize(m_image->width(), m_image->height());
490 // setMaximumSize(m_image->width(), m_image->height());
491 //
492 // // Updating the widget
493 // update();
494 // }
495 //
496 // private:
497 // void paintEvent(QPaintEvent *)
498 // {
499 // if (m_image == NULL) {
500 // return;
501 // }
502 //
503 // QPainter painter(this);
504 //
505 // // Drawing image. Also flipping image (perhaps yarp doesn't consider top left to be 0, 0)
506 // painter.drawImage(0, 0, m_image->mirrored(false, true));
507 // }
508 //
509 // QImage* m_image;
510 // };
511 // }
512 //
513 // VisionMapSensorGui::VisionMapSensorGui(QWidget* parent, Qt::WindowFlags flags) :
514 // QWidget(parent,flags),
515 // m_image(),
516 // m_imageDisplayer(new VisionMapSensorGuiInternal::ImageDisplayer(this))
517 // {
518 // // Creating a layout and adding the image displayer widget and the table with map activations
519 // QVBoxLayout* layout = new QVBoxLayout(this);
520 // layout->addWidget(m_imageDisplayer);
521 //
522 //
523 // }
524 //
525 // VisionMapSensorGui::~VisionMapSensorGui()
526 // {
527 // // Nothing to do here
528 // }
529 //
530 // void VisionMapSensorGui::setImage(PhyiCub *icub, bool useRightCamera)
531 // {
532 //
533 // // Taking the image in yarp format
534 // yarp::sig::ImageOf<yarp::sig::PixelRgb> yarpImage;
535 // // yarp::dev::IFrameGrabberImage* frameGrabber = useRightCamera ? icub->rightEyeFrameGrabber() : icub->leftEyeFrameGrabber();
536 // yarp::dev::IFrameGrabberImage* frameGrabber = NULL; // The line above crashes with multithread
537 // if (frameGrabber == NULL) {
538 // return;
539 // }
540 // // frameGrabber->getImage(yarpImage); // Crashes with multithread
541 //
542 // // Converting to QImage
543 // m_image = QImage(yarpImage.width(), yarpImage.height(), QImage::Format_RGB32);
544 // for (int i = 0; i < yarpImage.width(); i++) {
545 // for (int j = 0; j < yarpImage.height(); j++) {
546 // // Converting pixel and writing it into the QImage
547 // yarp::sig::PixelRgb& yarpPixel = yarpImage.pixel(i, j);
548 // m_image.setPixel(i, j, qRgb(yarpPixel.r, yarpPixel.g, yarpPixel.b));
549 // }
550 // }
551 //
552 //
553 // // Drawing an X at the image center
554 // QPainter painter(&m_image);
555 // const int cX = m_image.width() / 2;
556 // const int cY = m_image.height() / 2;
557 //
558 // // Drawing the X
559 // painter.setPen(QPen(Qt::white, 3));
560 // painter.drawLine(cX - 5, cY - 5, cX + 5, cY + 5);
561 // painter.drawLine(cX + 5, cY - 5, cX - 5, cY + 5);
562 // painter.setPen(QPen(Qt::black, 1));
563 // painter.drawLine(cX - 5, cY - 5, cX + 5, cY + 5);
564 // painter.drawLine(cX + 5, cY - 5, cX - 5, cY + 5);
565 //
566 // // Setting the image for the image displayer
567 // m_imageDisplayer->setImage(&m_image);
568 // m_imageDisplayer->update();
569 // }
570 //
571 // void VisionMapSensorGui::addMark(double x, double y, QColor markCenter, QColor markSurrounding)
572 // {
573 // // Drawing a mark directly on the image
574 // QPainter painter(&m_image);
575 //
576 // // Computing the mark position in image coordinates
577 // const int imageX = int(x * double(m_image.width()));
578 // const int imageY = int(y * double(m_image.height()));
579 //
580 // // Drawing the mark
581 // painter.setPen(QPen(markSurrounding, 5));
582 // painter.drawPoint(imageX, imageY);
583 // painter.setPen(QPen(markCenter, 3));
584 // painter.drawPoint(imageX, imageY);
585 //
586 // // Updating the image displayer widget
587 // m_imageDisplayer->update();
588 // }
589 
590 TestIndividualGUI::TestIndividualGUI(TestIndividual* tb, QWidget *parent, Qt::WindowFlags flags) :
591  QWidget(parent, flags)
592 {
593  test = tb;
594 
595  //set layout
596  QGridLayout* mainLay = new QGridLayout( this );
597 
598  // buttons
599  QPushButton* bt = new QPushButton( "Refresh", this );
600  connect( bt, SIGNAL(clicked()), this, SLOT(populateCombo()) );
601  mainLay->addWidget(bt, 0, 0, 1, 2);
602  //creating comboBox and list
603  combo = new QComboBox( this );
604  list = new QListWidget( this );
605  mainLay->addWidget(new QLabel("Select File to load:"), 1, 0);
606  mainLay->addWidget(combo, 1, 1);
607  mainLay->addWidget(list, 2, 0, 1, 2);
608 
609  //checking available best and gen files
610  populateCombo();
611 
612  // Connecting signals and slots
613  connect(combo, SIGNAL(activated(QString)), this, SLOT(seedWasChosen()));
614  connect(list, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(agentClicked()));
615 }
616 
617 void TestIndividualGUI::populateCombo()
618 {
619  combo->clear();
620  list->clear();
621  //ask abstractGA the template name for the files (i.e. "*P*S*G*.gen")
622  QString bestF = test->component()->getGA()->bestsFilename();
623  QString genF = test->component()->getGA()->generationFilename();
624 
625  //search current folder for files
626  QDir* dir = new QDir();
627  QStringList expression = (QStringList() << bestF << genF);
628  fileList = dir->entryList(expression);
629 
630  //insert their name into the combo boxes
631  combo->addItems(fileList);
632 }
633 
634 void TestIndividualGUI::seedWasChosen()
635 {
636  //load the chosen file
637  test->setPopulationToTest( combo->currentText(), false );
638  //refresh individuals list on the GUI
639  list->clear();
640  int loadindi = test->component()->getGA()->numLoadedGenotypes();
641  for(int i=1; i<=loadindi; i++)
642  {
643  list->addItem(QString::number(i));
644  }
645 }
646 
647 void TestIndividualGUI::agentClicked()
648 {
649  //take index of the chosen individual
650  test->setIndividualToTest( list->currentRow() );
651 }
652 
653 } //end namespace farsa
654 
655 // All the suff below is to restore the warning state on Windows
656 #if defined(_MSC_VER)
657  #pragma warning(pop)
658 #endif