MainWindow.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. // MainWindow.cpp
  2. #include "MainWindow.h"
  3. #include "EquirectangularToFovGaze.h"
  4. #include "EquirectangularToHead.h"
  5. #include "../arffHelper/ArffOps.h"
  6. #include <iostream>
  7. #include <cassert>
  8. using namespace std;
  9. // PUBLIC:
  10. MainWindow::MainWindow() : m_pMainWidget(0), m_pVideoWidget(0), m_pArffWidgetCoordX(0), m_pArffWidgetCoordY(0), m_pArffWidgetSpeed(0), m_pPaintGaze(0), m_pArff(0), m_pFovArff(0), m_openAction(0), m_saveAction(0), m_undoAction(0), m_redoAction(0)
  11. {
  12. InitializeVariables();
  13. InitializeMainWidget();
  14. InitializeMenu();
  15. SetData(0);
  16. }
  17. MainWindow::MainWindow(SetupValues setup) : m_setup(setup), m_pMainWidget(0), m_pVideoWidget(0), m_pArffWidgetCoordX(0), m_pArffWidgetCoordY(0), m_pArffWidgetSpeed(0), m_pPaintGaze(0), m_pArff(0), m_pFovArff(0), m_openAction(0), m_saveAction(0), m_undoAction(0), m_redoAction(0)
  18. {
  19. InitializeVariables();
  20. InitializeMainWidget();
  21. InitializeMenu();
  22. // assign values
  23. m_setup.arffFile = QFileInfo(m_setup.arffFile).absoluteFilePath();
  24. m_setup.saveFile = QFileInfo(m_setup.saveFile).absoluteFilePath();
  25. m_setup.videoFile = QFileInfo(m_setup.videoFile).absoluteFilePath();
  26. // Load Files
  27. if (!m_pVideoWidget->SetMedia(m_setup.videoFile))
  28. exit(-1);
  29. if (!m_pArff->Load(m_setup.arffFile.toStdString().c_str()))
  30. exit(-1);
  31. int primAttPosition = InitializeAtt(m_setup.primaryLabel, m_setup.primaryLabelValues);
  32. SetData(primAttPosition);
  33. if (!m_setup.secondaryLabel.isEmpty())
  34. {
  35. int secAttPosition = InitializeAtt(m_setup.secondaryLabel, m_setup.secondaryLabelValues);
  36. m_pArffSecondWidgetSpeed->SetData(*m_pArff, secAttPosition);
  37. m_pArffSecondWidgetSpeed->SetIntervalAtt(primAttPosition);
  38. m_pArffSecondWidgetY->SetData(*m_pArff, secAttPosition);
  39. m_pArffSecondWidgetY->SetIntervalAtt(primAttPosition);
  40. }
  41. if (m_setup.gazeType == GazeType::FOV)
  42. {
  43. EquirectangularToFovGaze eqToFov(m_pArff.get());
  44. m_pFovArff = eqToFov.Convert();
  45. m_pPaintGaze->SetFovData(*m_pFovArff);
  46. m_pVideoWidget->ConvertToFov(m_pArff.get());
  47. m_pArffWidgetCoordX->SetFovData(*m_pFovArff, m_pFovArff->WidthPx());
  48. m_pArffWidgetCoordY->SetFovData(*m_pFovArff, m_pFovArff->HeightPx());
  49. m_pArffWidgetSpeed->DisplayFov();
  50. emit SendToggleView();
  51. }
  52. else if (m_setup.gazeType == GazeType::HEAD)
  53. {
  54. EquirectangularToHead converter(m_pArff.get());
  55. m_pFovArff = converter.Convert();
  56. m_pPaintGaze->SetFovData(*m_pFovArff);
  57. m_pArffWidgetCoordX->SetFovData(*m_pFovArff, m_pFovArff->WidthPx());
  58. m_pArffWidgetCoordY->SetFovData(*m_pFovArff, m_pFovArff->HeightPx());
  59. m_pArffWidgetSpeed->DisplayHead();
  60. emit SendToggleView();
  61. }
  62. }
  63. MainWindow::~MainWindow()
  64. {
  65. delete m_pMainWidget;
  66. delete m_pVideoWidget;
  67. delete m_pArffWidgetCoordX;
  68. delete m_pArffWidgetCoordY;
  69. delete m_pArffWidgetSpeed;
  70. delete m_pArffSecondWidgetSpeed;
  71. delete m_pArffSecondWidgetY;
  72. delete m_pPaintGaze;
  73. delete m_openAction;
  74. delete m_saveAction;
  75. delete m_undoAction;
  76. delete m_redoAction;
  77. }
  78. // PROTECTED:
  79. void MainWindow::closeEvent(QCloseEvent *event)
  80. {
  81. if (m_pArff->IsDataChanged())
  82. {
  83. // display message box and ask for action
  84. QMessageBox msgBox;
  85. msgBox.setText("Gaze samples have been modified.");
  86. msgBox.setInformativeText("Do you want to save your changes?");
  87. msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
  88. msgBox.setDefaultButton(QMessageBox::Cancel);
  89. int ret = msgBox.exec();
  90. switch (ret) {
  91. case QMessageBox::Save:
  92. SaveArff();
  93. event->accept();
  94. break;
  95. case QMessageBox::Discard:
  96. event->accept();
  97. break;
  98. case QMessageBox::Cancel:
  99. event->ignore();
  100. break;
  101. }
  102. }
  103. else
  104. {
  105. event->accept();
  106. }
  107. }
  108. // PRIVATE:
  109. void MainWindow::InitializeMainWidget()
  110. {
  111. // load static file for beginning
  112. m_pArff = make_shared<Arff>();
  113. m_pVideoWidget = new VideoWidget;
  114. m_pArffWidgetCoordX = new ArffWidgetCoordX;
  115. m_pArffWidgetCoordY = new ArffWidgetCoordY;
  116. m_pArffWidgetSpeed = new ArffWidgetSpeed;
  117. m_pPaintGaze = new PaintGaze;
  118. // connect time signals-slots
  119. ConnectTimeSignals(m_pArffWidgetCoordX);
  120. ConnectTimeSignals(m_pArffWidgetCoordY);
  121. ConnectTimeSignals(m_pArffWidgetSpeed);
  122. ConnectTimeSignals(m_pVideoWidget);
  123. QObject::connect(this, SIGNAL(SendTime(int, QObject*)), m_pPaintGaze, SLOT(HandleTime(int, QObject*)));
  124. ConnectWinDurSignals(m_pArffWidgetCoordX);
  125. ConnectWinDurSignals(m_pArffWidgetCoordY);
  126. ConnectWinDurSignals(m_pArffWidgetSpeed);
  127. ConnectUpdateSignals(m_pArffWidgetCoordX);
  128. ConnectUpdateSignals(m_pArffWidgetCoordY);
  129. ConnectUpdateSignals(m_pArffWidgetSpeed);
  130. ConnectEyeMovementSignals(m_pArffWidgetCoordX);
  131. ConnectEyeMovementSignals(m_pArffWidgetCoordY);
  132. ConnectEyeMovementSignals(m_pArffWidgetSpeed);
  133. ConnectToggleViewSignals(m_pArffWidgetCoordX);
  134. ConnectToggleViewSignals(m_pArffWidgetCoordY);
  135. ConnectToggleViewSignals(m_pArffWidgetSpeed);
  136. ConnectToggleViewSignals(m_pVideoWidget);
  137. ConnectToggleViewSignals(m_pPaintGaze);
  138. QGridLayout *layout = new QGridLayout;
  139. // add widgets to layout
  140. layout->addWidget(m_pVideoWidget,0,0);
  141. layout->addWidget(m_pArffWidgetCoordX,0,1);
  142. layout->addWidget(m_pArffWidgetSpeed,1,0);
  143. layout->addWidget(m_pArffWidgetCoordY,1,1);
  144. layout->setColumnStretch(0,1);
  145. layout->setColumnStretch(1,1);
  146. layout->setRowStretch(0,4);
  147. layout->setRowStretch(1,4);
  148. // install event filter to all widgets
  149. m_pVideoWidget->installEventFilter(this);
  150. m_pArffWidgetCoordX->installEventFilter(this);
  151. m_pArffWidgetCoordY->installEventFilter(this);
  152. m_pArffWidgetSpeed->installEventFilter(this);
  153. // add secondary label widgets
  154. if (!m_setup.secondaryLabel.isEmpty())
  155. {
  156. m_pArffSecondWidgetSpeed = new ArffWidgetBase;
  157. m_pArffSecondWidgetY = new ArffWidgetBase;
  158. ConnectTimeSignals(m_pArffSecondWidgetSpeed);
  159. ConnectTimeSignals(m_pArffSecondWidgetY);
  160. ConnectWinDurSignals(m_pArffSecondWidgetSpeed);
  161. ConnectWinDurSignals(m_pArffSecondWidgetY);
  162. ConnectUpdateSignals(m_pArffSecondWidgetSpeed);
  163. ConnectUpdateSignals(m_pArffSecondWidgetY);
  164. ConnectEyeMovementSignals(m_pArffSecondWidgetSpeed);
  165. ConnectEyeMovementSignals(m_pArffSecondWidgetY);
  166. layout->addWidget(m_pArffSecondWidgetSpeed,2,0);
  167. layout->addWidget(m_pArffSecondWidgetY,2,1);
  168. layout->setRowStretch(2, 1);
  169. m_pArffSecondWidgetSpeed->installEventFilter(this);
  170. m_pArffSecondWidgetY->installEventFilter(this);
  171. }
  172. // create main widget
  173. m_pMainWidget = new QWidget;
  174. m_pMainWidget->setLayout(layout);
  175. setCentralWidget(m_pMainWidget);
  176. }
  177. void MainWindow::ConnectTimeSignals(const QObject *pObject)
  178. {
  179. QObject::connect(pObject, SIGNAL(SendTime(int)), this, SLOT(HandleTime(int)));
  180. QObject::connect(this, SIGNAL(SendTime(int, QObject*)), pObject, SLOT(HandleTime(int, QObject*)));
  181. }
  182. void MainWindow::ConnectWinDurSignals(const QObject *pObject)
  183. {
  184. QObject::connect(pObject, SIGNAL(SendWindowDur(int)), this, SLOT(HandleWindowDur(int)));
  185. QObject::connect(this, SIGNAL(SendWindowDur(int, QObject*)), pObject, SLOT(HandleWindowDur(int, QObject*)));
  186. }
  187. void MainWindow::ConnectUpdateSignals(const QObject *pObject)
  188. {
  189. QObject::connect(pObject, SIGNAL(SendUpdate()), this, SLOT(HandleUpdate()));
  190. QObject::connect(this, SIGNAL(SendUpdate()), pObject, SLOT(HandleUpdate()));
  191. }
  192. void MainWindow::ConnectEyeMovementSignals(const QObject *pObject)
  193. {
  194. QObject::connect(this, SIGNAL(SendSelectedEyeMovement(int)), pObject, SLOT(HandleSelectedEyeMovement(int)));
  195. }
  196. void MainWindow::ConnectToggleViewSignals(const QObject *pObject)
  197. {
  198. QObject::connect(this, SIGNAL(SendToggleView()), pObject, SLOT(HandleToggleView()));
  199. }
  200. void MainWindow::InitializeVariables()
  201. {
  202. path = QDir::current();
  203. }
  204. void MainWindow::InitializeMenu()
  205. {
  206. // create new statusbar. Otherwise it is not visible
  207. QStatusBar* status = new QStatusBar(this);
  208. setStatusBar(status);
  209. // making menu non native makes it visible in ubuntu
  210. menuBar()->setNativeMenuBar(false);
  211. // create actions
  212. m_openAction = new QAction(tr("&Open"), this);
  213. m_openAction->setShortcuts(QKeySequence::Open);
  214. m_openAction->setStatusTip(tr("Open video and Arff files"));
  215. connect(m_openAction, SIGNAL(triggered()), this, SLOT(OpenFiles()));
  216. m_saveAction = new QAction(tr("&Save"), this);
  217. m_saveAction->setShortcuts(QKeySequence::Save);
  218. m_saveAction->setStatusTip(tr("Save Arff to file"));
  219. connect(m_saveAction, &QAction::triggered, this, &MainWindow::SaveArff);
  220. m_saveAsAction = new QAction(tr("Save&As"), this);
  221. m_saveAsAction->setShortcuts(QKeySequence::SaveAs);
  222. m_saveAsAction->setStatusTip(tr("Save Arff to new file"));
  223. connect(m_saveAsAction, &QAction::triggered, this, &MainWindow::SaveAsArff);
  224. m_undoAction = new QAction(tr("&Undo"), this);
  225. m_undoAction->setShortcuts(QKeySequence::Undo);
  226. m_undoAction->setStatusTip(tr("Undo last change"));
  227. connect(m_undoAction, &QAction::triggered, this, &MainWindow::Undo);
  228. m_redoAction = new QAction(tr("&Redo"), this);
  229. m_redoAction->setShortcuts(QKeySequence::Redo);
  230. m_redoAction->setStatusTip(tr("Redo last change"));
  231. connect(m_redoAction, &QAction::triggered, this, &MainWindow::Redo);
  232. m_fileMenu = menuBar()->addMenu(tr("&File"));
  233. m_fileMenu->addAction(m_openAction);
  234. m_fileMenu->addAction(m_saveAction);
  235. m_fileMenu->addAction(m_saveAsAction);
  236. m_editMenu = menuBar()->addMenu(tr("&Edit"));
  237. m_editMenu->addAction(m_undoAction);
  238. m_editMenu->addAction(m_redoAction);
  239. }
  240. int MainWindow::InitializeAtt(QString name, QString values)
  241. {
  242. // check for hand labelling attribute use and prompt user for action
  243. if (!UseAttributeDialog(name))
  244. exit(-1);
  245. int attPosition;
  246. bool res = m_pArff->GetAttIndex(name.toStdString().c_str(), attPosition);
  247. if (!res)
  248. {
  249. if (values.isEmpty())
  250. // Get majority vote of attributes
  251. ArffOps::MajorityVote(m_pArff.get(), name.toStdString().c_str()); // add mode att the last column
  252. else
  253. m_pArff->AddColumn(name.toStdString(), values.toStdString());
  254. int rows, columns;
  255. m_pArff->Size(rows, columns);
  256. attPosition = columns-1;
  257. }
  258. else
  259. {
  260. cout << "WARNING: attribute '" << name.toStdString() << "' already in use." << endl;
  261. }
  262. return attPosition;
  263. }
  264. void MainWindow::SetData(int attIndex)
  265. {
  266. // Set time to the beginning of both video and gaze
  267. // Set max limits on each after reloading
  268. m_pArffWidgetCoordX->SetData(*m_pArff, attIndex, m_pArff->WidthPx());
  269. m_pArffWidgetCoordY->SetData(*m_pArff, attIndex, m_pArff->HeightPx());
  270. m_pArffWidgetSpeed->SetData(*m_pArff, attIndex);
  271. m_pVideoWidget->SetGazePaint(m_pPaintGaze);
  272. m_pVideoWidget->SetCurrentTime(0);
  273. m_pPaintGaze->SetData(*m_pArff);
  274. }
  275. void MainWindow::keyPressEvent(QKeyEvent *event)
  276. {
  277. if (!ProcessKeyPress(event))
  278. QMainWindow::keyPressEvent(event);
  279. }
  280. bool MainWindow::eventFilter(QObject *watched, QEvent *event)
  281. {
  282. if (event->type() == QEvent::KeyPress)
  283. {
  284. QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
  285. if (ProcessKeyPress(keyEvent))
  286. return true;
  287. }
  288. return QObject::eventFilter(watched, event);
  289. }
  290. bool MainWindow::ProcessKeyPress(QKeyEvent *event)
  291. {
  292. statusBar()->showMessage(tr(""));
  293. int key = event->key();
  294. int key_0 = 0x30; // Qt::Key_0
  295. int key_9 = 0x39; // Qt::Key_9
  296. int mask = 0x0F;
  297. if (key >= key_0 && key <= key_9)
  298. {
  299. int eyeMovement = key & mask;
  300. emit SendSelectedEyeMovement(eyeMovement);
  301. return true;
  302. }
  303. else if (key == Qt::Key_Space)
  304. {
  305. m_pVideoWidget->TogglePlayer();
  306. return true;
  307. }
  308. else if (key == Qt::Key_T)
  309. {
  310. emit SendToggleView();
  311. return true;
  312. }
  313. else
  314. return false;
  315. }
  316. bool MainWindow::UseAttributeDialog(QString attName)
  317. {
  318. int tmpPos;
  319. if (m_pArff->GetAttIndex(attName.toStdString().c_str(), tmpPos))
  320. {
  321. QMessageBox::StandardButton reply;
  322. string message = "Do you still want to use attribute '" + attName.toStdString() + "'?";
  323. reply = QMessageBox::question(this, "Attribute already exists", message.c_str(), QMessageBox::Yes|QMessageBox::No);
  324. if (reply == QMessageBox::Yes){
  325. return true;
  326. }
  327. else{
  328. return false;
  329. }
  330. }
  331. return true;
  332. }
  333. // PRIVATE SLOTS:
  334. void MainWindow::SaveArff()
  335. {
  336. if (m_setup.saveFile.isEmpty())
  337. {
  338. m_setup.saveFile = QFileDialog::getSaveFileName(this, tr("Save File"),
  339. path.path(), tr("Arff files (*.arff *.txt)"));
  340. // update path
  341. path = QFileInfo(m_setup.saveFile).dir();
  342. }
  343. // handle canceled window case
  344. if (!m_setup.saveFile.isEmpty())
  345. {
  346. m_pArff->Save(m_setup.saveFile.toStdString().c_str());
  347. statusBar()->showMessage(tr("Saved"));
  348. }
  349. else
  350. {
  351. statusBar()->showMessage(tr("Could not save Arff file"));
  352. }
  353. }
  354. void MainWindow::SaveAsArff()
  355. {
  356. m_setup.saveFile.clear();
  357. SaveArff();
  358. }
  359. void MainWindow::OpenFiles()
  360. {
  361. // first check for unsaved changes
  362. if (m_pArff->IsDataChanged())
  363. {
  364. // display message box and ask for action
  365. QMessageBox msgBox;
  366. msgBox.setText("Gaze samples have been modified.");
  367. msgBox.setInformativeText("Do you want to save your changes?");
  368. msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
  369. msgBox.setDefaultButton(QMessageBox::Cancel);
  370. int ret = msgBox.exec();
  371. switch (ret)
  372. {
  373. case QMessageBox::Save:
  374. SaveArff();
  375. break;
  376. case QMessageBox::Discard:
  377. // do nothing
  378. break;
  379. case QMessageBox::Cancel:
  380. return;
  381. break;
  382. }
  383. }
  384. m_setup.videoFile = QFileDialog::getOpenFileName(this, tr("Open Video File"),
  385. path.path(), tr("Video files (*.m2t *.avi *.mp4 *.wmv)"));
  386. // return if file is empty
  387. if (m_setup.videoFile.isEmpty())
  388. return;
  389. // update path
  390. path = QFileInfo(m_setup.videoFile).dir();
  391. m_setup.arffFile = QFileDialog::getOpenFileName(this, tr("Open Arff File"),
  392. path.path(), tr("Arff files (*.arff *.txt)"));
  393. if (m_setup.arffFile.isEmpty())
  394. return;
  395. // update path
  396. path = QFileInfo(m_setup.arffFile).dir();
  397. m_pVideoWidget->SetMedia(m_setup.videoFile);
  398. m_pArff->Load(m_setup.arffFile.toStdString().c_str());
  399. bool accepted=false;
  400. do
  401. {
  402. // check if name for hand labelling attribute exists
  403. if (m_setup.primaryLabel.isEmpty())
  404. {
  405. m_setup.primaryLabel = QInputDialog::getText(this, tr("Hande labeller name"), tr("Attribute name:"), QLineEdit::Normal, QDir::home().dirName(), &accepted);
  406. // remove whitespace from input value
  407. m_setup.primaryLabel = m_setup.primaryLabel.simplified();
  408. m_setup.primaryLabel.replace(" ", "");
  409. // if canceled or empty string provided return
  410. if (!accepted || m_setup.primaryLabel.isEmpty())
  411. return;
  412. }
  413. // check for hand labelling attribute use
  414. accepted = UseAttributeDialog(m_setup.primaryLabel);
  415. if (!accepted)
  416. m_setup.primaryLabel.clear();
  417. }
  418. while(!accepted);
  419. int attPosition;
  420. bool res = m_pArff->GetAttIndex(m_setup.primaryLabel.toStdString().c_str(), attPosition);
  421. if (!res){
  422. // Get majority vote for of attributes
  423. ArffOps::MajorityVote(m_pArff.get(), m_setup.primaryLabel.toStdString().c_str()); // add mode att the last column
  424. int rows, columns;
  425. m_pArff->Size(rows, columns);
  426. attPosition = columns-1;
  427. }
  428. SetData(attPosition);
  429. }
  430. void MainWindow::Undo()
  431. {
  432. m_pArff->UndoLastChange();
  433. emit SendUpdate();
  434. statusBar()->showMessage(tr("Last change reverted"));
  435. }
  436. void MainWindow::Redo()
  437. {
  438. m_pArff->RedoLastChange();
  439. emit SendUpdate();
  440. statusBar()->showMessage(tr("Last change remade"));
  441. }
  442. void MainWindow::HandleTime(int curTime_us)
  443. {
  444. QObject *pSender = sender();
  445. emit SendTime(curTime_us, pSender);
  446. }
  447. void MainWindow::HandleWindowDur(int dur_us)
  448. {
  449. QObject *pSender = sender();
  450. emit SendWindowDur(dur_us, pSender);
  451. }
  452. void MainWindow::HandleUpdate()
  453. {
  454. emit SendUpdate();
  455. }