YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
mainwindow.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: LGPL-2.1-or-later
4 */
5
7#include "ui_mainwindow.h"
8#include <QFileDialog>
9#include <QCheckBox>
10#include <QShortcut>
11#include <QProgressBar>
12#include <include/aboutdlg.h>
13#include <QMessageBox>
14#include <csignal>
15#include <yarp/conf/version.h>
16#include <yarp/dataplayer/YarpDataplayer.h>
17
18#if defined(_WIN32)
19 #pragma warning (disable : 4099)
20 #pragma warning (disable : 4250)
21 #pragma warning (disable : 4520)
22#endif
23
24#define WND_DEF_HEIGHT 400
25#define WND_DEF_WIDTH 800
26
27#define ACTIVE 0
28#define PART 1
29#define TYPE 2
30#define FRAMES 3
31#define SAMPLERATE 4
32#define PORT 5
33#define TIMETAKEN 6
34#define PERCENT 7
35
36#ifndef APP_NAME
37 #define APP_NAME "yarpdataplayer"
38#endif
39
40using namespace yarp::os;
41
42void sighandler(int sig)
43{
44 yInfo() << "\n\nCaught ctrl-c, please quit within gui for clean exit\n\n";
45}
46
47/**********************************************************/
49 QMainWindow(parent),
50 ui(new Ui::MainWindow),
51 loadingWidget(this)
52{
53 ui->setupUi(this);
54 setWindowTitle(APP_NAME);
55 qutilities = nullptr;
56 pressed = false;
57 initThread = nullptr;
58
59 moduleName = QString("%1").arg(rf.check("name", Value("yarpdataplayer"), "module name (string)").asString().c_str());
60 verbose = rf.check("verbose", Value(false)).asBool();
61 dataset = rf.check("dataset",Value("")).asString();
62
63 if (rf.check("withExtraTimeCol")){
64 withExtraTimeCol = true;
65 column = rf.check("withExtraTimeCol",Value(1)).asInt32();
66
68 column = 1;
69 }
70
71 if (verbose){
72 yInfo() << "Selected timestamp column to check is " << column;
73 }
74
75 } else {
76 withExtraTimeCol = false;
77 column = 0;
78 }
79
80 add_prefix = rf.check("add_prefix");
82
83 subDirCnt = 0;
84 setWindowTitle(moduleName);
85 setupActions();
86 setupSignals();
87
88 QString port = QString("/%1/rpc:i").arg(moduleName);
89 rpcPort.open( port.toLatin1().data() );
90
91 ::signal(SIGINT, sighandler);
92 ::signal(SIGTERM, sighandler);
93
94 attach(rpcPort);
95
96 quitFromCmd = false;
97
98 connect(ui->mainWidget,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(onItemDoubleClicked(QTreeWidgetItem*,int)));
99 connect(this,SIGNAL(internalLoad(QString)),this,SLOT(onInternalLoad(QString)),Qt::QueuedConnection);
100 connect(this,SIGNAL(internalPlay()),this,SLOT(onInternalPlay()),Qt::BlockingQueuedConnection);
101 connect(this,SIGNAL(internalPause()),this,SLOT(onInternalPause()),Qt::BlockingQueuedConnection);
102 connect(this,SIGNAL(internalStop()),this,SLOT(onInternalStop()),Qt::BlockingQueuedConnection);
103 connect(this,SIGNAL(internalStep(yarp::os::Bottle*)),this,SLOT(onInternalStep(yarp::os::Bottle*)),Qt::BlockingQueuedConnection);
104 connect(this,SIGNAL(internalSetFrame(int)),this,SLOT(onInternalSetFrame(int)),Qt::BlockingQueuedConnection);
105 connect(this,SIGNAL(internalGetFrame(std::string, int*)),this,SLOT(onInternalGetFrame(std::string,int*)),Qt::BlockingQueuedConnection);
106 connect(this,SIGNAL(internalQuit()),this,SLOT(onInternalQuit()),Qt::QueuedConnection);
107 connect(this,SIGNAL(internalGetSliderPercentage(int*)),this,SLOT(onInternalGetSliderPercentage(int*)),Qt::BlockingQueuedConnection);
108
109 if (!dataset.empty()){
110 if (!load(dataset) && verbose){
111 yError() << "Could not load " << dataset;
112 }
113 }
114
115}
116
117/**********************************************************/
119{
120 delete ui;
121 if (verbose){
122 yInfo() << "cleaning up rpc port...";
123 }
124 rpcPort.close();
125 if (verbose){
126 yInfo() << "done cleaning rpc port...";
127 }
129}
130
131/**********************************************************/
132void MainWindow::onItemDoubleClicked(QTreeWidgetItem *item,int column)
133{
134 if(column == 5){
135 //ui->treeWidget->openPersistentEditor(item,column);
136 item->setFlags(item->flags() | Qt::ItemIsEditable);
137 return;
138 }else{
139 item->setFlags(item->flags() & ~Qt::ItemIsEditable);
140 }
141}
142
143/**********************************************************/
145{
146 return this->yarp().attachAsServer(source);
147}
148
149/**********************************************************/
151{
152 Bottle reply;
153 emit internalStep(&reply);
154 if (reply.toString() == "error"){
155 return false;
156 }
157 if (reply.toString() == "ok"){
158 return true;
159 }
160 return false;
161}
162
163/**********************************************************/
164void MainWindow::onInternalStep(Bottle *reply)
165{
166 stepFromCommand(*reply);
167}
168
169/**********************************************************/
170bool MainWindow::setFrame(const int frameNum)
171{
172 emit internalSetFrame(frameNum);
173 return true;
174}
175
176/**********************************************************/
177void MainWindow::onInternalSetFrame(const int frameNum)
178{
179 updateFrameNumber(frameNum);
180}
181
182/**********************************************************/
183int MainWindow::getFrame(const std::string &name)
184{
185 int frame = 0;
186 emit internalGetFrame(name,&frame);
187 if (frame < 1){
188 return -1;
189 } else {
190 return frame;
191 }
192}
193
194/**********************************************************/
195void MainWindow::onInternalGetFrame(const std::string &name, int *frame)
196{
197 getFrameCmd(name.c_str(),frame);
198}
199
200/**********************************************************/
202{
203 int percentage = 0;
205 if (percentage < 1){
206 return -1;
207 } else {
208 return percentage;
209 }
210}
211
212/**********************************************************/
213void MainWindow::onInternalGetSliderPercentage(int *percentage)
214{
215 *percentage = ui->playSlider->value();
216}
217
218/**********************************************************/
220{
221 if (qutilities->qengine->isSuspended()){
222 return "paused";
223 }
224 if (qutilities->qengine->isRunning()){
225 return "playing";
226 }
227 else {
228 return "stopped";
229 }
230 return "";
231}
232
233/**********************************************************/
234bool MainWindow::load(const std::string &path)
235{
236 std::string cmdPath = path;
237 QString sPath = QString("%1").arg(path.c_str());
238
239 size_t slashErr = cmdPath.find('/');
240
241 if (slashErr == std::string::npos){
242 if (verbose){
243 yError() << "Error, please make sure you are using forward slashes '/' in path.";
244 }
245 return false;
246 } else {
248 }
249
250// waitMutex.lock();
251// waitCond.wait(&waitMutex);
252// waitMutex.unlock();
253
254 if (subDirCnt <= 0 ){
255 return false;
256 }
257
258 return true;
259}
260
261/**********************************************************/
262void MainWindow::onInternalLoad(QString sPath)
263{
264 ui->mainWidget->clear();
265 for (int x=0; x < subDirCnt; x++){
266 qutilities->closePorts(qutilities->partDetails[x]);
267 }
268
269 doGuiSetup(sPath);
270}
271
272/**********************************************************/
274{
276 return true;
277}
278
279/**********************************************************/
280void MainWindow::onInternalPlay()
281{
282 onMenuPlayBackPlay();
283}
284
285/**********************************************************/
287{
289 return true;
290}
291
292/**********************************************************/
293void MainWindow::onInternalPause()
294{
295 onMenuPlayBackPause();
296}
297
298/**********************************************************/
300{
302 return true;
303}
304
305/**********************************************************/
306void MainWindow::onInternalStop()
307{
308 onMenuPlayBackStop();
309}
310
311/**********************************************************/
313{
314 quitFromCmd = true;
316 return true;
317}
318
319/**********************************************************/
320void MainWindow::onInternalQuit()
321{
322 if(cmdSafeExit()){
323 QMainWindow::close();
324 }
325}
326
327/**********************************************************/
329{
330 if (subDirCnt > 0){
331 if (verbose){
332 yInfo() << "setting initial frame to " << frameNum;
333 }
334 //if (frameNum == 0)
335 //frameNum = 1;
336
337 for (auto& itr : partMap){
338
339 qutilities->qengine->virtualTime = qutilities->partDetails[itr.second].timestamp[qutilities->partDetails[itr.second].currFrame];
340 qutilities->partDetails[itr.second].currFrame = frameNum;
341 }
342 qutilities->qengine->virtualTime = qutilities->partDetails[0].timestamp[qutilities->partDetails[0].currFrame];
343 return true;
344 } else {
345 return false;
346 }
347}
348
349/**********************************************************/
350void MainWindow::getFrameCmd( const char* part , int *frame)
351{
352 if (subDirCnt > 0){
353 for (auto& itr : partMap) {
354 if (strcmp (part, itr.first) == 0) {
355 *frame = qutilities->partDetails[itr.second].currFrame;
356 }
357 }
358 }
359}
360
361/**********************************************************/
363{
364 if (subDirCnt > 0){
366 reply.addString("ok");
367 } else {
368 reply.addString("error");
369 }
370}
371
372/**********************************************************/
373bool MainWindow::cmdSafeExit()
374{
375 quitFromCmd = true;
376 if(qutilities->qengine){
377 if (verbose){
378 yInfo() << "asking the threads to stop...";
379 }
380 if (qutilities->qengine->isSuspended()){
381 qutilities->qengine->resume();
382
383 }
384 qutilities->qengine->stop();
385 if (verbose){
386 yInfo() << "done stopping!";
387 }
388 for (int i = 0; i < subDirCnt; i++) {
389 qutilities->partDetails[i].currFrame = 1;
390 }
391
392 if (verbose){
393 yInfo() << "Module closing...\nCleaning up...";
394 }
395 for (int x=0; x < subDirCnt; x++){
396 qutilities->partDetails[x].worker->release();
397 }
398 if (verbose){
399 yInfo() << "Attempt to interrupt ports";
400 }
401 for (int x=0; x < subDirCnt; x++){
402 qutilities->interruptPorts(qutilities->partDetails[x]);
403 }
404 if (verbose){
405 yInfo() << "Attempt to close ports\n";
406 }
407 for (int x=0; x < subDirCnt; x++){
408 qutilities->closePorts(qutilities->partDetails[x]);
409 }
411 if (verbose){
412 yInfo() << "Done!...";
413 }
414
415 }
416 return true;
417}
418
419/**********************************************************/
420bool MainWindow::safeExit()
421{
422 if(qutilities->qengine){
423 if (verbose){
424 yInfo() << "asking the threads to stop...";
425 }
426 if (qutilities->qengine->isSuspended()){
427 qutilities->qengine->resume();
428 }
429 qutilities->qengine->stop();
430 if (verbose){
431 yInfo() << "done stopping!";
432 }
433 for (int i = 0; i < subDirCnt; i++) {
434 qutilities->partDetails[i].currFrame = 1;
435 }
436
437 if (verbose){
438 yInfo() << "Module closing...\nCleaning up...";
439 }
440 for (int x=0; x < subDirCnt; x++){
441 qutilities->partDetails[x].worker->release();
442 }
443 if (verbose){
444 yInfo() << "Attempt to interrupt ports";
445 }
446 for (int x=0; x < subDirCnt; x++){
447 qutilities->interruptPorts(qutilities->partDetails[x]);
448 }
449 if (verbose){
450 yInfo() << "Attempt to close ports\n";
451 }
452 for (int x=0; x < subDirCnt; x++){
453 qutilities->closePorts(qutilities->partDetails[x]);
454 }
456 if (verbose){
457 yInfo() << "Done!...";
458 }
459 }
460 return true;
461}
462
463/**********************************************************/
465{
466 if(!qutilities){
467 qutilities = new QUtilities(this);
468 qutilities->withExtraColumn = withExtraTimeCol;
469 qutilities->column = column;
470 qutilities->setModuleName(moduleName.toLatin1().data());
471 qutilities->addPrefix(add_prefix);
472 qutilities->setVerbose(verbose);
473 }
474}
475
476/**********************************************************/
478{
479 if(qutilities){
480 delete qutilities;
481 qutilities = nullptr;
482 }
483}
484
485/**********************************************************/
487{
488 QTreeWidgetItem *row = nullptr;
489 row = getRowByPart(QString("%1").arg(szName));
490
491
492 if(row){
493 QCheckBox *check = ((QCheckBox*)ui->mainWidget->itemWidget(row,ACTIVE));
494 if(check){
495 return check->isChecked();
496 }
497 }
498 return false;
499}
500
501/**********************************************************/
503{
504 if (!quitFromCmd){
505 QMessageBox::StandardButton resBtn = QMessageBox::question( this, APP_NAME,
506 "Quitting, Are you sure?\n",
507 QMessageBox::No | QMessageBox::Yes, QMessageBox::Yes);
508
509 if (resBtn != QMessageBox::Yes) {
510 event->ignore();
511
512 } else {
513 safeExit();
514 event->accept();
515 }
516 }
517}
518
519/**********************************************************/
520void MainWindow::setupSignals()
521{
522 connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(onSpeedValueChanged(int)));
523 connect(ui->playSlider,SIGNAL(sliderPressed()),this,SLOT(onSliderPressed()));
524 connect(ui->playSlider,SIGNAL(sliderReleased()),this,SLOT(onSliderReleased()));
525
526 connect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPlay()));
527 connect(ui->stopButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackStop()));
528 connect(ui->ffwButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackForward()));
529 connect(ui->rewButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackBackward()));
530}
531
532/**********************************************************/
533void MainWindow::setupActions()
534{
535 connect(ui->actionOpen_Directory,SIGNAL(triggered()),this,SLOT(onMenuFileOpen()));
536 connect(ui->actionPlay,SIGNAL(triggered()),this,SLOT(onMenuPlayBackPlay()));
537 connect(ui->actionPause,SIGNAL(triggered()),this,SLOT(onMenuPlayBackPause()));
538 connect(ui->actionStop,SIGNAL(triggered()),this,SLOT(onMenuPlayBackStop()));
539 connect(ui->actionForward,SIGNAL(triggered()),this,SLOT(onMenuPlayBackForward()));
540 connect(ui->actionRewind,SIGNAL(triggered()),this,SLOT(onMenuPlayBackBackward()));
541 connect(ui->actionStrict,SIGNAL(triggered()),this,SLOT(onMenuPlayBackStrict()));
542 connect(ui->actionRepeat,SIGNAL(triggered()),this,SLOT(onMenuPlayBackRepeat()));
543 connect(ui->actionIncrease,SIGNAL(triggered()),this,SLOT(onMenuSpeedUp()));
544 connect(ui->actionDecrease,SIGNAL(triggered()),this,SLOT(onMenuSpeedDown()));
545 connect(ui->actionNormal_1x,SIGNAL(triggered()),this,SLOT(onMenuSpeedNormal()));
546 connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(onMenuHelpAbout()));
547 connect(ui->actionQuit,SIGNAL(triggered()),this,SLOT(onClose()));
548}
549
550/**********************************************************/
551bool MainWindow::doGuiSetup(QString newPath)
552{
553 if(initThread && initThread->isRunning()){
554 return false;
555 }
556
559
560 ui->statusBar->showMessage(newPath);//Write path to the gui
561 //look for folders and log files associated with them
562 if (verbose)
563 {
564 yInfo() << "the full path is " << newPath.toLatin1().data();
565 }
566 subDirCnt = 0;
567 rowInfoVec.clear();
568
569
570 itr = 0;
571 partMap.clear();
572
573 if(!initThread){
574 initThread = new InitThread(qutilities,newPath,rowInfoVec,this);
575 connect(initThread,SIGNAL(initDone(int)),this,SLOT(onInitDone(int)),Qt::QueuedConnection);
576 initThread->start();
577 }else{
578 if(!initThread->isRunning()){
579 delete initThread;
580 initThread = new InitThread(qutilities,newPath,rowInfoVec,this);
581 connect(initThread,SIGNAL(initDone(int)),this,SLOT(onInitDone(int)),Qt::QueuedConnection);
582 initThread->start();
583 }
584 }
585
586 loadingWidget.start();
587
588 return true;
589}
590
591/**********************************************************/
592void MainWindow::onInitDone(int subDirCount)
593{
594 subDirCnt = subDirCount;
595 //add the parts to the gui
596 for (int x=0; x < subDirCnt; x++){
597 addPart(qutilities->partDetails[x].name.c_str(), qutilities->partDetails[x].type.c_str(), qutilities->partDetails[x].maxFrame, qutilities->partDetails[x].portName.c_str() );
598 setInitialPartProgress(qutilities->partDetails[x].name.c_str(), 0);
599 qutilities->configurePorts(qutilities->partDetails[x]);
600 }
601
602 ui->playButton->setEnabled(true);
603 ui->ffwButton->setEnabled(true);
604 ui->rewButton->setEnabled(true);
605 ui->stopButton->setEnabled(true);
606 ui->playSlider->setEnabled(true);
607 ui->horizontalSlider->setEnabled(true);
608
609 ui->actionPlay->setEnabled(true);
610 ui->actionForward->setEnabled(true);
611 ui->actionRewind->setEnabled(true);
612 ui->actionStop->setEnabled(true);
613
614 ui->actionIncrease->setEnabled(true);
615 ui->actionDecrease->setEnabled(true);
616 ui->actionNormal_1x->setEnabled(true);
617 ui->actionRepeat->setEnabled(true);
618 ui->actionStrict->setEnabled(true);
619
620 loadingWidget.accept();
621 loadingWidget.stop();
622
623 if(!errorMessage.isEmpty()){
624 switch(QMessageBox::critical(this,"Setup Error",errorMessage,QMessageBox::Ok)){
625 case(QMessageBox::Ok):{
626 if(verbose){
627 yInfo() << "OK clicked.";
628 }
629 break;
630 }
631 default:{
632 if(verbose){
633 yError() << "Unexpected button clicked.";
634 }
635 break;
636 }
637 }
638 }
639
640 errorMessage = "";
641
642 waitCond.wakeAll();
643}
644
645/**********************************************************/
646void MainWindow::addPart(const char* szName, const char* type, int frames, const char* portName, const char* szFileName )
647{
648 partMap[szName] = itr;
649 auto* item = new QTreeWidgetItem();
650 ui->mainWidget->addTopLevelItem(item);
651 auto* checkBox = new QCheckBox();
652 checkBox->setChecked(true);
653 ui->mainWidget->setItemWidget(item,ACTIVE,checkBox);
654 if(szName){
655 item->setText(PART,QString("%1").arg(szName));
656 ui->mainWidget->resizeColumnToContents(PART);
657 }
658 if(type){
659 item->setText(TYPE,QString("%1").arg(type));
660 ui->mainWidget->resizeColumnToContents(TYPE);
661 }
662 item->setText(FRAMES,QString("%1").arg(frames));
663 ui->mainWidget->resizeColumnToContents(FRAMES);
664
665 if(portName){
666 item->setText(PORT,QString("%1").arg(portName));
667 ui->mainWidget->resizeColumnToContents(PORT);
668 }
669
670 auto* progress = new QProgressBar();
671 progress->setMaximum(100);
672 progress->setValue(0);
673 progress->setAlignment(Qt::AlignCenter);
674 ui->mainWidget->setItemWidget(item,PERCENT,progress);
675
676 itr++;
677}
678
679/**********************************************************/
680bool MainWindow::setInitialPartProgress(const char* szName, int percentage)
681{
682 QTreeWidgetItem *row = nullptr;
683 row = getRowByPart(QString("%1").arg(szName));
684
685
686 if(row){
687 QProgressBar *progress = ((QProgressBar*)ui->mainWidget->itemWidget(row,PERCENT));
688 if(progress){
689 progress->setValue(percentage);
690 return true;
691 }
692 }
693
694 return false;
695}
696
697/**********************************************************/
698bool MainWindow::setPartProgress(const char* szName, int percentage)
699{
700 QTreeWidgetItem *row = nullptr;
701 row = getRowByPart(QString("%1").arg(szName));
702 if(row){
703 QProgressBar *progress = ((QProgressBar*)ui->mainWidget->itemWidget(row,PERCENT));
704 if(progress){
705 progress->setValue(percentage);
706 return true;
707 }
708 }
709 return false;
710}
711
712/**********************************************************/
713QTreeWidgetItem * MainWindow::getRowByPart(QString szName )
714{
715
716 for(int i=0;i<ui->mainWidget->topLevelItemCount();i++){
717 if(ui->mainWidget->topLevelItem(i)->text(PART) == szName){
718 return ui->mainWidget->topLevelItem(i);
719 }
720 }
721 return nullptr;
722}
723
724/**********************************************************/
725void MainWindow::onMenuFileOpen()
726{
727 if(ui->actionRepeat->isChecked())
728 {
729 if (verbose){
730 yInfo() << "repeat mode is activated, setting it to false";
731 }
732 qutilities->repeat = false;
733 ui->actionRepeat->setChecked(false);
734 }
735
736 if (ui->actionStrict->isChecked())
737 {
738 if (verbose){
739 yInfo() << "send strict mode is activated, setting it to false";
740 }
741 qutilities->sendStrict = false;
742 ui->actionStrict->setChecked(false);
743 }
744 QString dir = QFileDialog::getExistingDirectory(this, tr("Please choose a folder"),
745 QDir::homePath(),
746 QFileDialog::ShowDirsOnly
747 | QFileDialog::DontResolveSymlinks);
748
749 if(!dir.isEmpty())
750 {
751 ui->mainWidget->clear();
752 for (int x = 0; x < subDirCnt; x++) {
753 qutilities->closePorts(qutilities->partDetails[x]);
754 }
755
756 doGuiSetup(dir);
757 }
758}
759
760/**********************************************************/
761void MainWindow::onErrorMessage(QString msg)
762{
763 QString file = msg;
764
765 if(loadingWidget.isVisible()){
767 if(errorMessage.isEmpty()){
768 fullMessage = QString( "There was a problem opening \n\n%1\n\nplease check its validity").arg(file);
769 errorMessage = errorMessage + "\n" + fullMessage;
770 }else{
771 int index = errorMessage.indexOf("please check");
772 QString aux = errorMessage.left(errorMessage.length() -(errorMessage.length() - index));
773 errorMessage = aux + msg + "\n\nplease check their validity";
774 }
775
776
777 return;
778 }else{
779 QString fullMessage = QString( "There was a problem opening \n\n%1\n\nplease check its validity").arg(file);
780 switch(QMessageBox::critical(this,"Setup Error",fullMessage,QMessageBox::Ok)){
781 case(QMessageBox::Ok):{
782 if (verbose){
783 yInfo("OK clicked.");
784 }
785 break;
786 }
787 default:{
788 if (verbose){
789 yError("Unexpected button clicked.");
790 }
791 break;
792 }
793 }
794 }
795}
796
797/**********************************************************/
798void MainWindow::onMenuHelpAbout()
799{
800 QString copyright = "Copyright (C) 2006-2021 Istituto Italiano di Tecnologia (IIT)";
801 QString name = APP_NAME;
802 QString version = YARP_VERSION;
803 AboutDlg dlg(name,version,copyright,"https://www.iit.it/");
804 dlg.exec();
805}
806
807/**********************************************************/
808void MainWindow::onMenuPlayBackPlay()
809{
810
811 if (subDirCnt > 0){
812 bool allPartsStatus = qutilities->qengine->getAllPartsStatus();
813 ui->playButton->setIcon(QIcon(":/pause.svg"));
814 disconnect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPlay()));
815 connect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPause()));
816
817 ui->actionPause->setEnabled(true);
818 ui->actionPlay->setEnabled(false);
819
820 if (verbose){
821 yInfo() << "checking if port was changed by the user...";
822 }
823
824 for (int i=0; i < subDirCnt; i++){
825 QString test;
826 getPartPort(qutilities->partDetails[i].name.c_str(), &test);
827 if (strcmp( test.toLatin1().data() , qutilities->partDetails[i].portName.c_str()) == 0 ){
828 if (verbose){
829 yInfo() << "Port is the same continue";
830 }
831
832 }else{
833 if (verbose){
834 yInfo() << "Modifying ports";
835 }
836 qutilities->partDetails[i].portName = test.toLatin1().data();//getPartPort( qutilities->partDetails[i].name.c_str(), test);
837 qutilities->configurePorts(qutilities->partDetails[i]);
838 }
839 }
840
841 if (allPartsStatus)
842 {
843 if (verbose){
844 yInfo() << "asking the threads to stop...";
845 }
846 if (qutilities->qengine->isSuspended()){
847 qutilities->qengine->resume();
848 }
849
850 qutilities->qengine->stop();
851 if (verbose){
852 yInfo() << "done stopping!";
853 }
854 for (int i = 0; i < subDirCnt; i++) {
855 qutilities->partDetails[i].currFrame = 1;
856 }
857
858 if (verbose){
859 yInfo() << "done stopping the thread...";
860 }
861 ui->playSlider->setEnabled(false);
862
863 for (int i=0; i < subDirCnt; i++){
864 setFrameRate(qutilities->partDetails[i].name.c_str(), 0);
865 setPartProgress( qutilities->partDetails[i].name.c_str(), 0 );
866 setFrameRate(qutilities->partDetails[i].name.c_str(), 0);
867 }
869 qutilities->qengine->setAllPartsStatus(false);
870 }
871
872 if ( qutilities->qengine->isSuspended() ) {
873 if (verbose){
874 yInfo() << "asking the thread to resume";
875 }
876
877 for (int i = 0; i < subDirCnt; i++) {
878 qutilities->partDetails[i].worker->resetTime();
879 }
880
881 qutilities->qengine->resume();
882 } else if (!qutilities->qengine->isRunning()) {
883 if (verbose){
884 yInfo() << "asking the thread to start";
885 yInfo() <<"initializing the workers...";
886 }
887
888 for (int i = 0; i < subDirCnt; i++) {
889 qutilities->partDetails[i].worker->init();
890 }
891
892 if (verbose){
893 yInfo() << "starting the master thread...";
894 }
895 qutilities->qengine->start();
896 }
897 ui->playSlider->setEnabled(true);
898 }
899}
900
901/**********************************************************/
902void MainWindow::onMenuPlayBackPause()
903{
904 if (subDirCnt > 0){
905 ui->playButton->setIcon(QIcon(":/play.svg"));
906 disconnect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPause()));
907 connect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPlay()));
908
909 ui->actionPause->setEnabled(false);
910 ui->actionPlay->setEnabled(true);
911
912 if (verbose){
913 yInfo() << "asking the threads to pause...";
914 }
915 qutilities->qengine->pause();
916 }
917}
918
919/**********************************************************/
920void MainWindow::resetButtonOnStop()
921{
922 ui->playButton->setIcon(QIcon(":/play.svg"));
923 disconnect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPause()));
924 connect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPlay()));
925
926 ui->actionPause->setEnabled(false);
927 ui->actionPlay->setEnabled(true);
928 ui->playSlider->setEnabled(false);
929}
930
931/**********************************************************/
932void MainWindow::onMenuPlayBackStop()
933{
934 if (subDirCnt > 0){
935
936 if (verbose){
937 yInfo() << "asking the threads to stop...";
938 }
939 if (qutilities->qengine->isSuspended()){
940 qutilities->qengine->resume();
941 }
942
943 qutilities->qengine->stop();
944 if (verbose){
945 yInfo() << "done stopping!";
946 }
947 for (int i = 0; i < subDirCnt; i++) {
948 qutilities->partDetails[i].currFrame = 1;
949 }
950
951 if (verbose){
952 yInfo() << "done stopping the thread...";
953 }
954 ui->playSlider->setEnabled(false);
955
956
957 for (int i=0; i < subDirCnt; i++){
958 setFrameRate(qutilities->partDetails[i].name.c_str(), 0);
959 setPartProgress( qutilities->partDetails[i].name.c_str(), 0 );
960 setFrameRate(qutilities->partDetails[i].name.c_str(), 0);
961 }
963
964 ui->playButton->setIcon(QIcon(":/play.svg"));
965 disconnect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPause()));
966 disconnect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPlay()));
967 connect(ui->playButton,SIGNAL(clicked()),this,SLOT(onMenuPlayBackPlay()));
968 }
969}
970
971/**********************************************************/
972void MainWindow::onMenuPlayBackForward()
973{
974 if (subDirCnt > 0) {
975 qutilities->qengine->forward(5);
976 }
977}
978
979/**********************************************************/
980void MainWindow::onMenuPlayBackBackward()
981{
982 if (subDirCnt > 0) {
983 qutilities->qengine->backward(5);
984 }
985}
986
987/**********************************************************/
988void MainWindow::onMenuPlayBackStrict()
989{
990 if(ui->actionStrict->isChecked()){
991 if (verbose){
992 yInfo() << "strict mode is activated";
993 }
994 qutilities->sendStrict = true;
995 } else {
996 if (verbose){
997 yInfo() << "strict mode is deactivated";
998 }
999 qutilities->sendStrict = false;
1000 }
1001}
1002
1003/**********************************************************/
1004void MainWindow::onMenuPlayBackRepeat()
1005{
1006 if(ui->actionRepeat->isChecked()){
1007 if (verbose){
1008 yInfo() << "repeat mode is activated";
1009 }
1010 qutilities->repeat = true;
1011 } else {
1012 if (verbose){
1013 yInfo() << "repeat mode is deactivated";
1014 }
1015 qutilities->repeat = false;
1016 }
1017}
1018
1019/**********************************************************/
1020void MainWindow::onMenuSpeedUp()
1021{
1022 ui->horizontalSlider->setValue(ui->horizontalSlider->value() + 1);
1023 //m_hScale.set_value(m_hScale.get_value() + 1.0);
1024}
1025
1026/**********************************************************/
1027void MainWindow::onMenuSpeedDown()
1028{
1029 ui->horizontalSlider->setValue(ui->horizontalSlider->value() - 1);
1030}
1031
1032/**********************************************************/
1033void MainWindow::onMenuSpeedNormal()
1034{
1035 ui->horizontalSlider->setValue(10);
1036}
1037
1038/**********************************************************/
1039void MainWindow::onSpeedValueChanged(int val)
1040{
1041 double value = (double)val/10;
1042 value = (value>=1.0) ? value : (value+1.0)/2.0;
1043 char szValue[16];
1044 sprintf(szValue, "%.1fx", value);
1045 QString speed = QString("%1").arg(szValue);
1046 ui->speedValueLbl->setText(speed);
1047 // the range is [0.25 ... 4.0]
1048 if(qutilities){
1049 qutilities->speed = value;
1050 }
1051}
1052
1053/**********************************************************/
1054void MainWindow::onSliderPressed()
1055{
1056 pressed = true;
1057}
1058
1059/**********************************************************/
1060void MainWindow::onSliderReleased()
1061{
1062 int currValue = ui->playSlider->value();
1063 goToPercentage(currValue);
1064 pressed = false;
1065}
1066
1067/**********************************************************/
1069{
1070 QTreeWidgetItem *row = nullptr;
1071 row = getRowByPart(QString("%1").arg(szName));
1072 if(row){
1073 *dest = row->text(PORT);
1074 return true;
1075 }
1076 if (verbose){
1077 yInfo() << "returning null ";
1078 }
1079
1080 return false;
1081}
1082
1083/**********************************************************/
1085{
1086 QTreeWidgetItem *row = nullptr;
1087 row = getRowByPart(QString("%1").arg(szName));
1088 if(row){
1089 row->setText(SAMPLERATE,QString("%1 ms").arg(frameRate));
1090 return true;
1091 }
1092
1093 return false;
1094}
1095
1096/**********************************************************/
1097bool MainWindow::setTimeTaken(const char* szName, double time)
1098{
1099 QTreeWidgetItem *row = nullptr;
1100 row = getRowByPart(QString("%1").arg(szName));
1101 if(row){
1102 row->setText(TIMETAKEN,QString("%1 s").arg(time, 0, 'f', 3));
1103 return true;
1104 }
1105
1106 return false;
1107}
1108
1109/**********************************************************/
1111{
1112 if(pressed){
1113 return;
1114 }
1115 ui->playSlider->setValue(percentage);
1116}
1117
1118/**********************************************************/
1119void MainWindow::onUpdateGuiRateThread()
1120{
1121 for (int i=0; i < subDirCnt; i++){
1122 //TODO SIGNAL
1123 if (getPartActivation(qutilities->partDetails[i].name.c_str()) ){
1124 if ( qutilities->partDetails[i].bot.get(1).asList()->get(2).isString() && qutilities->partDetails[i].type == "Bottle"){
1125 //avoid checking frame rate for string data
1126 setFrameRate(qutilities->partDetails[i].name.c_str(), 0);
1127 } else {
1128 if (qutilities->partDetails[i].currFrame <= qutilities->partDetails[i].maxFrame + 1){
1129 int rate = (int)qutilities->partDetails[i].worker->getFrameRate();
1130 setFrameRate(qutilities->partDetails[i].name.c_str(),rate);
1131 double time = qutilities->partDetails[i].worker->getTimeTaken();
1132 if (time > 700000){ //value of a time stamp...
1133 setTimeTaken(qutilities->partDetails[i].name.c_str(),0.0);
1134 } else {
1135 setTimeTaken(qutilities->partDetails[i].name.c_str(), time);
1136 }
1137 }
1138 }
1139 //percentage = 0;
1140 percentage = ( qutilities->partDetails[i].currFrame *100 ) / qutilities->partDetails[i].maxFrame;
1141 setPartProgress( qutilities->partDetails[i].name.c_str(), percentage );
1142
1143 //LOG( "part %d is at frame %d of %d therefore %d\n",i, qutilities->partDetails[i].currFrame, qutilities->partDetails[i].maxFrame, percentage);
1144 }
1145 if(i == 0){
1146 setPlayProgress(percentage);
1147 }
1148 }
1149}
1150
1151/**********************************************************/
1152void MainWindow::goToPercentage(int value)
1153{
1154 qutilities->qengine->goToPercentage(value);
1155}
1156
1157/**********************************************************/
1158void MainWindow::onClose()
1159{
1160 //just send the closing event
1161 QMainWindow::close();
1162}
1163
1164/**********************************************************/
1166 QString newPath,
1167 std::vector<yarp::yarpDataplayer::RowInfo>& rowInfoVec,
1168 QObject *parent) : QThread(parent),
1169 qutilities(qutilities),
1170 newPath(std::move(newPath)),
1171 mainWindow(dynamic_cast<QMainWindow*> (parent)),
1172 rowInfoVec(rowInfoVec)
1173{
1174}
1175
1176/**********************************************************/
1178{
1179 qutilities->resetMaxTimeStamp();
1180 int subDirCnt = qutilities->getRecSubDirList(newPath.toLatin1().data(), rowInfoVec, 1);
1181 if (qutilities->verbose) {
1182 yInfo() << "the size of subDirs is: " << subDirCnt;
1183 }
1184 //reset totalSent to 0
1185 qutilities->totalSent = 0;
1186 qutilities->totalThreads = subDirCnt;
1187
1188 if (subDirCnt > 0){
1189 qutilities->partDetails = new yarp::yarpDataplayer::PartsData [subDirCnt];//resize(subDirCnt);
1190 }
1191
1192 //fill in parts with all data
1193 for (int x=0; x < subDirCnt; x++){
1194 qutilities->partDetails[x].name = rowInfoVec[x].name;
1195 qutilities->partDetails[x].infoFile = rowInfoVec[x].info;
1196 qutilities->partDetails[x].logFile = rowInfoVec[x].log;
1197 qutilities->partDetails[x].path = rowInfoVec[x].path;
1198
1199 qutilities->setupDataFromParts(qutilities->partDetails[x]);
1200
1201 qutilities->partDetails[x].worker = new yarp::yarpDataplayer::DataplayerWorker(x, subDirCnt);
1202 qutilities->partDetails[x].worker->setManager(qutilities);
1203 }
1204
1205 //get the max timestamp of all the parts for synchronization
1206 if (subDirCnt > 0){
1207 qutilities->getMaxTimeStamp();
1208 }
1209
1210 if (subDirCnt > 0){
1211 qutilities->getMinTimeStamp();
1212 }
1213
1214 //set initial frames for all parts depending on first timestamps
1215 for (int x=0; x < subDirCnt; x++){
1216 qutilities->initialFrame.push_back( qutilities->partDetails[x].currFrame);
1217
1218 double totalTime = 0.0;
1219 double final = qutilities->partDetails[x].timestamp[qutilities->partDetails[x].timestamp.length()-1];
1220 double initial = qutilities->partDetails[x].timestamp[qutilities->partDetails[x].currFrame];
1221
1222 //LOG("initial timestamp is = %lf\n", initial);
1223 //LOG("final timestamp is = %lf\n", final);
1224
1225 totalTime = final - initial;
1226
1227 if (qutilities->verbose){
1228 yInfo() << "The part " << qutilities->partDetails[x].name.c_str() << " should last for: " << totalTime << " with " << qutilities->partDetails[x].maxFrame << " frames";
1229 }
1230
1231 }
1232
1233 qutilities->qengine = new QEngine(qutilities, subDirCnt, mainWindow);
1234
1235// connect(masterThread,SIGNAL(updateGuiRateThread()),this,SLOT(onUpdateGuiRateThread()),Qt::QueuedConnection);
1236 qutilities->qengine->stepfromCmd = false;
1237
1238 emit initDone(subDirCnt);
1239}
#define yInfo(...)
Definition Log.h:319
#define yError(...)
Definition Log.h:361
@ PORT
Definition MainWindow.h:20
int SIGNAL(int pid, int signum)
void initDone(int subDirCount)
InitThread(QUtilities *qutilities, QString newPath, std::vector< yarp::yarpDataplayer::RowInfo > &rowInfoVec, QObject *parent=0)
void run() override
MainWindow class.
Definition display.h:22
bool quit() override
function that handles an IDL message - quit
void closeEvent(QCloseEvent *event) override
void stepFromCommand(yarp::os::Bottle &reply)
function steps datasets when requeted from terminal
void internalSetFrame(const int frameNum)
MainWindow(const yarp::os::ResourceFinder &rf, yarp::dev::IBattery *ibat, QWidget *parent=0, double refresh_period=10.0)
Definition display.cpp:186
bool setFrame(const int frameNum) override
function that handles an IDL message - setFrame
bool pause() override
function that handles an IDL message - pause
bool stop() override
function that handles an IDL message - stop
bool getPartActivation(const char *szName)
function that gets which parts are activated
bool load(const std::string &path) override
function that handles an IDL message - load
void addPart(const char *szName, const char *type, int frames, const char *portName, const char *szFileName=NULL)
function that adds a data part to the main window
bool setPartProgress(const char *szName, int percentage)
function that sets the dataset part progress bar
bool setInitialPartProgress(const char *szName, int percentage)
function that sets the initial dataset part progress bar
QUtilities * qutilities
Definition mainwindow.h:198
void internalGetFrame(const std::string &name, int *frame)
void internalGetSliderPercentage(int *percentage)
bool setTimeTaken(const char *szName, double time)
function that sets the time taken
void internalLoad(QString)
int getSliderPercentage() override
function that returns slider percentage
void internalPlay()
bool quitFromCmd
Definition mainwindow.h:204
bool setFrameRate(const char *szName, int frameRate)
function that sets the frame rate
void internalStep(yarp::os::Bottle *reply)
bool getPartPort(const char *szName, QString *dest)
function that handles individual dataset part ports
void setPlayProgress(int percentage)
function that sets the play progress bar
bool updateFrameNumber(int number)
function that updates the frame number
bool step() override
function that that handles an IDL message - step
void createUtilities()
function that creates utilities
void internalQuit()
int getFrame(const std::string &name) override
function that handles an IDL message - getFrame
void clearUtilities()
function that deletes utilities
void internalStop()
std::string getStatus() override
function that returns the player status (playing, paused, stopped)
bool play() override
function that handles an IDL message - play
friend class QUtilities
Definition mainwindow.h:41
void getFrameCmd(const char *part, int *frame)
function that gets the frame command
bool attach(yarp::os::RpcServer &source)
function that that attaches the rpcServer port for IDL
yarp::os::Network yarp
Definition display.h:34
std::map< const char *, int > partMap
Definition mainwindow.h:200
void internalPause()
bool withExtraTimeCol
Definition mainwindow.h:203
QEngine * qengine
Definition utils.h:36
void stepThread()
Definition utils.cpp:54
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
void close() override
Stop port activity.
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition Bottle.cpp:170
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition Bottle.cpp:211
A mini-server for performing network communication in the background.
Helper class for finding config files and other external resources.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
A port that is specialized as an RPC server.
Definition RpcServer.h:23
A single value (typically within a Bottle).
Definition Value.h:43
Definition aboutdlg.h:11
STL namespace.
An interface to the operating system, including Port based communication.
#define YARP_VERSION
Definition version.h:14
#define TIMETAKEN
#define ACTIVE
#define FRAMES
#define SAMPLERATE
#define TYPE
#define PERCENT
void sighandler(int sig)
#define PART
#define APP_NAME