diff --git a/.gitignore b/.gitignore index 8b9398b8..cff85ba5 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,5 @@ CMakeFiles *.cache *.csv build +biotracker_workspace.code-workspace +*.code-workspace diff --git a/Src/CMakeLists.txt b/Src/CMakeLists.txt index 42c290de..ebecf41c 100644 --- a/Src/CMakeLists.txt +++ b/Src/CMakeLists.txt @@ -215,6 +215,7 @@ PRIVATE "View/AreaDesciptor/AreaDescriptor.cpp" "View/AreaDesciptor/EllipseDescriptor.cpp" "View/AreaDesciptor/RectDescriptor.cpp" + "View/AreaDesciptor/PolygonDescriptor.cpp" "View/AnnotationsView.cpp" "View/CameraDevice.cpp" "View/ComponentShape.cpp" diff --git a/Src/Controller/ControllerAnnotations.cpp b/Src/Controller/ControllerAnnotations.cpp index d4dce888..91019fbc 100644 --- a/Src/Controller/ControllerAnnotations.cpp +++ b/Src/Controller/ControllerAnnotations.cpp @@ -25,7 +25,7 @@ void ControllerAnnotations::cleanup() { delete getModel(); } -void ControllerAnnotations::reset(std::string filepath) +void ControllerAnnotations::reset(std::string filepath, int batchIndex) { // Replace the model with a fresh one. delete getModel(); diff --git a/Src/Controller/ControllerAnnotations.h b/Src/Controller/ControllerAnnotations.h index 4dd44906..7e95a365 100644 --- a/Src/Controller/ControllerAnnotations.h +++ b/Src/Controller/ControllerAnnotations.h @@ -29,7 +29,7 @@ class ControllerAnnotations : public IControllerCfg public Q_SLOTS: /// - void reset(std::string filepath); + void reset(std::string filepath, int batchIndex = 0); void mousePressEvent(QMouseEvent *event, const QPoint &pos); void mouseReleaseEvent(QMouseEvent*event, const QPoint &pos); void mouseMoveEvent(QMouseEvent*event, const QPoint &pos); diff --git a/Src/Controller/ControllerAreaDescriptor.cpp b/Src/Controller/ControllerAreaDescriptor.cpp index 6e2b0af1..001e3347 100644 --- a/Src/Controller/ControllerAreaDescriptor.cpp +++ b/Src/Controller/ControllerAreaDescriptor.cpp @@ -4,6 +4,7 @@ #include "View/AreaDesciptor/AreaDescriptor.h" #include "View/AreaDesciptor/RectDescriptor.h" #include "View/AreaDesciptor/EllipseDescriptor.h" +#include "View/AreaDesciptor/PolygonDescriptor.h" #include "util/types.h" #include "ControllerGraphicScene.h" @@ -16,6 +17,7 @@ #include "Model/AreaDescriptor/AreaMemory.h" using namespace AreaMemory; +using namespace BioTrackerUtilsMisc; //split ControllerAreaDescriptor::ControllerAreaDescriptor(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : IControllerCfg(parent, context, ctr) @@ -48,6 +50,11 @@ void ControllerAreaDescriptor::createView() int v = _cfg->AppertureType; trackingAreaType(v); + + // set the rectification dimensions + double h = std::max(_cfg->RectificationHeight, std::numeric_limits::epsilon()); + double w = std::max(_cfg->RectificationWidth, std::numeric_limits::epsilon()); + setRectificationDimensions(w, h); } void ControllerAreaDescriptor::connectModelToController() @@ -76,7 +83,7 @@ void ControllerAreaDescriptor::trackingAreaType(int v) { QObject::connect(this, &ControllerAreaDescriptor::currentVectorDrag, static_cast(m_ViewApperture), &RectDescriptor::receiveDragUpdate); _cfg->AppertureType = 0; } - else if (v > 0) { + else if (v == 1) { m_ViewApperture = new EllipseDescriptor(this, area->_apperture.get()); area->_apperture->setType(1); static_cast(m_ViewApperture)->setBrush(QBrush(Qt::red)); @@ -84,6 +91,15 @@ void ControllerAreaDescriptor::trackingAreaType(int v) { QObject::connect(this, &ControllerAreaDescriptor::currentVectorDrag, static_cast(m_ViewApperture), &EllipseDescriptor::receiveDragUpdate); _cfg->AppertureType = 1; } + else if (v == 2) { + m_ViewApperture = new PolygonDescriptor(this, area->_apperture.get()); + area->_apperture->setType(2); + static_cast(m_ViewApperture)->setBrush(QBrush(Qt::red)); + static_cast(m_ViewApperture)->setDimensions(_w, _h); + QObject::connect(this, &ControllerAreaDescriptor::currentVectorDrag, static_cast(m_ViewApperture), &PolygonDescriptor::receiveDragUpdate); + _cfg->AppertureType = 2; + } + if (!_visibleApperture) static_cast(m_ViewApperture)->hide(); @@ -110,9 +126,24 @@ void ControllerAreaDescriptor::rcvPlayerParameters(playerParameters* parameters) ad->setDimensions(_w, _h); } QVector v = getVertices(_currentFilename, _cfg->AreaDefinitions); + std::string v1_string = v[1].toStdString(); if (!v.empty()) { + setTrackingAreaType(v[2].toInt()); changeAreaDescriptorType(v[2]); + std::vector strVerts; + int numberOfVerts = 4; + if(v[2].toInt() == 2){ + numberOfVerts = split(v1_string, strVerts, ';'); + } + changeNumberOfVerts(numberOfVerts); } + + AreaInfo* area = dynamic_cast(getModel()); + std::vector pts = stringToCVPointVec(v1_string); + area->_apperture->setVertices(pts); + // updateView(); + + triggerUpdateAreaDescriptor(); } } @@ -141,6 +172,7 @@ void ControllerAreaDescriptor::connectControllerToController() IController* ctrParms = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); auto parmsController = qobject_cast(ctrParms); QObject::connect(this, &ControllerAreaDescriptor::changeAreaDescriptorType, parmsController, &ControllerCoreParameter::changeAreaDescriptorType, Qt::DirectConnection); + QObject::connect(this, &ControllerAreaDescriptor::changeNumberOfVerts, parmsController, &ControllerCoreParameter::changeNumberOfVerts, Qt::DirectConnection); AreaInfo* area = dynamic_cast(getModel()); @@ -260,7 +292,9 @@ void ControllerAreaDescriptor::setRectificationDimensions(double w, double h) { triggerUpdateAreaDescriptor(); RectDescriptor* rd = static_cast(getView()); - rd->updateRect(); + if(rd){ + rd->updateRect(); + } } void ControllerAreaDescriptor::setDisplayRectificationDefinition(bool b) { @@ -275,14 +309,21 @@ void ControllerAreaDescriptor::setDisplayTrackingAreaDefinition(bool b) { ad->setVisible(b); } -void ControllerAreaDescriptor::setTrackingAreaAsEllipse(bool b) { - //Not passing b as a parameter for clarification reasons - if (b) { - trackingAreaType(1); - } - else { - trackingAreaType(0); - } +// void ControllerAreaDescriptor::setTrackingAreaAsEllipse(bool b) { +// //Not passing b as a parameter for clarification reasons +// if (b) { +// trackingAreaType(1); +// } +// else { +// trackingAreaType(0); +// } +// } + +void ControllerAreaDescriptor::setTrackingAreaType(int type) { + trackingAreaType(type); } - +void ControllerAreaDescriptor::setTrArNumberOfVertices(int v) { + AreaInfo* area = dynamic_cast(getModel()); + area->_apperture->changeTrArNumberOfVertices(v); +} \ No newline at end of file diff --git a/Src/Controller/ControllerAreaDescriptor.h b/Src/Controller/ControllerAreaDescriptor.h index dc885d19..be2e205d 100644 --- a/Src/Controller/ControllerAreaDescriptor.h +++ b/Src/Controller/ControllerAreaDescriptor.h @@ -19,12 +19,15 @@ class ControllerAreaDescriptor : public IControllerCfg void updateAreaDescriptor(IModelAreaDescriptor *ad); void currentVectorDrag(BiotrackerTypes::AreaType vectorType, int id, double x, double y); void changeAreaDescriptorType(QString type); + void changeNumberOfVerts(int i); public slots: void setRectificationDimensions(double w, double h); void setDisplayRectificationDefinition(bool b); void setDisplayTrackingAreaDefinition(bool b); - void setTrackingAreaAsEllipse(bool b); + // void setTrackingAreaAsEllipse(bool b); + void setTrackingAreaType(int type); + void setTrArNumberOfVertices(int v); void rcvPlayerParameters(playerParameters* parameters); private slots: diff --git a/Src/Controller/ControllerCommands.cpp b/Src/Controller/ControllerCommands.cpp index 542447e1..3d4bacce 100644 --- a/Src/Controller/ControllerCommands.cpp +++ b/Src/Controller/ControllerCommands.cpp @@ -12,9 +12,9 @@ ControllerCommands::~ControllerCommands() void ControllerCommands::receiveAddTrackCommand(QPoint pos, int id) { AddTrackCommand* addCmd = new AddTrackCommand(id, pos); - QObject::connect(addCmd, &AddTrackCommand::emitAddTrajectory, this, &ControllerCommands::emitAddTrajectory); - QObject::connect(addCmd, &AddTrackCommand::emitValidateTrajectory, this, &ControllerCommands::emitValidateTrajectory); - QObject::connect(addCmd, &AddTrackCommand::emitRemoveTrajectoryId, this, &ControllerCommands::emitRemoveTrajectoryId); + QObject::connect(addCmd, &AddTrackCommand::emitAddTrajectory, this, &ControllerCommands::emitAddTrajectory, Qt::DirectConnection); + QObject::connect(addCmd, &AddTrackCommand::emitValidateTrajectory, this, &ControllerCommands::emitValidateTrajectory, Qt::DirectConnection); + QObject::connect(addCmd, &AddTrackCommand::emitRemoveTrajectoryId, this, &ControllerCommands::emitRemoveTrajectoryId, Qt::DirectConnection); _undoStack->push(addCmd); } @@ -22,8 +22,8 @@ void ControllerCommands::receiveAddTrackCommand(QPoint pos, int id) { void ControllerCommands::receiveRemoveTrackCommand(IModelTrackedTrajectory * traj) { RemoveTrackCommand* rmtCmd = new RemoveTrackCommand(traj); - QObject::connect(rmtCmd, &RemoveTrackCommand::emitValidateTrajectory, this, &ControllerCommands::emitValidateTrajectory); - QObject::connect(rmtCmd, &RemoveTrackCommand::emitRemoveTrajectory, this, &ControllerCommands::emitRemoveTrajectory); + QObject::connect(rmtCmd, &RemoveTrackCommand::emitValidateTrajectory, this, &ControllerCommands::emitValidateTrajectory, Qt::DirectConnection); + QObject::connect(rmtCmd, &RemoveTrackCommand::emitRemoveTrajectory, this, &ControllerCommands::emitRemoveTrajectory, Qt::DirectConnection); _undoStack->push(rmtCmd); } @@ -31,8 +31,8 @@ void ControllerCommands::receiveRemoveTrackCommand(IModelTrackedTrajectory * tra void ControllerCommands::receiveRemoveTrackEntityCommand(IModelTrackedTrajectory * traj, uint frameNumber) { RemoveElementCommand* rmeCmd = new RemoveElementCommand(traj, frameNumber); - QObject::connect(rmeCmd, &RemoveElementCommand::emitValidateEntity, this, &ControllerCommands::emitValidateEntity); - QObject::connect(rmeCmd, &RemoveElementCommand::emitRemoveElement, this, &ControllerCommands::emitRemoveTrackEntity); + QObject::connect(rmeCmd, &RemoveElementCommand::emitValidateEntity, this, &ControllerCommands::emitValidateEntity, Qt::DirectConnection); + QObject::connect(rmeCmd, &RemoveElementCommand::emitRemoveElement, this, &ControllerCommands::emitRemoveTrackEntity, Qt::DirectConnection); _undoStack->push(rmeCmd); } @@ -40,7 +40,7 @@ void ControllerCommands::receiveRemoveTrackEntityCommand(IModelTrackedTrajectory void ControllerCommands::receiveMoveElementCommand(IModelTrackedTrajectory* traj, QPoint oldPos, QPoint newPos, uint frameNumber, int toMove) { MoveElementCommand* mvCmd = new MoveElementCommand(traj, frameNumber, oldPos, newPos, toMove); - QObject::connect(mvCmd, &MoveElementCommand::emitMoveElement, this, &ControllerCommands::emitMoveElement); + QObject::connect(mvCmd, &MoveElementCommand::emitMoveElement, this, &ControllerCommands::emitMoveElement, Qt::DirectConnection); _undoStack->push(mvCmd); } @@ -48,7 +48,7 @@ void ControllerCommands::receiveMoveElementCommand(IModelTrackedTrajectory* traj void ControllerCommands::receiveSwapIdCommand(IModelTrackedTrajectory * traj0, IModelTrackedTrajectory * traj1) { SwapTrackIdCommand* swapCmd = new SwapTrackIdCommand(traj0, traj1); - QObject::connect(swapCmd, &SwapTrackIdCommand::emitSwapIds, this, &ControllerCommands::emitSwapIds); + QObject::connect(swapCmd, &SwapTrackIdCommand::emitSwapIds, this, &ControllerCommands::emitSwapIds, Qt::DirectConnection); _undoStack->push(swapCmd); } @@ -56,7 +56,7 @@ void ControllerCommands::receiveSwapIdCommand(IModelTrackedTrajectory * traj0, I void ControllerCommands::receiveFixTrackCommand(IModelTrackedTrajectory * traj, bool toggle) { FixTrackCommand* fixCmd = new FixTrackCommand(traj, toggle); - QObject::connect(fixCmd, &FixTrackCommand::emitFixTrack, this, &ControllerCommands::emitToggleFixTrack); + QObject::connect(fixCmd, &FixTrackCommand::emitFixTrack, this, &ControllerCommands::emitToggleFixTrack, Qt::DirectConnection); _undoStack->push(fixCmd); } @@ -64,7 +64,7 @@ void ControllerCommands::receiveFixTrackCommand(IModelTrackedTrajectory * traj, void ControllerCommands::receiveEntityRotation(IModelTrackedTrajectory * traj,double oldAngleDeg, double newAngleDeg, uint frameNumber) { RotateEntityCommand* rotCmd = new RotateEntityCommand(traj, oldAngleDeg, newAngleDeg, frameNumber); - QObject::connect(rotCmd, &RotateEntityCommand::emitEntityRotation, this, &ControllerCommands::emitEntityRotation); + QObject::connect(rotCmd, &RotateEntityCommand::emitEntityRotation, this, &ControllerCommands::emitEntityRotation, Qt::DirectConnection); _undoStack->push(rotCmd); } @@ -85,7 +85,7 @@ void ControllerCommands::receiveRedo() _undoStack->redo(); } else { - qDebug() << "CORE: Csannot redo the next command!"; + qDebug() << "CORE: Cannot redo the next command!"; } } diff --git a/Src/Controller/ControllerCoreParameter.cpp b/Src/Controller/ControllerCoreParameter.cpp index 3b425cfa..cd519fae 100644 --- a/Src/Controller/ControllerCoreParameter.cpp +++ b/Src/Controller/ControllerCoreParameter.cpp @@ -29,7 +29,8 @@ void ControllerCoreParameter::connectModelToController() void ControllerCoreParameter::connectControllerToController() { - CoreParameterView* view = static_cast(m_View);view->triggerUpdate(); + CoreParameterView* view = static_cast(m_View); + view->triggerUpdate(); //Connections to the trackedComponentCore { IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); @@ -82,7 +83,9 @@ void ControllerCoreParameter::connectControllerToController() QObject::connect(view, &CoreParameterView::emitRectDimensions, adController, &ControllerAreaDescriptor::setRectificationDimensions, Qt::DirectConnection); QObject::connect(view, &CoreParameterView::emitDisplayTrackingArea, adController, &ControllerAreaDescriptor::setDisplayTrackingAreaDefinition, Qt::DirectConnection); QObject::connect(view, &CoreParameterView::emitDisplayRectification, adController, &ControllerAreaDescriptor::setDisplayRectificationDefinition, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTrackingAreaAsEllipse, adController, &ControllerAreaDescriptor::setTrackingAreaAsEllipse, Qt::DirectConnection); + // QObject::connect(view, &CoreParameterView::emitTrackingAreaAsEllipse, adController, &ControllerAreaDescriptor::setTrackingAreaAsEllipse, Qt::DirectConnection); + QObject::connect(view, &CoreParameterView::emitTrackingAreaType, adController, &ControllerAreaDescriptor::setTrackingAreaType, Qt::DirectConnection); + QObject::connect(view, &CoreParameterView::emitTrArNumberOfVertices, adController, &ControllerAreaDescriptor::setTrArNumberOfVertices, Qt::DirectConnection); } //Connections to the Annotations @@ -130,6 +133,11 @@ void ControllerCoreParameter::changeAreaDescriptorType(QString type) { dynamic_cast(m_View)->areaDescriptorTypeChanged(type); } +void ControllerCoreParameter::changeNumberOfVerts(int i) { + if (dynamic_cast(m_View)) + dynamic_cast(m_View)->trAreaNumberOfVertsChanged(i); +} + void ControllerCoreParameter::receiveResetTrial() { CoreParameterView* view = static_cast(m_View); diff --git a/Src/Controller/ControllerCoreParameter.h b/Src/Controller/ControllerCoreParameter.h index 87e5c093..7b5726a5 100644 --- a/Src/Controller/ControllerCoreParameter.h +++ b/Src/Controller/ControllerCoreParameter.h @@ -26,6 +26,7 @@ class ControllerCoreParameter : public IControllerCfg public slots: void setCorePermission(std::pair permission); void changeAreaDescriptorType(QString type); + void changeNumberOfVerts(int i); void receiveResetTrial(); //Forwarded from data exporter diff --git a/Src/Controller/ControllerDataExporter.cpp b/Src/Controller/ControllerDataExporter.cpp index 40870293..30801c6a 100644 --- a/Src/Controller/ControllerDataExporter.cpp +++ b/Src/Controller/ControllerDataExporter.cpp @@ -21,8 +21,11 @@ ControllerDataExporter::~ControllerDataExporter() } void ControllerDataExporter::cleanup() { - if (m_Model) + _closing = true; + + if (m_Model){ qobject_cast(m_Model)->finalize(); + } } void ControllerDataExporter::connectControllerToController() { @@ -38,9 +41,8 @@ void ControllerDataExporter::connectControllerToController() { QObject::connect(this, &ControllerDataExporter::emitViewUpdate, tccController, &ControllerTrackedComponentCore::receiveUpdateView, Qt::DirectConnection); - - // ControllerPlayer* cPl = dynamic_cast(m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER)); - // QObject::connect(cPl, &ControllerPlayer::emitNextMediaInBatch, this, &ControllerDataExporter::receiveReset, Qt::DirectConnection); + //ControllerPlayer* cPl = dynamic_cast(m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER)); + //QObject::connect(cPl, &ControllerPlayer::emitNextMediaInBatch, this, &ControllerDataExporter::receiveReset, Qt::DirectConnection); } void ControllerDataExporter::createModel() { @@ -62,7 +64,7 @@ void ControllerDataExporter::loadFile(std::string file) { qobject_cast(m_Model)->loadFile(file); } else { - std::cout << "Can not load tracks for this plugin as it does not provide a factory." << std::endl; + std::cout << "Cannot load tracks for this plugin as it does not provide a factory." << std::endl; } } @@ -71,7 +73,7 @@ void ControllerDataExporter::saveFile(std::string file) { qobject_cast(m_Model)->writeAll(file); } else { - std::cout << "Can not save tracks for this plugin as it does not provide a factory." << std::endl; + std::cout << "Cannot save tracks for this plugin as it does not provide a factory." << std::endl; } } @@ -178,26 +180,34 @@ void ControllerDataExporter::receiveFileWritten(QFileInfo fname) { QString str = "Exported file:\n"; str += fname.absoluteFilePath(); - QMessageBox msgBox; - msgBox.setText("File saved!"); - msgBox.setInformativeText(str); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - QPushButton *goToFileDirButton = msgBox.addButton(tr("Show in folder"), QMessageBox::ActionRole); - QPushButton *openFileButton = msgBox.addButton(tr("Open file"), QMessageBox::ActionRole); + QMessageBox* msgBox = new QMessageBox(QApplication::activeWindow()); + msgBox->setText("File saved!"); + msgBox->setInformativeText(str); + msgBox->setStandardButtons(QMessageBox::Ok); + msgBox->setDefaultButton(QMessageBox::Ok); + QPushButton *goToFileDirButton = msgBox->addButton(tr("Show in folder"), QMessageBox::ActionRole); + QPushButton *openFileButton = msgBox->addButton(tr("Open file"), QMessageBox::ActionRole); - msgBox.setIcon(QMessageBox::Information); - msgBox.exec(); + msgBox->setIcon(QMessageBox::Information); - if (msgBox.clickedButton() == goToFileDirButton) { + // is modal if program is closing, else not + if(_closing && !_cfg->AutoClose){ + msgBox->setModal(true); + msgBox->exec(); + } + else{ + msgBox->setModal(false); + msgBox->show(); + } + + if (msgBox->clickedButton() == goToFileDirButton) { QUrl fileDirUrl = QUrl::fromLocalFile(fname.absolutePath()); QDesktopServices::openUrl(fileDirUrl); } - else if (msgBox.clickedButton() == openFileButton){ + else if (msgBox->clickedButton() == openFileButton) { QUrl fileUrl = QUrl::fromLocalFile(fname.absoluteFilePath()); QDesktopServices::openUrl(fileUrl); } - } void ControllerDataExporter::receiveTrialStarted(bool started) @@ -205,3 +215,19 @@ void ControllerDataExporter::receiveTrialStarted(bool started) _trialStarted = started; } +void ControllerDataExporter::receiveMediaLoaded(std::string path, int numOfFiles) +{ + if(_cfg->UseMediaName){ + QString mediaPath = QString::fromStdString(path); + if (getModel()) { + dynamic_cast(getModel())->setFinalFileFromMediaName(mediaPath); + } + } + _currentMedium = path; +} + +std::string ControllerDataExporter::getMediaPath(){ + return _currentMedium; +} + + diff --git a/Src/Controller/ControllerDataExporter.h b/Src/Controller/ControllerDataExporter.h index a3af361e..0659e238 100644 --- a/Src/Controller/ControllerDataExporter.h +++ b/Src/Controller/ControllerDataExporter.h @@ -33,6 +33,8 @@ class ControllerDataExporter : public IControllerCfg { void loadFile(std::string file); void saveFile(std::string file); + std::string getMediaPath(); + Q_SIGNALS: void emitResetUndoStack(); void emitViewUpdate(); @@ -43,6 +45,7 @@ class ControllerDataExporter : public IControllerCfg { void receiveFinalizeExperiment(); void receiveFileWritten(QFileInfo fname); void receiveTrialStarted(bool started); + void receiveMediaLoaded(std::string path, int numOfFiles); protected: void createModel() override; @@ -55,5 +58,7 @@ private Q_SLOTS: private: IModelTrackedComponentFactory* _factory; bool _trialStarted = false; + bool _closing = false; + std::string _currentMedium = ""; }; diff --git a/Src/Controller/ControllerMainWindow.cpp b/Src/Controller/ControllerMainWindow.cpp index 2d03f366..4beb0435 100644 --- a/Src/Controller/ControllerMainWindow.cpp +++ b/Src/Controller/ControllerMainWindow.cpp @@ -30,7 +30,10 @@ void ControllerMainWindow::loadVideo(std::vector files) Q_EMIT emitOnLoadMedia(files.front().string()); IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); qobject_cast(ctr)->loadVideoStream(files); - Q_EMIT emitMediaLoaded(files.front().string()); + Q_EMIT emitMediaLoaded(files.front().string(), files.size()); + qDebug() << "CORE: Video loaded: " << QString::fromStdString(files.front().string()); + + Q_EMIT emitFilesCount((int)files.size()); dynamic_cast(m_View)->checkMediaGroupBox(); } @@ -50,7 +53,11 @@ void ControllerMainWindow::loadPictures(std::vector fil Q_EMIT emitOnLoadMedia(str); IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); qobject_cast(ctr)->loadPictures(files); - Q_EMIT emitMediaLoaded(str); + Q_EMIT emitMediaLoaded(str, files.size()); + + qDebug() << "CORE: Picture loaded: " << QString::fromStdString(files.front().string()); + + Q_EMIT emitFilesCount((int)files.size()); dynamic_cast(m_View)->checkMediaGroupBox(); } @@ -59,7 +66,11 @@ void ControllerMainWindow::loadCameraDevice(CameraConfiguration conf) { Q_EMIT emitOnLoadMedia("::Camera"); IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); qobject_cast(ctr)->loadCameraDevice(conf); - Q_EMIT emitMediaLoaded("::Camera"); + Q_EMIT emitMediaLoaded("::Camera", 0); + + qDebug() << "CORE: Camera loaded!"; + + Q_EMIT emitFilesCount(1); dynamic_cast(m_View)->checkMediaGroupBox(); } @@ -104,6 +115,7 @@ void ControllerMainWindow::loadTrajectoryFile(std::string file) { IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT); static_cast(ctr)->loadFile(file); Q_EMIT emitTrackLoaded(file); + qDebug() << "CORE: Tracking file loaded: " << QString::fromStdString(file); } void ControllerMainWindow::saveTrajectoryFile(std::string file) { @@ -149,6 +161,7 @@ void ControllerMainWindow::connectModelToController() { ControllerDataExporter *contrl = static_cast(ctr2); QObject::connect(this, &ControllerMainWindow::emitOnLoadMedia, contrl, &ControllerDataExporter::receiveFinalizeExperiment, Qt::DirectConnection); QObject::connect(this, &ControllerMainWindow::emitOnLoadPlugin, contrl, &ControllerDataExporter::receiveReset, Qt::DirectConnection); + QObject::connect(this, &ControllerMainWindow::emitMediaLoaded, contrl, &ControllerDataExporter::receiveMediaLoaded, Qt::DirectConnection); } void ControllerMainWindow::connectControllerToController() { @@ -211,10 +224,38 @@ void ControllerMainWindow::connectControllerToController() { ControllerPlayer *cont3 = static_cast(ctr3); QObject::connect(cont3, &ControllerPlayer::emitNextMediaInBatch, this, &ControllerMainWindow::emitOnLoadMedia, Qt::DirectConnection); QObject::connect(cont3, &ControllerPlayer::emitNextMediaInBatchLoaded, this, &ControllerMainWindow::emitMediaLoaded, Qt::DirectConnection); + QObject::connect(cont3, &ControllerPlayer::emitEndOfPlayback, this, &ControllerMainWindow::receiveEndOfPlayback, Qt::QueuedConnection); + + // updater for media label in video control widget + QObject::connect(this, &ControllerMainWindow::emitMediaLoaded, cont3, &ControllerPlayer::receiveMediumChanged); + QObject::connect(this, &ControllerMainWindow::emitFilesCount, cont3, &ControllerPlayer::receiveMaxBatchNumber); //Load video as per CLI - if (!_cfg->LoadVideo.isEmpty()) - loadVideo({ _cfg->LoadVideo.toStdString().c_str() }); + if (!_cfg->LoadVideo.isEmpty()) + { + QDir videoDir(_cfg->LoadVideo); + //if path is directory do batch processing + if (videoDir.exists()) + { + qDebug() << "CORE: Loading all video files in: " << _cfg->LoadVideo; + std::vector files; + + QStringList filters; + filters << "*.avi" << "*.wmv" << "*.mp4" << "*.mkv" << "*.mov"; + for (QFileInfo const& fileInfo : videoDir.entryInfoList(filters, QDir::Files | QDir::NoSymLinks, QDir::Name)) + { + files.push_back(boost::filesystem::path(fileInfo.absoluteFilePath().toStdString())); + } + if (!files.empty()) { + loadVideo(files); + } + } + else + { + loadVideo({ _cfg->LoadVideo.toStdString().c_str() }); + } + } + } void ControllerMainWindow::receiveCursorPosition(QPoint pos) @@ -242,9 +283,16 @@ void ControllerMainWindow::rcvSelectPlugin(QString plugin) { Q_EMIT emitPluginLoaded(plugin.toStdString()); } +void ControllerMainWindow::receiveEndOfPlayback(){ + if (_cfg->AutoClose){ + qDebug() << "CORE: Closing the BioTracker..."; + this->exit(); + } +} + void ControllerMainWindow::onNewMediumLoaded(const std::string path) { - Q_EMIT emitMediaLoaded(path); + Q_EMIT emitMediaLoaded(path, 0); } void ControllerMainWindow::exit() { diff --git a/Src/Controller/ControllerMainWindow.h b/Src/Controller/ControllerMainWindow.h index f4cd8c01..df83a917 100644 --- a/Src/Controller/ControllerMainWindow.h +++ b/Src/Controller/ControllerMainWindow.h @@ -80,7 +80,7 @@ class ControllerMainWindow : public IControllerCfg { void emitOnLoadMedia(const std::string path); void emitPluginLoaded(const std::string path); - void emitMediaLoaded(const std::string path); + void emitMediaLoaded(const std::string path, int batchIndex); void emitTrackLoaded(const std::string path); void emitUndoCommand(); @@ -101,6 +101,9 @@ class ControllerMainWindow : public IControllerCfg { void emitAddEllAnno(); void emitDelSelAnno(); + //signal to video control widget + void emitFilesCount(int i); + public slots: void setCorePermission(std::pair permission); /** @@ -124,6 +127,7 @@ class ControllerMainWindow : public IControllerCfg { private slots: void rcvSelectPlugin(QString plugin); void receiveCursorPosition(QPoint pos); + void receiveEndOfPlayback(); private: // Internal cleanup callback when a new video or imagestream is loaded. diff --git a/Src/Controller/ControllerNotifications.cpp b/Src/Controller/ControllerNotifications.cpp index 07295117..1a2147cc 100644 --- a/Src/Controller/ControllerNotifications.cpp +++ b/Src/Controller/ControllerNotifications.cpp @@ -1,7 +1,10 @@ #include "ControllerNotifications.h" #include "View/NotificationLogBrowser.h" #include "ControllerMainWindow.h" + #include "qdebug.h" +// #include +#include IView* view; @@ -43,12 +46,29 @@ void ControllerNotifications::connectControllerToController() ctrMainWindow->setNotificationBrowserWidget(m_View); } - +// Get the default Qt message handler. +static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(0); void messageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg) { + //notification text browser NotificationLogBrowser* log = dynamic_cast(view); if (log) { - log->outputMessage(type, msg); + // std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + log->outputMessage(type, context, msg); } + + //log file + if (type == QtMsgType::QtInfoMsg) + return; + + QString fmsg = qFormatLogMessage(type, context, msg); + QString outf = IConfig::dataLocation+"/log.txt"; + std::string debugs = outf.toStdString(); + QFile outFile(outf); + outFile.open(QIODevice::WriteOnly | QIODevice::Append); + QTextStream ts(&outFile); + ts << fmsg << endl; + + (*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg); } diff --git a/Src/Controller/ControllerPlayer.cpp b/Src/Controller/ControllerPlayer.cpp index 2789dc85..9ad65cb8 100644 --- a/Src/Controller/ControllerPlayer.cpp +++ b/Src/Controller/ControllerPlayer.cpp @@ -6,10 +6,12 @@ #include "Controller/ControllerGraphicScene.h" #include "Controller/ControllerTrackedComponentCore.h" #include "Controller/ControllerCoreParameter.h" +#include "Controller/ControllerMainWindow.h" #include #include + ControllerPlayer::ControllerPlayer(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : IControllerCfg(parent, context, ctr) { @@ -93,6 +95,15 @@ int ControllerPlayer::recordInput() { return qobject_cast(m_Model)->toggleRecordImageStream(); } +void ControllerPlayer::prevMedium() { + qobject_cast(m_Model)->prevMediumCommand(); + // emitPauseState(false); +} + +void ControllerPlayer::nextMedium() { + qobject_cast(m_Model)->nextMediumCommand(); +} + void ControllerPlayer::setTargetFps(double fps) { return qobject_cast(m_Model)->setTargetFPS(fps); } @@ -113,12 +124,18 @@ void ControllerPlayer::setTrackingDeactivated() { void ControllerPlayer::connectControllerToController() { //connect to mainwindow - IController* ctrM = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< MainWindow > mainWin = dynamic_cast(ctrM->getView()); + IController* ictrM = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); + ControllerMainWindow* ctrM = qobject_cast(ictrM); + QPointer< MainWindow > mainWin = dynamic_cast(ictrM->getView()); mainWin->addVideoControllWidget(m_View); VideoControllWidget* vControl = static_cast(m_View); vControl->setupVideoToolbar(); + //QObject::connect(qobject_cast(m_Model), &MediaPlayer::emitNextMediaInBatchLoaded, vControl, &VideoControllWidget::mediumChanged); + // QObject::connect(ctrM, &ControllerMainWindow::emitMediaLoaded, vControl, &VideoControllWidget::mediumChanged); + // QObject::connect(ctrM, &ControllerMainWindow::emitFilesCount, vControl, &VideoControllWidget::getMaxBatchNumber); + + ////connect to coreparameterview //IController* ictrCpv = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); //QPointer< ControllerCoreParameter > ctrCpv = dynamic_cast(ictrCpv); @@ -147,7 +164,7 @@ void ControllerPlayer::connectModelToController() { QObject::connect(qobject_cast(m_Model), &MediaPlayer::emitNextMediaInBatch, this, &ControllerPlayer::receiveNextMediaInBatch, Qt::DirectConnection); QObject::connect(qobject_cast(m_Model), &MediaPlayer::emitNextMediaInBatchLoaded, this, &ControllerPlayer::receiveNextMediaInBatchLoaded, Qt::DirectConnection); - + QObject::connect(qobject_cast(m_Model), &MediaPlayer::emitEndOfPlayback, this, &ControllerPlayer::emitEndOfPlayback, Qt::DirectConnection); IController* ctrTRCC = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); QPointer< ControllerTrackedComponentCore > trCC = qobject_cast(ctrTRCC); @@ -161,16 +178,30 @@ void ControllerPlayer::receiveNextMediaInBatch(const std::string path){ Q_EMIT emitNextMediaInBatch(path); } -void ControllerPlayer::receiveNextMediaInBatchLoaded(const std::string path){ - Q_EMIT emitNextMediaInBatchLoaded(path); +void ControllerPlayer::receiveNextMediaInBatchLoaded(const std::string path, int batchIndex){ + Q_EMIT emitNextMediaInBatchLoaded(path, batchIndex); IController* ctrTRCC = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); QPointer< ControllerTrackedComponentCore > trCC = qobject_cast(ctrTRCC); for(int i=0; i<_trackCountEndOfBatch; i++){ trCC->emitAddTrack(); } + qDebug() << "CORE: Video loaded: " << QString::fromStdString(path); + + //set video name in video control widget + //VideoControllWidget* vControl = static_cast(m_View); + //vControl->mediumChanged(path); } +// void ControllerPlayer::receiveEndOfPlayback(){ +// if (_cfg->AutoClose){ +// qDebug() << "CORE: Closing the BioTracker..."; +// IController* ictrM = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); +// ControllerMainWindow* ctrM = qobject_cast(ictrM); +// ctrM->exit(); +// } +// } + void ControllerPlayer::receiveTrackCount(int trackNo){ _trackCount = trackNo; } @@ -194,3 +225,15 @@ void ControllerPlayer::receiveCurrentFrameNumberToPlugin(uint frameNumber) { Q_EMIT signalCurrentFrameNumberToPlugin(frameNumber); } + +void ControllerPlayer::receiveMediumChanged(const std::string path, int batchIndex) +{ + VideoControllWidget* vControl = static_cast(m_View); + vControl->mediumChanged(path, batchIndex); +} + +void ControllerPlayer::receiveMaxBatchNumber(int i) +{ + VideoControllWidget* vControl = static_cast(m_View); + vControl->getMaxBatchNumber(i); +} diff --git a/Src/Controller/ControllerPlayer.h b/Src/Controller/ControllerPlayer.h index 50ca447d..7eedb625 100644 --- a/Src/Controller/ControllerPlayer.h +++ b/Src/Controller/ControllerPlayer.h @@ -74,6 +74,14 @@ class ControllerPlayer : public IControllerCfg { int recordOutput(); int recordInput(); + /** + * Tells the IModel class MediaPlayer to load the previuos ImageStream. + */ + void prevMedium(); + /** + * Tells the IModel class MediaPlayer to load the next ImageStream. + */ + void nextMedium(); void setTargetFps(double fps); @@ -87,7 +95,8 @@ class ControllerPlayer : public IControllerCfg { void emitPauseState(bool state); void signalCurrentFrameNumberToPlugin(uint frameNumber); void emitNextMediaInBatch(const std::string path); - void emitNextMediaInBatchLoaded(const std::string path); + void emitNextMediaInBatchLoaded(const std::string path, int batchIndex); + void emitEndOfPlayback(); public Q_SLOTS: /** @@ -111,9 +120,11 @@ class ControllerPlayer : public IControllerCfg { */ void setGoToFrame(int frame); + void receiveMediumChanged(const std::string path, int batchIndex); + void receiveMaxBatchNumber(int i); void receiveNextMediaInBatch(const std::string path); - void receiveNextMediaInBatchLoaded(const std::string path); + void receiveNextMediaInBatchLoaded(const std::string path, int batchIndex); void receiveTrackCount(int trackNo); protected: diff --git a/Src/Controller/ControllerPlugin.cpp b/Src/Controller/ControllerPlugin.cpp index 92918e10..7eb05c8e 100644 --- a/Src/Controller/ControllerPlugin.cpp +++ b/Src/Controller/ControllerPlugin.cpp @@ -11,7 +11,7 @@ #include "Controller/ControllerCoreParameter.h" #include "Controller/ControllerCommands.h" -#define REGISTRY_PATH "SOFTWARE\\FUBioroboticsLab\\BioTracker\\Plugins" +#define REGISTRY_PATH "SOFTWARE\\FU Berlin\\Biorobotics Lab\\BioTracker\\Plugins" #define TRACKER_SUFFIX ".bio_tracker" ControllerPlugin::ControllerPlugin(QObject* parent, IBioTrackerContext* context, ENUMS::CONTROLLERTYPE ctr) : @@ -139,7 +139,6 @@ void ControllerPlugin::connectControllerToController() { // Add Plugin name to Main Window IController* ctrA = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); QPointer< ControllerMainWindow > ctrMainWindow = qobject_cast(ctrA); - ctrMainWindow->deactiveTrackingCheckBox(); loadPluginsFromPluginSubfolder(); @@ -259,30 +258,31 @@ void ControllerPlugin::connectPlugin() { // data model actions QObject::connect(this, SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), obj, - SLOT(receiveRemoveTrajectory(IModelTrackedTrajectory*))); + SLOT(receiveRemoveTrajectory(IModelTrackedTrajectory*)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), obj, - SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint))); + SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitAddTrajectory(QPoint)), obj, - SLOT(receiveAddTrajectory(QPoint))); + SLOT(receiveAddTrajectory(QPoint)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint)), obj, - SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint))); + SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*)), obj, - SLOT(receiveSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*))); + SLOT(receiveSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), obj, - SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool))); + SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitRemoveTrajectoryId(int)), obj, - SIGNAL(emitRemoveTrajectoryId(int))); + SIGNAL(emitRemoveTrajectoryId(int)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitValidateTrajectory(int)), obj, - SIGNAL(emitValidateTrajectory(int))); + SIGNAL(emitValidateTrajectory(int)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint)), obj, - SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint))); + SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint)), Qt::BlockingQueuedConnection); QObject::connect(this, SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint)), obj, - SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint))); + SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint)), Qt::BlockingQueuedConnection); connect(this, &ControllerPlugin::frameRetrieved, m_BioTrackerPlugin, &IBioTrackerPlugin::receiveCurrentFrameFromMainApp); QObject::connect(this, SIGNAL(signalCurrentFrameNumberToPlugin(uint)), obj, SLOT(receiveCurrentFrameNumberFromMainApp(uint))); + } void ControllerPlugin::disconnectPlugin() { @@ -293,6 +293,8 @@ void ControllerPlugin::disconnectPlugin() { void ControllerPlugin::sendCurrentFrameToPlugin(std::shared_ptr mat, uint number) { m_currentFrameNumber = number; + //qDebug() << "Core send: " << number; + //Prevent calling the plugin if none is loaded if (m_BioTrackerPlugin) { while (!m_editQueue.isEmpty()) { diff --git a/Src/Controller/ControllerTextureObject.cpp b/Src/Controller/ControllerTextureObject.cpp index bf8132a7..32634e24 100644 --- a/Src/Controller/ControllerTextureObject.cpp +++ b/Src/Controller/ControllerTextureObject.cpp @@ -41,7 +41,6 @@ void ControllerTextureObject::receiveCvMat(std::shared_ptr mat, QString checkIfTextureModelExists(name); m_TextureObjects.value(name)->set(*mat); - } void ControllerTextureObject::createModel() { diff --git a/Src/Controller/ControllerTextureObject.h b/Src/Controller/ControllerTextureObject.h index cdcc50f2..be37d7a7 100644 --- a/Src/Controller/ControllerTextureObject.h +++ b/Src/Controller/ControllerTextureObject.h @@ -23,7 +23,7 @@ * receiveCvMat(std::shard_ptr mat, QString name) in order to render their images. Usually this would be the component MediaPlayer which will send the original cv::Mat from * an ImageStream to controller class ControllerTextureObject. An other component is the BioTracker Plugin. If a cv::Mat is manipulated by a Tracking Algorithm the Plugin is able to * send that cv::Mat to this component. The Parameter name will be listed in the combobox widget on the MainWindow widget. - * The ControllerTextureObject class controlls the of the TrextureObject Component. + * The ControllerTextureObject class controlls the of the TextureObject Component. */ class ControllerTextureObject : public IControllerCfg { Q_OBJECT diff --git a/Src/GuiContext.cpp b/Src/GuiContext.cpp index fcaf0914..9fe884e9 100644 --- a/Src/GuiContext.cpp +++ b/Src/GuiContext.cpp @@ -75,6 +75,34 @@ void GuiContext::connectController() { i.value()->connectComponents(); } + //activate tracking if autotracking activated in cfg and autoplay if in cfg + ControllerMainWindow *contMW = static_cast(m_ControllersMap.value(ENUMS::CONTROLLERTYPE::MAINWINDOW)); + ControllerPlayer *contP = static_cast(m_ControllersMap.value(ENUMS::CONTROLLERTYPE::PLAYER)); + ControllerPlugin *contPlg = static_cast(m_ControllersMap.value(ENUMS::CONTROLLERTYPE::PLUGIN)); + + // Activate tracking as per CLI + if (_cfg->AutoTrack != -1){ + contMW->activeTracking(); + + // add as many tracks as set in CLI for autotracking + qDebug() << "CORE: CtrPlugin: Adding " << _cfg->AutoTrack << " tracks "; + for(int i = 0; i < _cfg->AutoTrack; i++){ + contPlg->emitAddTrajectory(QPoint(0,0)); + } + + if(_cfg->AutoPlay){ + contP->play(); + } + } + else if (_cfg->AutoTrack==-1 && _cfg->AutoPlay){ + contP->play(); + } + + //Load track file as per CLI + if (!_cfg->LoadTrack.isEmpty()) + { + contMW->loadTrajectoryFile(_cfg->LoadTrack.toStdString().c_str()); + } } void GuiContext::exit() { diff --git a/Src/GuiContext.h b/Src/GuiContext.h index 31944c92..9c920628 100644 --- a/Src/GuiContext.h +++ b/Src/GuiContext.h @@ -13,6 +13,7 @@ class GuiContext : public IBioTrackerContext GuiContext(QObject *parent = 0, Config *cfg = nullptr); ~GuiContext() { exit(); + return; } void loadBioTrackerPlugin(QString str); diff --git a/Src/IStates/IPlayerState.h b/Src/IStates/IPlayerState.h index d47d81df..8dc9cd9d 100644 --- a/Src/IStates/IPlayerState.h +++ b/Src/IStates/IPlayerState.h @@ -96,7 +96,8 @@ class IPlayerState : public IModel { Q_SIGNALS: void emitNextMediaInBatch(const std::string path); - void emitNextMediaInBatchLoaded(const std::string path); + void emitNextMediaInBatchLoaded(const std::string path, int batchIndex); + void emitEndOfPlayback(); protected: MediaPlayerStateMachine* m_Player; diff --git a/Src/Model/AreaDescriptor/AreaInfo.cpp b/Src/Model/AreaDescriptor/AreaInfo.cpp index 93951475..68335576 100644 --- a/Src/Model/AreaDescriptor/AreaInfo.cpp +++ b/Src/Model/AreaDescriptor/AreaInfo.cpp @@ -79,7 +79,7 @@ void AreaInfo::loadAreas() { std::vector p = stringToCVPointVec(pair[0].toStdString()); _rect->setVertices(p); - p = stringToCVPointVec(pair[1].toStdString());; + p = stringToCVPointVec(pair[1].toStdString()); _apperture->setVertices(p); } diff --git a/Src/Model/AreaDescriptor/AreaInfoElement.cpp b/Src/Model/AreaDescriptor/AreaInfoElement.cpp index 5ce6c01b..9d4f9c1b 100644 --- a/Src/Model/AreaDescriptor/AreaInfoElement.cpp +++ b/Src/Model/AreaDescriptor/AreaInfoElement.cpp @@ -2,6 +2,7 @@ #include #include +#include AreaInfoElement::AreaInfoElement(int type) : _areaType(BiotrackerTypes::AreaType::NONE), @@ -19,8 +20,10 @@ AreaInfoElement::~AreaInfoElement() bool AreaInfoElement::insideElement(cv::Point p) { if (_type == 0) { - - return cv::pointPolygonTest(_v, p, true) > 0; + auto start = _v.begin(); + auto end = _v.begin() + 4; + std::vector rectV(start, end); + return cv::pointPolygonTest(rectV, p, true) > 0; } else if (_type == 1) { float rx = std::abs(_v[1].x - _v[0].x) / 2; @@ -37,6 +40,9 @@ bool AreaInfoElement::insideElement(cv::Point p) { return inShape; } + else if (_type == 2){ + return cv::pointPolygonTest(_v, p, true) > 0; + } return false; } @@ -53,22 +59,59 @@ int AreaInfoElement::getVerticeAtLocation(const QPoint &pos) { return i; } } + else if (_type == 2) { + int numberOfVertices = _v.size(); + for (int i = 0; i < numberOfVertices; i++) { + if (isHandleAtPosition(_v[i], pos)) + return i; + } + } return -1; } -void AreaInfoElement::setVerticeAtLocation(const QPoint &pos, int vertice) { - if (_type == 0 && vertice >= 0 && vertice <4) { - _v[vertice] = cv::Point2f(pos.x(), pos.y()); +//Moving vertices +void AreaInfoElement::setVerticeAtLocation(const QPoint &pos, int vertex) { + int numberOfVertices = _v.size(); + //Move existing vertices + if (_type == 0 && vertex >= 0 && vertex < 4) { + _v[vertex] = cv::Point2f(pos.x(), pos.y()); } - else if (_type > 0 && vertice >= 0 && vertice < 2) { - _v[vertice] = cv::Point2f(pos.x(), pos.y()); + else if (_type == 1 && vertex >= 0 && vertex < 2) { + _v[vertex] = cv::Point2f(pos.x(), pos.y()); } + else if (_type == 2 && vertex >= 0 && vertex < numberOfVertices) { + _v[vertex] = cv::Point2f(pos.x(), pos.y()); + } + // //Add new vertex to polygon + // else if (_type == 2 && vertex == numberOfVertices) { + // _v.push_back(cv::Point2f(pos.x(), pos.y())); + // } Q_EMIT updatedVertices(); } +void AreaInfoElement::changeTrArNumberOfVertices(int number) { + int numberOfVertices = _v.size(); + + // add more vertices + while (numberOfVertices < number) { + cv::Point2f first = _v[0]; + cv::Point2f last = _v[numberOfVertices-1]; + _v.push_back((first+last) * .5); + numberOfVertices = _v.size(); + } + + // remove last vertices (down to 4) + while (numberOfVertices > number && numberOfVertices > 4) { + _v.pop_back(); + numberOfVertices = _v.size(); + } + + Q_EMIT updatedVertices(); +} + bool AreaInfoElement::isHandleAtPosition(const cv::Point2f &handle, const QPoint &pos) { return isHandleAtPosition(QPoint(handle.x, handle.y), pos); } diff --git a/Src/Model/AreaDescriptor/AreaInfoElement.h b/Src/Model/AreaDescriptor/AreaInfoElement.h index 5ed1d957..69778527 100644 --- a/Src/Model/AreaDescriptor/AreaInfoElement.h +++ b/Src/Model/AreaDescriptor/AreaInfoElement.h @@ -38,6 +38,9 @@ class AreaInfoElement : public IModel void setVerticeAtLocation(const QPoint &pos, int vertice); int getVerticeAtLocation(const QPoint &pos); + void changeTrArNumberOfVertices(const int number); + + virtual QPoint *getHandleForPosition(const QPoint &pos) { if (isHandleAtPosition(_origin, pos)) return &_origin; diff --git a/Src/Model/AreaDescriptor/AreaMemory.h b/Src/Model/AreaDescriptor/AreaMemory.h index 93a086b0..b1188430 100644 --- a/Src/Model/AreaDescriptor/AreaMemory.h +++ b/Src/Model/AreaDescriptor/AreaMemory.h @@ -11,7 +11,7 @@ namespace AreaMemory #define DEFAULT_AREA "10,10;10,100;100,100;100,10" #define DEFAULT_PAIR QVector{DEFAULT_AREA, DEFAULT_RECT, "0", "0"} - QVector getVertices(QString file, QString areaFile, bool useLast = false); + QVector getVertices(QString file, QString areaFile, bool useLast = true); void setVertices(QString file, QVector values, QString areaFile); std::vector toQPointVector(QString vertices); }; diff --git a/Src/Model/DataExporters/DataExporterCSV.cpp b/Src/Model/DataExporters/DataExporterCSV.cpp index a6db9a96..8ae5766b 100644 --- a/Src/Model/DataExporters/DataExporterCSV.cpp +++ b/Src/Model/DataExporters/DataExporterCSV.cpp @@ -4,7 +4,9 @@ #include #include #include +#include +#include "qmessagebox.h" using namespace BioTrackerUtilsMisc; //split @@ -123,15 +125,56 @@ void DataExporterCSV::addChildOfChild(IModelTrackedTrajectory *root, IModelTrack void DataExporterCSV::loadFile(std::string file) { - std::ifstream ifs(file, std::ifstream::in); + std::ifstream ifs (file, std::ifstream::in); std::string line = "# "; + + // first line is "# Source name: " + // check if file video file has same path or same name as loaded video + ControllerDataExporter *ctr = dynamic_cast(_parent); + SourceVideoMetadata d = ctr->getSourceMetadata(); + + getline(ifs, line); + + QString loadedMediaName = QString::fromStdString(d.name); + QString sourceName; + if (line.length() > 14){ + sourceName = QString::fromStdString(line.substr(15, std::string::npos)); + } + else{ + sourceName = QString(""); + qDebug() << QString("CORE: No media source file in tracking file found!"); + } + + QFileInfo loadedMediaPath(loadedMediaName); + QFileInfo sourceNamePath(sourceName); + + QString loadedName = loadedMediaPath.fileName(); + QString sourceFileName = sourceNamePath.fileName(); + + if ((loadedMediaPath.isFile()) && (loadedMediaPath != sourceNamePath)){ + qDebug() << "CORE: Paths of currently loaded medium and tracked medium in track file are different!"; + + // if file names also differ, display a warning + if(loadedName != sourceFileName){ + QString msg = QString("The currently loaded medium file path and the" + "media path found in tracking file differ!\n\n" + "(current media path):\n%1\n\n" + "(found media path):\n%2").arg(loadedMediaName).arg(sourceName); + QMessageBox q = QMessageBox(QMessageBox::Warning, + QString("Loaded medium and tracked medium differ!"), + msg, + QMessageBox::Ok); + q.exec(); + } + } + + // skip all other lines with # while (line.substr(0, 1) == "#") { getline(ifs, line); } //parse header - ControllerDataExporter *ctr = dynamic_cast(_parent); IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() : nullptr; if (!factory) { return; @@ -176,14 +219,28 @@ void DataExporterCSV::loadFile(std::string file) } void DataExporterCSV::write(int idx) { + + //_ofs = QTextStream(_oFileTmp); + if (!_root) { qDebug() << "CORE: No output opened!"; return; } + //check if tmp filestream has device (file loaded) + if (!_ofs.device()){ + qDebug() << "CORE: Tmp file not found!"; + return; + } + + if(!_oFileTmp->isOpen()){ + qDebug() << "CORE: Tmp file not open!"; //most likely the last frame, which was processed by the tracker after the next batch was loaded (meaning reinit of the dataexporter). The last frame of each video is not written to the tmp + return; + } + //TODO there is some duplicated code here - _ofs << std::to_string(idx) - << _separator + std::to_string((long long)((((double)idx) / _fps) * 1000)); + _ofs << QString::fromStdString(std::to_string(idx)) + << QString::fromStdString(_separator) + QString::fromStdString(std::to_string((long long)((((double)idx) / _fps) * 1000))); //Write single trajectory int trajNumber = 0; @@ -197,12 +254,14 @@ void DataExporterCSV::write(int idx) { else e = dynamic_cast(t->getChild(idx)); if (e && e->getValid()) { - _ofs << writeComponentCSV(e, trajNumber); + _ofs << QString::fromStdString(writeComponentCSV(e, trajNumber)); } trajNumber++; } } - _ofs << std::endl; + //qDebug() << "line written into temp file"; + //_ofs << std::endl; + _ofs << endl; } void DataExporterCSV::finalizeAndReInit() { @@ -216,12 +275,16 @@ void DataExporterCSV::finalizeAndReInit() { void DataExporterCSV::writeAll(std::string f) { //Sanity if (!_root) { - qDebug() << "CORE: No output opened!"; + qDebug() << "CORE: No output opened!"; return; } - if (_ofs.is_open()) { - _ofs.close(); - } + +// if (_oFileTmp->isOpen()) { +// _oFileTmp->close(); +// } +// if (_ofs.device()){ +// _ofs.setDevice(0); +// } //Find max length of all tracks int max = getMaxLinecount(); @@ -240,27 +303,46 @@ void DataExporterCSV::writeAll(std::string f) { if (target.substr(target.size() - 4) != ".csv") target += ".csv"; - //Create final file - std::ofstream o; - o.open(target, std::ofstream::out); + + //QT-Ansatz, weil std ofstream oft hängt bei open + QFile outFile(QString::fromStdString(target)); + outFile.open(QIODevice::WriteOnly); + + + if(!outFile.isOpen()){ + qWarning() << "File could not be opened! " << QString::fromStdString(target); + } + + QTextStream o(&outFile); + + /* + try { + //target = "C:/Users/Jonas/Desktop/blubb.csv"; + target = "C:/Users/Jonas/AppData/Roaming/FU Berlin/BioTracker/Tracks/blubbbbbb.csv"; + o.open(target, std::ofstream::out | std::ofstream::app); // hier ist ein fehler im batch processing + } + catch (std::ofstream::failure e) { + qDebug() << "Exception opening/reading file"; + } + */ //write metadata ControllerDataExporter *ctr = dynamic_cast(_parent); SourceVideoMetadata d = ctr->getSourceMetadata(); - o << "# Source name: " << d.name << std::endl; - o << "# Source FPS: " << d.fps << std::endl; + o << "# Source name: " << QString::fromStdString(d.name) << endl; + o << "# Source FPS: " << QString::fromStdString(d.fps) << endl; QVariant vv(QDateTime::currentDateTime()); - o << "# Generation time: " << vv.toString().toStdString() << std::endl; + o << "# Generation time: " << QString::fromStdString(vv.toString().toStdString()) << endl; //write header int vcount = _root->validCount(); IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() : nullptr; int headerCount = 0; if (factory != nullptr) { - IModelTrackedComponent *ptraj = static_cast(factory->getNewTrackedElement("0")); + IModelTrackedComponent *ptraj = static_cast(factory->getNewTrackedElement("0")); // do this with signals/slots std::string header = getHeader(ptraj, vcount); headerCount = static_cast(getHeaderElements(ptraj).size()); - o << header << "\n"; + o << QString::fromStdString(header) << QString("\n"); delete ptraj; } @@ -271,8 +353,8 @@ void DataExporterCSV::writeAll(std::string f) { //idx is the frame number for (int idx = 0; idx < max; idx++) { - o << std::to_string(idx) - << _separator + std::to_string((((float)idx) / _fps) * 1000); + o << QString::fromStdString(std::to_string(idx)) + << QString::fromStdString(_separator) + QString::fromStdString(std::to_string((((float)idx) / _fps) * 1000)); int linecnt = 0; //i is the track number @@ -283,7 +365,7 @@ void DataExporterCSV::writeAll(std::string f) { IModelTrackedPoint *e = dynamic_cast(t->getChild(idx)); if (e) { std::string line = writeComponentCSV(e, trajNumber); - o << line; + o << QString::fromStdString(line); linecnt++; } trajNumber++; @@ -292,19 +374,34 @@ void DataExporterCSV::writeAll(std::string f) { int count = _root->validCount(); while (linecnt < count) { for (int i = 0; iisOpen()){ + _oFileTmp->close(); + } + + //remove tmp file from filestream + if (_ofs.device()){ + _ofs.setDevice(0); + } //Remove temporary file QFile file(_tmpFile.c_str()); file.remove(); + _oFileTmp->remove(); } diff --git a/Src/Model/DataExporters/DataExporterGeneric.cpp b/Src/Model/DataExporters/DataExporterGeneric.cpp index 950b659a..9e9a3597 100644 --- a/Src/Model/DataExporters/DataExporterGeneric.cpp +++ b/Src/Model/DataExporters/DataExporterGeneric.cpp @@ -2,9 +2,12 @@ #include "util/types.h" #include "Utility/misc.h" #include -#include +#include +#include #include +using namespace BioTrackerUtilsMisc; //split + DataExporterGeneric::DataExporterGeneric(QObject *parent) : IModelDataExporter(parent) { @@ -18,7 +21,31 @@ void DataExporterGeneric::open(IModelTrackedTrajectory *root) { _tmpFile = _parent->generateBasename(true).toStdString() + ".tmp" + getSuffix().toStdString(); _finalFile = _parent->generateBasename(false).toStdString() + getSuffix().toStdString(); - _ofs.open(_tmpFile, std::ofstream::out); + + if(_cfg->UseMediaName){ + + ControllerDataExporter *ctr = dynamic_cast(_parent); + std::string mPath = ctr->getMediaPath(); + if(mPath != ""){ + this->setFinalFileFromMediaName(QString::fromStdString(mPath)); + } + } + + //_ofs.open(_tmpFile, std::ofstream::out); + + //QFile _oFileTmp(QString::fromStdString(_tmpFile)); + _oFileTmp = new QFile(QString::fromStdString(_tmpFile)); + _oFileTmp->open(QIODevice::WriteOnly); + + if(!_oFileTmp->isOpen()){ + qWarning() << "File could not be opened! " << QString::fromStdString(_tmpFile); + } + + _ofs.setDevice(_oFileTmp); + + if(!_ofs.device()){ + qDebug() << "Failed to assign device to tmp-QTextStream"; + } } int DataExporterGeneric::getMaxLinecount() @@ -42,6 +69,14 @@ void DataExporterGeneric::cleanup() //Erase all tracking data from the tracking structure! _root->clear(); + // close tmp file and textstream + if (_oFileTmp->isOpen()) { + _oFileTmp->close(); + } + if (_ofs.device()){ + _ofs.setDevice(0); + } + //Remove temporary file QFile file(_tmpFile.c_str()); file.remove(); @@ -49,11 +84,21 @@ void DataExporterGeneric::cleanup() if (s > 0) { //Tell the controller about the written file QFileInfo fi(_finalFile.c_str()); - fileWritten(fi); + Q_EMIT fileWritten(fi); } return; } +void DataExporterGeneric::setFinalFileFromMediaName(QString path){ + QFileInfo mediaFile(path); + QString mediaName = mediaFile.completeBaseName(); + + QString outDir = _cfg->DirTracks; + + std::string outPath = getTimeAndDate(outDir.toStdString() + mediaName.toStdString() + "_", ""); + _finalFile = outPath + getSuffix().toStdString(); +} + void DataExporterGeneric::finalize() { close(); diff --git a/Src/Model/DataExporters/DataExporterGeneric.h b/Src/Model/DataExporters/DataExporterGeneric.h index fbed180e..511e90ef 100644 --- a/Src/Model/DataExporters/DataExporterGeneric.h +++ b/Src/Model/DataExporters/DataExporterGeneric.h @@ -7,6 +7,7 @@ #include "util/Config.h" #include #include +#include class DataExporterGeneric : public IModelDataExporter { @@ -21,6 +22,7 @@ class DataExporterGeneric : public IModelDataExporter void open(IModelTrackedTrajectory *root) override; void finalize() override; + void setFinalFileFromMediaName(QString path); protected: @@ -31,7 +33,10 @@ class DataExporterGeneric : public IModelDataExporter ControllerDataExporter *_parent = nullptr; Config *_cfg; - std::ofstream _ofs; + //std::ofstream::open blocks the program very often (~80% of the time) + //std::ofstream _ofs; + QFile* _oFileTmp; + QTextStream _ofs; //Name of the temporary file to write to std::string _tmpFile; diff --git a/Src/Model/DataExporters/DataExporterJson.cpp b/Src/Model/DataExporters/DataExporterJson.cpp index da0d2e99..66e8947c 100644 --- a/Src/Model/DataExporters/DataExporterJson.cpp +++ b/Src/Model/DataExporters/DataExporterJson.cpp @@ -136,7 +136,7 @@ void DataExporterJson::write(int idx) { return; } - _ofs << std::endl; + _ofs << endl; } void DataExporterJson::finalizeAndReInit() { @@ -173,8 +173,8 @@ void DataExporterJson::writeAll(std::string f) { qDebug() << "CORE: No output opened!"; return; } - if (_ofs.is_open()) { - _ofs.close(); + if (_oFileTmp->isOpen()) { + _oFileTmp->close(); } if (getMaxLinecount() <= 1) { @@ -217,7 +217,7 @@ void DataExporterJson::writeAll(std::string f) { } void DataExporterJson::close() { - _ofs.close(); + _oFileTmp->close(); if ((!_root || _root->size() == 0) &&_tmpFile!="" ) { //Remove temporary file diff --git a/Src/Model/DataExporters/DataExporterSerialize.cpp b/Src/Model/DataExporters/DataExporterSerialize.cpp index a6742207..666382c6 100644 --- a/Src/Model/DataExporters/DataExporterSerialize.cpp +++ b/Src/Model/DataExporters/DataExporterSerialize.cpp @@ -35,7 +35,7 @@ void DataExporterSerialize::write(int idx) { return; } - _ofs << std::endl; + _ofs << endl; } void DataExporterSerialize::finalizeAndReInit() { @@ -92,8 +92,8 @@ void DataExporterSerialize::writeAll(std::string f) { qDebug() << "CORE: No output opened!"; return; } - if (_ofs.is_open()) { - _ofs.close(); + if (_oFileTmp->isOpen()) { + _oFileTmp->close(); } if (getMaxLinecount() <= 1) { @@ -151,7 +151,7 @@ void DataExporterSerialize::writeAll(std::string f) { } void DataExporterSerialize::close() { - _ofs.close(); + _oFileTmp->close(); if ((!_root || _root->size() == 0) && _tmpFile!="" ) { //Remove temporary file diff --git a/Src/Model/ImageStream.cpp b/Src/Model/ImageStream.cpp index f138c452..7b20ae61 100644 --- a/Src/Model/ImageStream.cpp +++ b/Src/Model/ImageStream.cpp @@ -39,6 +39,10 @@ namespace BioTracker { return m_current_frame_number; } + int ImageStream::currentBatchIndex() const { + return m_currentBatchIndex; + } + std::shared_ptr ImageStream::currentFrame() const { return m_current_frame; } @@ -129,6 +133,13 @@ namespace BioTracker { void ImageStream::stepToNextInBatch(){ } + bool ImageStream::hasPrevInBatch(){ + return false; + } + + void ImageStream::stepToPrevInBatch(){ + } + std::vector ImageStream::getBatchItems(){ return {}; } @@ -268,7 +279,8 @@ namespace BioTracker { explicit ImageStream3Video(Config *cfg, const std::vector &files) : ImageStream(0, cfg) { - openMedia(files); + m_currentBatchIndex = -1; + openMedia(files, 1); } virtual GuiParam::MediaType type() const override { return GuiParam::MediaType::Video; @@ -292,14 +304,25 @@ namespace BioTracker { } virtual bool hasNextInBatch() override{ - return !(m_batch.empty()); + return m_currentBatchIndex < (m_batch.size()-1); } virtual void stepToNextInBatch() override{ - if (m_batch.empty()) { - throw video_open_error("batch is empty"); + if (m_currentBatchIndex == (m_batch.size()-1)) { + throw video_open_error("end of batch is empty"); } - openMedia(m_batch); + openMedia(m_batch, 1); + } + + virtual bool hasPrevInBatch() override{ + return m_currentBatchIndex != 0; + } + + virtual void stepToPrevInBatch() override{ + if (m_currentBatchIndex == 0) { + // throw video_open_error("batch is empty"); + } + openMedia(m_batch, -1); } virtual std::vector getBatchItems() override{ @@ -312,22 +335,31 @@ namespace BioTracker { private: - void openMedia(std::vector files){ + void openMedia(std::vector files, int nextOrPrev){ + + // skip if index would be out of range + if((m_currentBatchIndex == files.size()-1) && (nextOrPrev == 1)){ + return; + } + if((m_currentBatchIndex == 0) && (nextOrPrev == -1)){ + return; + } + m_currentBatchIndex += nextOrPrev; - m_capture.open(files.front().string()); + m_capture.open(files[m_currentBatchIndex].string()); m_num_frames = static_cast(m_capture.get(cv::CAP_PROP_FRAME_COUNT)); m_fps = m_capture.get(cv::CAP_PROP_FPS); - m_fileName = files.front().string(); + m_fileName = files[m_currentBatchIndex].string(); - if (!boost::filesystem::exists(files.front())) { - throw file_not_found("Could not find file " + files.front().string()); + if (!boost::filesystem::exists(files[m_currentBatchIndex])) { + throw file_not_found("Could not find file " + files[m_currentBatchIndex].string()); } if (!m_capture.isOpened()) { throw video_open_error(":("); } m_batch = files; - m_batch.erase(m_batch.begin(), m_batch.begin()+1); + // m_batch.erase(m_batch.begin(), m_batch.begin()+1); //Grab the fps from config file double fps = _cfg->RecordFPS; diff --git a/Src/Model/ImageStream.h b/Src/Model/ImageStream.h index 6c17284b..5bbdbcce 100644 --- a/Src/Model/ImageStream.h +++ b/Src/Model/ImageStream.h @@ -49,6 +49,11 @@ class ImageStream : public QObject { */ size_t currentFrameNumber() const; + /** + * @return the current batch index + */ + int currentBatchIndex() const; + /** * @return true, if the current frame is the last frame */ @@ -112,7 +117,11 @@ class ImageStream : public QObject { virtual bool hasNextInBatch(); - virtual void stepToNextInBatch(); + virtual void stepToNextInBatch(); + + virtual bool hasPrevInBatch(); + + virtual void stepToPrevInBatch(); virtual std::vector getBatchItems(); @@ -143,6 +152,7 @@ class ImageStream : public QObject { size_t m_current_frame_number; std::string m_title; Config *_cfg; + int m_currentBatchIndex; private: /** diff --git a/Src/Model/MediaPlayer.cpp b/Src/Model/MediaPlayer.cpp index 8c1e446d..abd6f1bc 100644 --- a/Src/Model/MediaPlayer.cpp +++ b/Src/Model/MediaPlayer.cpp @@ -46,6 +46,9 @@ MediaPlayer::MediaPlayer(QObject* parent) : QObject::connect(this, &MediaPlayer::prevFrameCommand, m_Player, &MediaPlayerStateMachine::receivePrevFrameCommand); QObject::connect(this, &MediaPlayer::stopCommand, m_Player, &MediaPlayerStateMachine::receiveStopCommand); QObject::connect(this, &MediaPlayer::goToFrame, m_Player, &MediaPlayerStateMachine::receiveGoToFrame); + + QObject::connect(this, &MediaPlayer::prevMediumCommand, m_Player, &MediaPlayerStateMachine::receivePrevMediumCommand); + QObject::connect(this, &MediaPlayer::nextMediumCommand, m_Player, &MediaPlayerStateMachine::receiveNextMediumCommand); QObject::connect(this, &MediaPlayer::pauseCommand, this, &MediaPlayer::receiveTrackingPaused); QObject::connect(this, &MediaPlayer::stopCommand, this, &MediaPlayer::receiveTrackingPaused); @@ -62,6 +65,7 @@ MediaPlayer::MediaPlayer(QObject* parent) : QObject::connect(m_Player, &MediaPlayerStateMachine::emitNextMediaInBatch, this, &MediaPlayer::emitNextMediaInBatch, Qt::DirectConnection); QObject::connect(m_Player, &MediaPlayerStateMachine::emitNextMediaInBatchLoaded, this, &MediaPlayer::emitNextMediaInBatchLoaded, Qt::DirectConnection); + QObject::connect(m_Player, &MediaPlayerStateMachine::emitEndOfPlayback, this, &MediaPlayer::emitEndOfPlayback, Qt::DirectConnection); // Move the PlayerStateMachine to the Thread m_Player->moveToThread(m_PlayerThread); @@ -284,7 +288,6 @@ void MediaPlayer::receivePlayerParameters(playerParameters* param) { Q_EMIT notifyView(); } - void MediaPlayer::rcvPauseState(bool state) { _paused = state; diff --git a/Src/Model/MediaPlayer.h b/Src/Model/MediaPlayer.h index 367abed3..8d687a1e 100644 --- a/Src/Model/MediaPlayer.h +++ b/Src/Model/MediaPlayer.h @@ -35,45 +35,53 @@ class MediaPlayer : public IModel { Q_SIGNALS: /** - * Emit the path to a video stream. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit the path to a video stream. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void loadVideoStream(std::vector files); /** - * Emit the path to pictures. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit the path to pictures. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void loadPictures(std::vector files); /** - * Emit the camera device number. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit the camera device number. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void loadCameraDevice(CameraConfiguration conf); /** - * Emit a frame number. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit a frame number. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void goToFrame(int frame); /** - * Emit the next frame command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit the next frame command. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void nextFrameCommand(); /** - * Emit previous frame command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit previous frame command. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void prevFrameCommand(); /** - * Emit the play command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit the play command. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void playCommand(); /** - * Emit stop command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit stop command. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void stopCommand(); /** - * Emit the pause command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * Emit the pause command. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void pauseCommand(); + /** + * Emit the previous medium command. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. + */ + void prevMediumCommand(); + /** + * Emit the next medium command. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. + */ + void nextMediumCommand(); /** - * This SIGNAL will be emmited if a state operation should be executed. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. + * This SIGNAL will be emmited if a state operation should be executed. This signal will be received by the MediaPlayerStateMachine which runs in a separate Thread. */ void runPlayerOperation(); @@ -97,7 +105,8 @@ class MediaPlayer : public IModel { void fwdPlayerParameters(playerParameters* parameters); void emitNextMediaInBatch(const std::string path); - void emitNextMediaInBatchLoaded(const std::string path); + void emitNextMediaInBatchLoaded(const std::string path, int batchIndex); + void emitEndOfPlayback(); public: void setTrackingActive(); diff --git a/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp b/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp index d74d62de..e74e6875 100644 --- a/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp +++ b/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp @@ -28,8 +28,9 @@ MediaPlayerStateMachine::MediaPlayerStateMachine(QObject* parent) : QMap::iterator i; for (i = m_States.begin(); i != m_States.end(); i++) { - QObject::connect(i.value(), &IPlayerState::emitNextMediaInBatch, this, &MediaPlayerStateMachine::emitNextMediaInBatch); - QObject::connect(i.value(), &IPlayerState::emitNextMediaInBatchLoaded, this, &MediaPlayerStateMachine::emitNextMediaInBatchLoaded); + QObject::connect(i.value(), &IPlayerState::emitNextMediaInBatch, this, &MediaPlayerStateMachine::emitNextMediaInBatch, Qt::DirectConnection); + QObject::connect(i.value(), &IPlayerState::emitNextMediaInBatchLoaded, this, &MediaPlayerStateMachine::emitNextMediaInBatchLoaded, Qt::DirectConnection); + QObject::connect(i.value(), &IPlayerState::emitEndOfPlayback, this, &MediaPlayerStateMachine::emitEndOfPlayback, Qt::DirectConnection); } setNextState(IPlayerState::PLAYER_STATES::STATE_INITIAL); @@ -124,6 +125,18 @@ void MediaPlayerStateMachine::receiveTargetFps(double fps) { static_cast(m_States.value(IPlayerState::STATE_PLAY))->setFps(fps); } +void MediaPlayerStateMachine::receivePrevMediumCommand() { + PStateStepBack* state = dynamic_cast (m_States.value(IPlayerState::PLAYER_STATES::STATE_STEP_BACK)); + state->setPrevInBatch(true); + setNextState(IPlayerState::STATE_STEP_BACK); +} + +void MediaPlayerStateMachine::receiveNextMediumCommand() { + PStateStepForw* state = dynamic_cast (m_States.value(IPlayerState::PLAYER_STATES::STATE_STEP_FORW)); + state->setNextInBatch(true); + setNextState(IPlayerState::STATE_STEP_FORW); +} + void MediaPlayerStateMachine::receivetoggleRecordImageStream() { if (m_stream) m_PlayerParameters->m_RecI = m_stream->toggleRecord(); diff --git a/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h b/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h index eb3fccd2..26ba7ad4 100644 --- a/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h +++ b/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h @@ -64,6 +64,9 @@ class MediaPlayerStateMachine : public IModel { void receiveGoToFrame(int frame); void receiveTargetFps(double fps); + void receivePrevMediumCommand(); + void receiveNextMediumCommand(); + void receivetoggleRecordImageStream(); Q_SIGNALS: @@ -78,7 +81,8 @@ class MediaPlayerStateMachine : public IModel { void emitPlayerOperationDone(); void emitNextMediaInBatch(const std::string path); - void emitNextMediaInBatchLoaded(const std::string path); + void emitNextMediaInBatchLoaded(const std::string path, int batchIndex); + void emitEndOfPlayback(); private: void updatePlayerParameter(); diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp index 737c9994..9d26cf13 100644 --- a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp @@ -19,7 +19,6 @@ PStatePlay::PStatePlay(MediaPlayerStateMachine* player, m_FrameNumber = 0; - } void PStatePlay::operate() { @@ -40,17 +39,18 @@ void PStatePlay::operate() { m_FrameNumber = m_ImageStream->currentFrameNumber(); nextState = IPlayerState::STATE_PLAY; } else if (m_ImageStream->hasNextInBatch()){ - Q_EMIT emitNextMediaInBatch("Samplestring"); + Q_EMIT emitNextMediaInBatch(m_ImageStream->currentFilename()); m_ImageStream->stepToNextInBatch(); m_ImageStream->nextFrame(); m_Mat = m_ImageStream->currentFrame(); m_FrameNumber = m_ImageStream->currentFrameNumber(); nextState = IPlayerState::STATE_PLAY; - Q_EMIT emitNextMediaInBatchLoaded("Samplestring"); + Q_EMIT emitNextMediaInBatchLoaded(m_ImageStream->currentFilename(), m_ImageStream->currentBatchIndex() ); } else { nextState = IPlayerState::STATE_INITIAL_STREAM; - + qDebug() << "CORE: Last medium ended"; + Q_EMIT emitEndOfPlayback(); } //If fps is limited, wait the neccessary time diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp index c924e4d3..2772eb8f 100644 --- a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp @@ -14,7 +14,11 @@ PStateStepBack::PStateStepBack(MediaPlayerStateMachine* player, m_StateParameters.m_RecO = false; m_FrameNumber = 0; + m_prevInBatch = false; +} +void PStateStepBack::setPrevInBatch(bool prev) { + m_prevInBatch = prev; } void PStateStepBack::operate() { @@ -24,20 +28,42 @@ void PStateStepBack::operate() { m_StateParameters.m_Stop = true; m_StateParameters.m_Paus = false; + IPlayerState::PLAYER_STATES nextState = IPlayerState::STATE_INITIAL; + + // skip to next medium in batch if existing + if (m_prevInBatch && m_ImageStream->hasPrevInBatch()) { + m_StateParameters.m_Play = true; + m_StateParameters.m_Forw = false; + m_StateParameters.m_Back = false; + m_StateParameters.m_Stop = true; + m_StateParameters.m_Paus = true; - if (m_ImageStream->previousFrame()) { + Q_EMIT emitNextMediaInBatch(m_ImageStream->currentFilename()); + m_ImageStream->stepToPrevInBatch(); + m_ImageStream->nextFrame(); m_Mat = m_ImageStream->currentFrame(); - m_FrameNumber = m_ImageStream->currentFrameNumber(); - } + m_FrameNumber = m_ImageStream->currentFrameNumber(); + nextState = IPlayerState::STATE_PLAY; + Q_EMIT emitNextMediaInBatchLoaded(m_ImageStream->currentFilename(), m_ImageStream->currentBatchIndex()); - bool stateBack = false; - if (m_FrameNumber <= 0) { - stateBack = false; - } else { - stateBack = true; + m_prevInBatch = false; } + else{ + if (m_ImageStream->previousFrame()) { + m_Mat = m_ImageStream->currentFrame(); + m_FrameNumber = m_ImageStream->currentFrameNumber(); + } - m_StateParameters.m_Back = stateBack; + bool stateBack = false; + if (m_FrameNumber <= 0) { + stateBack = false; + } else { + stateBack = true; + } + + m_StateParameters.m_Back = stateBack; + nextState = IPlayerState::STATE_WAIT; + } - m_Player->setNextState(IPlayerState::STATE_WAIT); + m_Player->setNextState(nextState); } diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h index 5a805aed..c4d789d3 100644 --- a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h @@ -17,9 +17,17 @@ class PStateStepBack : public IPlayerState { public: PStateStepBack(MediaPlayerStateMachine* player, std::shared_ptr imageStream); + /** + * This function sets the previous medium flag. + */ + void setPrevInBatch(bool next); + // IPlayerState interface public Q_SLOTS: void operate() override; + + private: + bool m_prevInBatch; }; #endif // PSTATESTEPBACK_H diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp index fae818ab..15147edc 100644 --- a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp @@ -14,7 +14,11 @@ PStateStepForw::PStateStepForw(MediaPlayerStateMachine* player, m_StateParameters.m_RecO = false; m_FrameNumber = 0; + m_nextInBatch = false; +} +void PStateStepForw::setNextInBatch(bool next) { + m_nextInBatch = next; } void PStateStepForw::operate() { @@ -24,20 +28,43 @@ void PStateStepForw::operate() { m_StateParameters.m_Stop = true; m_StateParameters.m_Paus = false; + IPlayerState::PLAYER_STATES nextState = IPlayerState::STATE_INITIAL; + + // skip to next medium in batch if existing + if (m_nextInBatch && m_ImageStream->hasNextInBatch()) { + m_StateParameters.m_Play = true; + m_StateParameters.m_Forw = false; + m_StateParameters.m_Back = false; + m_StateParameters.m_Stop = true; + m_StateParameters.m_Paus = true; - if (m_ImageStream->nextFrame()) { + Q_EMIT emitNextMediaInBatch(m_ImageStream->currentFilename()); + m_ImageStream->stepToNextInBatch(); + m_ImageStream->nextFrame(); m_Mat = m_ImageStream->currentFrame(); - m_FrameNumber = m_ImageStream->currentFrameNumber(); - } + m_FrameNumber = m_ImageStream->currentFrameNumber(); + nextState = IPlayerState::STATE_PLAY; + Q_EMIT emitNextMediaInBatchLoaded(m_ImageStream->currentFilename(), m_ImageStream->currentBatchIndex()); - bool stateFw = false; - if (m_ImageStream->lastFrame()) { - stateFw = false; - } else { - stateFw = true; + m_nextInBatch = false; } + // else just skip to next frame + else{ + if (m_ImageStream->nextFrame()) { + m_Mat = m_ImageStream->currentFrame(); + m_FrameNumber = m_ImageStream->currentFrameNumber(); + } - m_StateParameters.m_Forw = true; + bool stateFw = false; + if (m_ImageStream->lastFrame()) { + stateFw = false; + } else { + stateFw = true; + } + + m_StateParameters.m_Forw = stateFw; + nextState = IPlayerState::STATE_WAIT; + } - m_Player->setNextState(IPlayerState::STATE_WAIT); + m_Player->setNextState(nextState); } diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h index 44b67703..d65733e5 100644 --- a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h @@ -17,9 +17,16 @@ class PStateStepForw : public IPlayerState { public: PStateStepForw(MediaPlayerStateMachine* player, std::shared_ptr imageStream); + /** + * This function sets the next medium flag. + */ + void setNextInBatch(bool next); + // IPlayerState interface public Q_SLOTS: void operate() override; + private: + bool m_nextInBatch; }; #endif // PSTATESTEPFORW_H diff --git a/Src/Model/TextureObject.cpp b/Src/Model/TextureObject.cpp index 781939be..39a59a10 100644 --- a/Src/Model/TextureObject.cpp +++ b/Src/Model/TextureObject.cpp @@ -13,6 +13,10 @@ void TextureObject::set(const cv::Mat &img) { //TODO Andi this cv::Mat is null sometimes when using the camera!? if (&img == NULL) return; + + if(img.empty()){ + return; + } if (img.channels() == 3) { img.convertTo(img, CV_8UC3); cv::cvtColor(img, m_img, cv::ColorConversionCodes::COLOR_BGR2RGB); @@ -36,7 +40,9 @@ void TextureObject::set(const cv::Mat &img) { const double convertedMin = abs(static_cast(min * sizeRatio)); img.convertTo(img8U, CV_8U, sizeRatio, convertedMin); } - cv::cvtColor(img8U, m_img, cv::ColorConversionCodes::COLOR_GRAY2RGB); + if(!img8U.empty()){ + cv::cvtColor(img8U, m_img, cv::ColorConversionCodes::COLOR_GRAY2RGB); + } } else { m_img = img; } diff --git a/Src/View/AreaDesciptor/PolygonDescriptor.cpp b/Src/View/AreaDesciptor/PolygonDescriptor.cpp new file mode 100644 index 00000000..d02eba9e --- /dev/null +++ b/Src/View/AreaDesciptor/PolygonDescriptor.cpp @@ -0,0 +1,181 @@ +#include "PolygonDescriptor.h" + +#include "QBrush" +#include "QPainter" +#include + +#include "Utility/misc.h" +#include "Model/AreaDescriptor/AreaInfoElement.h" +#include "Model/AreaDescriptor/AreaInfo.h" +#include + +// double orientation(cv::Point2f p1, cv::Point2f p2) +// { +// cv::Point2f diff = p1 - p2; +// // need to check the origin of coorindiates +// return std::atan2(p1.y - p2.y, p1.x - p2.x); +// } + +PolygonDescriptor::PolygonDescriptor(IController *controller, IModel *model) : + AreaDescriptor(controller, model) +{ + _dragVectorId = -1; + _dragType = BiotrackerTypes::AreaType::NONE; + setAcceptHoverEvents(true); + + _brush = QBrush(Qt::blue); + + _v = (dynamic_cast(getModel()))->getVertices(); + setRect(_v); + + _isInit = false; +} + +void PolygonDescriptor::init() { + int numberOfVertices = _rectification.size(); + for (int i = 0; i < numberOfVertices; i++) { + _rectification[i]->setAcceptHoverEvents(true); + _rectification[i]->installSceneEventFilter(this); + } +} + +void PolygonDescriptor::setBrush(QBrush brush) { + int numberOfVertices = _rectification.size(); + for (int i = 0; i < numberOfVertices; i++) { + _rectification[i]->setBrush(brush); + } + _brush = brush; +} + +void PolygonDescriptor::updateRect() { + setRect(getRect()); +} + +void PolygonDescriptor::setRect(std::vector rect) { + std::vector> rectification; + std::vector> rectificationLines; + // std::vector> rectificationNumbers; + + // _v = (dynamic_cast(getModel()))->getVertices(); + //Create QGraphicsRectItem for each vertex + int numberOfVertices = rect.size(); + for (int i = 0; i < numberOfVertices; i++) { + std::shared_ptr ri = std::make_shared(QRect(rect[i].x - 10, rect[i].y - 10, 20, 20), this); + ri->setBrush(_brush); + rectification.push_back(ri); + // //Numbers at corners + // if ((dynamic_cast(getModel()))->getShowNumbers()) { + // std::shared_ptr ti = std::make_shared(QString::number(i), this); + // ti->setPos(_v[i].x + 10, _v[i].y + 10); + // ti->setFont(QFont("Arial", 20)); + // rectificationNumbers.push_back(ti); + // } + } + + //Create QGraphicsLineItem for each edge + for (int i = 0; i < numberOfVertices; i++) { + + auto fst = rectification[i]; + auto snd = rectification[(i + 1) % numberOfVertices]; + + std::shared_ptr ri = std::make_shared( + QLine(fst->rect().x() + 10, fst->rect().y() + 10, snd->rect().x() + 10, snd->rect().y() + 10), this); + + rectificationLines.push_back(ri); + // if ((dynamic_cast(getModel()))->getShowNumbers()) { + // std::string label = "???"; + // if (i % 2 == 0) { + // label = std::to_string(_cfg->RectificationHeight); + // label.erase(label.find_last_not_of('0') + 1, std::string::npos); + // } + // else { + // label = std::to_string(_cfg->RectificationWidth); + // label.erase(label.find_last_not_of('0') + 1, std::string::npos); + // } + // std::shared_ptr ti = std::make_shared(label.c_str(), this); + // cv::Point2f a(fst->rect().x() + 10, fst->rect().y() + 10); + // cv::Point2f b(snd->rect().x() + 10, snd->rect().y() + 10); + // double alpha = orientation(a, b) * 180 / CV_PI; + // //Fix upside down text + // alpha = alpha > 0 ? 180 - alpha : alpha; + // cv::Point2f c = a + (b - a) * 0.5; + // ti->setPos(c.x, c.y); + // ti->setFont(QFont("Arial", 20)); + // ti->setRotation(-1*alpha); + // rectificationNumbers.push_back(ti); + // } + } + _rectification = rectification; + _rectificationLines = rectificationLines; + // _rectificationNumbers = rectificationNumbers; +} + +std::vector PolygonDescriptor::getRect() { + return (dynamic_cast(getModel()))->getVertices(); +} + +void PolygonDescriptor::receiveDragUpdate(BiotrackerTypes::AreaType vectorType, int id, double x, double y) { + _dragType = (dynamic_cast(getModel()))->getAreaType(); + if (_dragType == vectorType) { + _dragVectorId = id; + _drag = QPoint(x,y); + } + else { + _dragVectorId = -1; + } + update(); +} + +PolygonDescriptor::~PolygonDescriptor() +{ +} + +void PolygonDescriptor::getNotified() { + +} + +QRectF PolygonDescriptor::boundingRect() const +{ + return QRect(10,10,10,10); +} + +void PolygonDescriptor::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + if (!_isInit) + init(); + + //We want smooth lines! + painter->setRenderHint(QPainter::Antialiasing); + + //TODO remove hardcoding and code duplication + if (_dragVectorId >= 0 && _dragType != BiotrackerTypes::AreaType::NONE) { + QColor transparentGray = Qt::gray; + transparentGray.setAlphaF(0.75); + painter->setPen(QPen(transparentGray, 1, Qt::SolidLine)); + painter->drawRect(_drag.x()-10, _drag.y()-10, 20, 20); + int numberOfVertices = _rectification.size(); + int fstId = (_dragVectorId - 1) % numberOfVertices; + fstId = (fstId == -1 ? numberOfVertices-1 : fstId); + auto fst = _rectification[fstId]; + auto snd = _rectification[(_dragVectorId + 1) % numberOfVertices]; + painter->drawLine(QLine(fst->rect().x() + 10, fst->rect().y() + 10, _drag.x(), _drag.y())); + painter->drawLine(QLine(snd->rect().x() + 10, snd->rect().y() + 10, _drag.x(), _drag.y())); + } +} + +void PolygonDescriptor::updateLinePositions() { + int numberOfVertices = _rectification.size(); + for (int i = 0; i < numberOfVertices; i++) { + + auto fst = _rectification[i]; + auto snd = _rectification[(i + 1) % numberOfVertices]; + auto ln = _rectificationLines[i]; + ln->setLine(QLine(fst->rect().x() + 10, fst->rect().y() + 10, snd->rect().x() + 10, snd->rect().y() + 10)); + } + +} + +bool PolygonDescriptor::sceneEventFilter(QGraphicsItem *watched, QEvent *event) { + + return 0; +} diff --git a/Src/View/AreaDesciptor/PolygonDescriptor.h b/Src/View/AreaDesciptor/PolygonDescriptor.h new file mode 100644 index 00000000..b2f326aa --- /dev/null +++ b/Src/View/AreaDesciptor/PolygonDescriptor.h @@ -0,0 +1,61 @@ +#pragma once + +#include "AreaDescriptor.h" +#include +#include +#include "util/types.h" +#include + +class PolygonDescriptor : public AreaDescriptor +{ + Q_OBJECT +public: + PolygonDescriptor(IController *controller = 0, IModel *model = 0); + ~PolygonDescriptor(); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + + QRectF boundingRect() const override; + + void setBrush(QBrush brush) override; + void setRect(std::vector rect) override; + std::vector getRect() override; + + void updateRect() override; + + // IViewTrackedComponent interface +public Q_SLOTS: + void getNotified(); + void receiveDragUpdate(BiotrackerTypes::AreaType vectorType, int id, double x, double y); + +protected: + bool sceneEventFilter(QGraphicsItem * watched, QEvent * event) override; + void updateLinePositions(); + +private: + void init(); + bool _isInit; + + QGraphicsItem *_watchingDrag; + int _dragX; + int _dragY; + + std::vector _v; + + //Rects + std::vector> _rectification; + std::vector> _rectificationLines; + std::vector> _rectificationNumbers; + + QBrush _brush; + + BiotrackerTypes::AreaType _dragType; + int _dragVectorId; + QPoint _drag; + + // IView interface +public: + void setNewModel(IModel *model) override { setModel(model); }; +protected: + void connectModelView() override {}; +}; + diff --git a/Src/View/ComponentShape.cpp b/Src/View/ComponentShape.cpp index e23e6d49..1ce95b2d 100644 --- a/Src/View/ComponentShape.cpp +++ b/Src/View/ComponentShape.cpp @@ -75,6 +75,7 @@ ComponentShape::ComponentShape(QGraphicsObject* parent, setFlag(ItemIsMovable); setFlag(ItemIsSelectable); setAcceptedMouseButtons(Qt::LeftButton); + setToolTip(QString::number(m_id)); setVisible(true); } @@ -962,7 +963,10 @@ void ComponentShape::setMembers(CoreParameter* coreParams) m_orientationLine = coreParams->m_trackOrientationLine; m_showId = coreParams->m_trackShowId; - m_brushColor = *(coreParams->m_colorBrush); + // m_brushColor = *(coreParams->m_colorBrush); + + int colorInt = (m_id % 12) + 7; // 12 colors in Qt::GlobalColor in range 7 to 18; m_id can be unlimited so first mod 12 + m_brushColor = QColor(Qt::GlobalColor(colorInt)); m_penColor = *(coreParams->m_colorBorder); m_dragged = false; @@ -1079,7 +1083,7 @@ bool ComponentShape::removeTrackEntity() Q_EMIT emitRemoveTrackEntity(m_trajectory, m_currentFramenumber); } else { - qDebug() << "track entity is not removable"; + qDebug() << "Track entity is not removable"; } return m_pRemovable; } diff --git a/Src/View/CoreParameterView.cpp b/Src/View/CoreParameterView.cpp index 0dcb72e3..f9dc8f5d 100644 --- a/Src/View/CoreParameterView.cpp +++ b/Src/View/CoreParameterView.cpp @@ -84,18 +84,28 @@ void CoreParameterView::setPermission(std::pair pe void CoreParameterView::triggerUpdate() { on_checkBoxDisplayTrackingArea_stateChanged(0); on_checkBoxDisplayRectification_stateChanged(0); - on_checkboxTrackingAreaAsEllipse_stateChanged(0); + // on_checkboxTrackingAreaAsEllipse_stateChanged(0); } void CoreParameterView::areaDescriptorTypeChanged(QString type) { - if (type != "0") { - ui->checkboxTrackingAreaAsEllipse->setChecked(true); + if (type == "0") { + ui->radioButtonRect->setChecked(true); } - else { - ui->checkboxTrackingAreaAsEllipse->setChecked(false); + else if (type == "1"){ + ui->radioButtonEllipse->setChecked(true); + } + else if (type == "2"){ + ui->radioButtonPolygon->setChecked(true); } } +void CoreParameterView::trAreaNumberOfVertsChanged(int i){ + ui->spinBoxVertices->blockSignals(true); //Shush, block your signals + ui->spinBoxVertices->setValue(i); + ui->spinBoxVertices->blockSignals(false); //OK, emit from now on + +} + void CoreParameterView::on_checkBoxEnableCoreView_stateChanged(int v) { CoreParameter* coreParams = dynamic_cast(getModel()); @@ -278,8 +288,27 @@ void CoreParameterView::on_checkBoxDisplayRectification_stateChanged(int v) { Q_EMIT emitDisplayRectification(ui->checkBoxDisplayRectification->isChecked()); } -void CoreParameterView::on_checkboxTrackingAreaAsEllipse_stateChanged(int v) { - Q_EMIT emitTrackingAreaAsEllipse(ui->checkboxTrackingAreaAsEllipse->isChecked()); +// void CoreParameterView::on_checkboxTrackingAreaAsEllipse_stateChanged(int v) { +// Q_EMIT emitTrackingAreaAsEllipse(ui->checkboxTrackingAreaAsEllipse->isChecked()); +// } + +void CoreParameterView::on_radioButtonRect_toggled(bool checked){ + if (checked) + Q_EMIT emitTrackingAreaType(0); +} + +void CoreParameterView::on_radioButtonEllipse_toggled(bool checked){ + if (checked) + Q_EMIT emitTrackingAreaType(1); +} + +void CoreParameterView::on_radioButtonPolygon_toggled(bool checked){ + if (checked) + Q_EMIT emitTrackingAreaType(2); +} + +void CoreParameterView::on_spinBoxVertices_valueChanged(int i){ + Q_EMIT emitTrArNumberOfVertices(i); } void CoreParameterView::on_pushButtonAnnoColor_clicked() @@ -534,7 +563,6 @@ void CoreParameterView::on_pushButton_resetData_clicked(){ Q_EMIT emitFinalizeExperiment(); } - void CoreParameterView::on_pushButton_addTraj_clicked(){ emitAddTrack(); } diff --git a/Src/View/CoreParameterView.h b/Src/View/CoreParameterView.h index bbef97b6..9ceac9a9 100644 --- a/Src/View/CoreParameterView.h +++ b/Src/View/CoreParameterView.h @@ -31,6 +31,7 @@ class CoreParameterView : public IViewWidget void triggerUpdate(); void areaDescriptorTypeChanged(QString type); + void trAreaNumberOfVertsChanged(int i); private slots: @@ -65,7 +66,6 @@ class CoreParameterView : public IViewWidget void on_checkBoxTrackOrientationLine_stateChanged(int v); void on_checkBoxShowId_stateChanged(int v); - void on_pushButtonTrackDimensionSetterAll_clicked(); void on_pushButtonTrackDimensionSetterSelected_clicked(); void on_pushButtonDefaultDimensions_clicked(); @@ -75,7 +75,11 @@ class CoreParameterView : public IViewWidget void on_lineEditRectHeight_textChanged(QString s); void on_checkBoxDisplayTrackingArea_stateChanged(int v); void on_checkBoxDisplayRectification_stateChanged(int v); - void on_checkboxTrackingAreaAsEllipse_stateChanged(int v); + // void on_checkboxTrackingAreaAsEllipse_stateChanged(int v); + void on_radioButtonRect_toggled(bool checked); + void on_radioButtonEllipse_toggled(bool checked); + void on_radioButtonPolygon_toggled(bool checked); + void on_spinBoxVertices_valueChanged(int i); //Annotations void on_pushButtonAnnoColor_clicked(); @@ -158,7 +162,9 @@ class CoreParameterView : public IViewWidget void emitRectDimensions(double w, double h); void emitDisplayTrackingArea(bool b); void emitDisplayRectification(bool b); - void emitTrackingAreaAsEllipse(bool b); + // void emitTrackingAreaAsEllipse(bool b); + void emitTrackingAreaType(int t); + void emitTrArNumberOfVertices(int v); //Annotations void emitSetAnnoColor(QColor color); diff --git a/Src/View/CoreParameterView.ui b/Src/View/CoreParameterView.ui index 7e449dae..08f731f9 100644 --- a/Src/View/CoreParameterView.ui +++ b/Src/View/CoreParameterView.ui @@ -155,9 +155,9 @@ 0 - 0 + -284 333 - 938 + 959 @@ -1459,12 +1459,12 @@ - + - Show the tracking area + Show the rectification area - Display tracking area definition + Display Rectification definition false @@ -1485,15 +1485,15 @@ - + - Show the rectification area + Show the tracking area - Display Rectification definition + Display tracking area definition - false + true @@ -1511,13 +1511,40 @@ - - - Set the trackingarea to ellipse - - - Tracking area as ellipse - + + + + + + Rect + + + + + + + Ellipse + + + + + + + Polygon: + + + + + + + 4 + + + 5 + + + + diff --git a/Src/View/GraphicsView.cpp b/Src/View/GraphicsView.cpp index 8aa23a68..49e34067 100644 --- a/Src/View/GraphicsView.cpp +++ b/Src/View/GraphicsView.cpp @@ -150,6 +150,12 @@ void GraphicsView::mouseMoveEvent(QMouseEvent*event) } } +void GraphicsView::enterEvent(QEvent *event) + { + QGraphicsView::enterEvent(event); + viewport()->setCursor(Qt::CrossCursor); + } + void GraphicsView::receiveToggleAntialiasingFull(bool toggle){ setRenderHint(QPainter::Antialiasing, toggle); } \ No newline at end of file diff --git a/Src/View/GraphicsView.h b/Src/View/GraphicsView.h index a289bc70..d7200bc3 100644 --- a/Src/View/GraphicsView.h +++ b/Src/View/GraphicsView.h @@ -21,7 +21,7 @@ class GraphicsView : public IViewGraphicsView void mouseMoveEvent(QMouseEvent*event) override; void keyReleaseEvent(QKeyEvent *event) override; void keyPressEvent(QKeyEvent *event) override; - + void enterEvent(QEvent *event) override; // IGraphicsView interface public Q_SLOTS: diff --git a/Src/View/MainWindow.cpp b/Src/View/MainWindow.cpp index 6d72e6b8..30cd074a 100644 --- a/Src/View/MainWindow.cpp +++ b/Src/View/MainWindow.cpp @@ -228,7 +228,48 @@ void MainWindow::addVideoView(IView* videoView) { m_graphView = dynamic_cast(videoView); m_graphView->setParent(ui->trackingArea); - ui->videoViewLayout->addWidget(m_graphView); + ui->videoViewLayout->addWidget(m_graphView, 0, 0); + this->addZoomButtons(); +} + +void MainWindow::addZoomButtons(){ + //zoom pushbottons + QWidget* zoomButtons = new QWidget(ui->trackingArea); + QVBoxLayout* zoomButtonLayout = new QVBoxLayout; + zoomButtons->setLayout(zoomButtonLayout); + zoomButtons->setMaximumSize(60, 16777215); + QPushButton* zoomInButton = new QPushButton(QString("+"), ui->trackingArea); + QPushButton* zoomOutButton = new QPushButton(QString("-"), ui->trackingArea); + zoomInButton->setObjectName("zoomButton"); + zoomOutButton->setObjectName("zoomButton"); + QObject::connect(zoomInButton, &QPushButton::clicked, this, &MainWindow::zoomIn); + QObject::connect(zoomOutButton, &QPushButton::clicked, this, &MainWindow::zoomOut); + + QString buttonStyles = QString("QPushButton#zoomButton {" + "background-color: rgba(229, 229, 229, 200);" + "border-style: outset;" + "border-width: 2px;" + "border-radius: 10px;" + "border-color: rgba(229, 229, 229, 200);" + "font: bold 14px;" + "max-width: 20px;" + "max-height: 20px;" + "min-width: 20px;" + "min-height: 20px;" + "padding: 6px;" + "}" + "QPushButton#zoomButton:pressed {" + "background-color: rgb(200, 200, 200);" + "border-style: inset;" + "}"); + zoomButtons->setStyleSheet(buttonStyles); + + zoomButtonLayout->addWidget(zoomInButton); + zoomButtonLayout->addWidget(zoomOutButton); + + zoomButtonLayout->setContentsMargins(0,0,50,25); + + ui->videoViewLayout->addWidget(zoomButtons, 0, 0, Qt::AlignRight | Qt::AlignBottom); } void MainWindow::addTrackerElementsView(IView *elemView) @@ -667,6 +708,14 @@ void MainWindow::toggleNoShowWiz(bool toggle) { _cfg->DisableWizard = toggle;//Todo implicit cast bool->int } +void MainWindow::zoomIn(bool checked) { + m_graphView->scale(1.1, 1.1); +} + +void MainWindow::zoomOut(bool checked) { + m_graphView->scale(0.9, 0.9); +} + void MainWindow::receiveSelectedCameraDevice(CameraConfiguration conf) { qobject_cast (getController())->loadCameraDevice(conf); @@ -786,7 +835,7 @@ void MainWindow::on_actionOpen_Video_batch_triggered() { std::vector files; for (QString const& path : QFileDialog::getOpenFileNames(this, - "Open image files", "", videoFilter, 0)) { + "Open video files", "", videoFilter, 0)) { files.push_back(boost::filesystem::path(path.toStdString())); } @@ -827,7 +876,7 @@ void MainWindow::on_actionLoad_trackingdata_triggered() { std::vector files; for (QString const& path : QFileDialog::getOpenFileNames(this, - "Open tracking file", "", imageFilter, 0)) { + "Open tracking file", _cfg->DirTracks, imageFilter, 0)) { files.push_back(boost::filesystem::path(path.toStdString())); } @@ -945,6 +994,10 @@ void MainWindow::on_actionOpen_Screenshot_directory_triggered() { void MainWindow::on_actionOpen_Videos_directory_triggered() { QDesktopServices::openUrl(QUrl::fromLocalFile(_cfg->DirVideos)); } +void MainWindow::on_actionOpen_Config_directory_triggered() { + QFileInfo fi(_cfg->AreaDefinitions); + QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absolutePath())); +} //////////////////////////////////menu->Help slots////////////////////////////// @@ -995,7 +1048,6 @@ void MainWindow::on_actionShortcuts_triggered() { scTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Description")); scTable->verticalHeader()->hide(); - QLinkedList> scList; //read from file in resources and add to linked list diff --git a/Src/View/MainWindow.h b/Src/View/MainWindow.h index e8f7357c..22b7af87 100644 --- a/Src/View/MainWindow.h +++ b/Src/View/MainWindow.h @@ -73,12 +73,16 @@ class MainWindow : public IViewMainWindow { void resetTrackerViews(); + void addZoomButtons(); + Q_SIGNALS: void selectPlugin(QString ct); private Q_SLOTS: void toggleNoShowWiz(bool toggle); + void zoomIn(bool checked); + void zoomOut(bool checked); //menu->File void on_actionOpen_Video_triggered(); @@ -121,6 +125,7 @@ class MainWindow : public IViewMainWindow { void on_actionOpen_Trial_directory_triggered(); void on_actionOpen_Screenshot_directory_triggered(); void on_actionOpen_Videos_directory_triggered(); + void on_actionOpen_Config_directory_triggered(); //view toolbar actions diff --git a/Src/View/MainWindow.ui b/Src/View/MainWindow.ui index de7321a3..29cba386 100644 --- a/Src/View/MainWindow.ui +++ b/Src/View/MainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 1022 - 565 + 1551 + 789 @@ -143,7 +143,7 @@ 0 - + 0 @@ -439,15 +439,15 @@ 1 - 3 + 1 0 0 - 743 - 304 + 1090 + 528 @@ -469,8 +469,8 @@ 0 0 - 743 - 304 + 1090 + 528 @@ -515,8 +515,8 @@ 0 0 - 743 - 304 + 1090 + 528 @@ -551,8 +551,8 @@ 0 0 - 743 - 304 + 1090 + 528 @@ -641,8 +641,8 @@ p, li { white-space: pre-wrap; } 0 0 - 743 - 304 + 1090 + 528 @@ -690,7 +690,7 @@ p, li { white-space: pre-wrap; } 0 0 - 1022 + 1551 21 @@ -762,6 +762,8 @@ p, li { white-space: pre-wrap; } + + @@ -1369,6 +1371,11 @@ QToolButton { Open Video Batch... + + + Open Configuration directory + + diff --git a/Src/View/NotificationLogBrowser.cpp b/Src/View/NotificationLogBrowser.cpp index 51bdb883..52b45dda 100644 --- a/Src/View/NotificationLogBrowser.cpp +++ b/Src/View/NotificationLogBrowser.cpp @@ -1,13 +1,17 @@ #include "NotificationLogBrowser.h" #include "QVBoxLayout" +#include "QScrollBar" +#include "QMutexLocker" NotificationLogBrowser::NotificationLogBrowser(QWidget *parent, IController *controller, IModel *model) : IViewWidget(parent, controller, model) { + QMutex m_mutex; QVBoxLayout *layout = new QVBoxLayout(this); - browser = new QTextBrowser(this); + browser = new QTextEdit(this); + browser->setReadOnly(true); browser->setLineWrapMode(QTextEdit::NoWrap); layout->addWidget(browser); @@ -28,24 +32,37 @@ NotificationLogBrowser::~NotificationLogBrowser() { } -void NotificationLogBrowser::outputMessage(QtMsgType type, const QString & msg) +void NotificationLogBrowser::outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + QMutexLocker locker(&m_mutex); switch (type) { - case QtDebugMsg: - browser->append(msg); - break; + case QtDebugMsg: + case QtInfoMsg: + browser->append(msg); + break; - case QtWarningMsg: - browser->append(tr("- %1 ").arg(msg)); - break; + case QtWarningMsg: + browser->append(tr("- %1 line: %2").arg(msg).arg(context.line)); + break; - case QtCriticalMsg: - browser->append(tr("- %1 ").arg(msg)); - break; + case QtCriticalMsg: + browser->append(tr("- %1 line: %2").arg(msg).arg(context.line)); + break; - case QtFatalMsg: - browser->append(tr("- %1 ").arg(msg)); - break; + case QtFatalMsg: + browser->append(tr("- %1 line: %2").arg(msg).arg(context.line)); + break; + + default: + browser->append(msg); + break; + } + + QScrollBar *sb = browser->verticalScrollBar(); + int value = sb->value(); + int max = sb->maximum(); + if(max - value <= 15){ + sb->setValue(sb->maximum()); } } void NotificationLogBrowser::getNotified() { diff --git a/Src/View/NotificationLogBrowser.h b/Src/View/NotificationLogBrowser.h index eaa6c1b3..8db9f4dc 100644 --- a/Src/View/NotificationLogBrowser.h +++ b/Src/View/NotificationLogBrowser.h @@ -3,7 +3,8 @@ #pragma once #include "Interfaces/IView/IViewWidget.h" -#include +#include +#include /** * This is the view of the notifications component. @@ -18,15 +19,16 @@ class NotificationLogBrowser : public IViewWidget explicit NotificationLogBrowser(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); ~NotificationLogBrowser(); - void outputMessage(QtMsgType type, const QString &msg); + void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg); // IViewWidget interface public slots: void getNotified(); private: - QTextBrowser *browser; + QTextEdit *browser; QFont m_font; + QMutex m_mutex; }; diff --git a/Src/View/TrackedComponentView.cpp b/Src/View/TrackedComponentView.cpp index 9454444f..39de11da 100644 --- a/Src/View/TrackedComponentView.cpp +++ b/Src/View/TrackedComponentView.cpp @@ -95,6 +95,24 @@ void TrackedComponentView::mousePressEvent(QGraphicsSceneMouseEvent *event) { event->accept(); return; } + else if (event->button() == Qt::LeftButton) { + QList allSelected = this->scene()->selectedItems(); + if (!allSelected.isEmpty()){ + int size = allSelected.size(); + if (size == 1) { + ComponentShape* selectedItem = dynamic_cast(allSelected.at(0)); + if (selectedItem && selectedItem->isSelected() && (event->modifiers() == Qt::ControlModifier)) { + IModelTrackedTrajectory* shapeTrajectory = selectedItem->getTrajectory(); + //calculate the current pos and emit it to the commands component + selectedItem->emitMoveElement(shapeTrajectory, selectedItem->pos().toPoint() + QPoint(selectedItem->m_w / 2, selectedItem->m_h / 2), + event->pos().toPoint(), m_currentFrameNumber, 0); + selectedItem->setPos(event->pos() - QPoint(selectedItem->m_w / 2, selectedItem->m_h / 2)); + } + } + + + } + } QGraphicsItem::mousePressEvent(event); } @@ -151,7 +169,7 @@ void TrackedComponentView::contextMenuEvent(QGraphicsSceneContextMenuEvent * eve void TrackedComponentView::setPermission(std::pair permission) { m_permissions[permission.first] = permission.second; - qDebug() << permission.first << " set to" << permission.second; + qDebug() << "TRACKER: " << permission.first << " set to" << permission.second; //first check if permission is for view, if not pass permission to shapes -> view has all permissions, shapes only certain ones diff --git a/Src/View/VideoControllWidget.cpp b/Src/View/VideoControllWidget.cpp index 1bb498bd..b30f9c63 100644 --- a/Src/View/VideoControllWidget.cpp +++ b/Src/View/VideoControllWidget.cpp @@ -7,6 +7,7 @@ #include #include #include +#include VideoControllWidget::VideoControllWidget(QWidget* parent, IController* controller, IModel* model) : IViewWidget(parent, controller, model), @@ -22,6 +23,17 @@ VideoControllWidget::VideoControllWidget(QWidget* parent, IController* controlle QSize(), QIcon::Normal, QIcon::Off); ui->sld_video->setMinimum(0); + + QList pl_pa_list({QKeySequence(Qt::Key_Space),QKeySequence(Qt::Key_S)}); + QList st_list({QKeySequence(Qt::CTRL + Qt::Key_Space),QKeySequence(Qt::CTRL + Qt::Key_S)}); + QList prev_list({QKeySequence(Qt::Key_Left),QKeySequence(Qt::Key_A)}); + QList ne_list({QKeySequence(Qt::Key_Right),QKeySequence(Qt::Key_D)}); + + ui->actionPlay_Pause->setShortcuts(pl_pa_list); + ui->actionStop->setShortcuts(st_list); + ui->actionPrev_frame->setShortcuts(prev_list); + ui->actionNext_frame->setShortcuts(ne_list); + this->setSelectedView("Original"); updateGeometry(); } @@ -76,7 +88,6 @@ void VideoControllWidget::getNotified() { ui->time_edit->setText(currentVideoTime); - //Write current fps label every 1/2 second std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); long long dt = std::chrono::duration_cast(now - lastFpsSet).count(); @@ -180,9 +191,8 @@ void VideoControllWidget::on_sld_video_actionTriggered(int action) controller->setGoToFrame(position); } - /** - * If the video slider is moved, this function sets the value to the current frame number lable + * If the video slider is moved, this function sets the value to the current frame number label */ void VideoControllWidget::on_sld_video_sliderMoved(int position) { //ui->frame_num_edit->setText(QString::number(position)); @@ -205,7 +215,6 @@ void VideoControllWidget::on_frame_num_spin_editingFinished() { controller->setGoToFrame(val); } - //actions void VideoControllWidget::on_actionPlay_Pause_triggered(bool checked) { ControllerPlayer* controller = dynamic_cast(getController()); @@ -283,6 +292,14 @@ void VideoControllWidget::on_actionRecord_all_triggered(bool checked) { //ui->actionRecord_all->setIconSize(QSize(32, 32)); } } +void VideoControllWidget::on_pushButton_prevMedium_clicked(bool checked) { + ControllerPlayer* controller = dynamic_cast(getController()); + controller->prevMedium(); +} +void VideoControllWidget::on_pushButton_nextMedium_clicked(bool checked) { + ControllerPlayer* controller = dynamic_cast(getController()); + controller->nextMedium(); +} MainWindow* VideoControllWidget::getMainWindow() { @@ -318,3 +335,15 @@ void VideoControllWidget::setupVideoToolbar() { } } } + +void VideoControllWidget::mediumChanged(const std::string path, int batchIndex) { + ui->medium_label->setText(QString::fromStdString(path)); + + ui->medium_bCurr->setText(QString::number(batchIndex+1)); + +} + +void VideoControllWidget::getMaxBatchNumber(int number){ + ui->medium_bCurr->setText("1"); + ui->medium_bMax->setText(QString::number(number)); +} diff --git a/Src/View/VideoControllWidget.h b/Src/View/VideoControllWidget.h index f057b211..5d00a4c3 100644 --- a/Src/View/VideoControllWidget.h +++ b/Src/View/VideoControllWidget.h @@ -37,6 +37,8 @@ class VideoControllWidget : public IViewWidget { public Q_SLOTS: void getNotified(); + void mediumChanged(const std::string path, int batchIndex); + void getMaxBatchNumber(int number); private Q_SLOTS: void on_DurationChanged(int position); @@ -56,7 +58,7 @@ class VideoControllWidget : public IViewWidget { void on_sld_video_sliderMoved(int position); - void on_sld_video_actionTriggered(int action); + void on_sld_video_actionTriggered(int action); void on_doubleSpinBoxTargetFps_editingFinished(); @@ -71,6 +73,9 @@ class VideoControllWidget : public IViewWidget { void on_actionRecord_cam_triggered(bool checked = false); void on_actionRecord_all_triggered(bool checked = false); + void on_pushButton_prevMedium_clicked(bool checked = false); + void on_pushButton_nextMedium_clicked(bool checked = false); + private: Ui::VideoControllWidget* ui; diff --git a/Src/View/VideoControllWidget.ui b/Src/View/VideoControllWidget.ui index 5d4312f4..341d330c 100644 --- a/Src/View/VideoControllWidget.ui +++ b/Src/View/VideoControllWidget.ui @@ -9,7 +9,7 @@ 0 0 - 1056 + 1329 101 @@ -100,8 +100,8 @@ 0 0 - 1038 - 50 + 1311 + 51 @@ -151,7 +151,7 @@ 0 - + 0 @@ -161,12 +161,42 @@ Qt::LeftToRight + + QGroupBox { + border: 1px solid #e5e5e5; + border-radius: 5px; + spacing: 1px; + padding: 3px; + margin-top: 1ex; /* leave space at the top for the title */} + +QGroupBox::title{ + subcontrol-origin: margin; + subcontrol-position: top center; + padding: 0 3px;} + +QToolButton { + padding: 5px; + margin: 0px} + +QFrame[frameShape="4"], +QFrame[frameShape="5"] +{ + color: green; + border: none; + background: #e5e5e5; + max-width: 1px; +} + + + + false + - 0 + 1 - 0 + 1 0 @@ -177,20 +207,147 @@ 0 + + + + + 0 + 0 + + + + + 3 + + + 3 + + + 0 + + + 3 + + + 0 + + + + + + 30 + 0 + + + + + 30 + 16777215 + + + + Previous medium + + + « + + + + + + + Medium + + + + + + + ( + + + + + + + 0 + + + + + + + / + + + + + + + 0 + + + + + + + ): + + + + + + + none + + + + + + + + 30 + 0 + + + + + 30 + 16777215 + + + + Next medium + + + » + + + + + + + + + + Qt::Vertical + + + - 5 + 3 - 0 + 3 0 - 0 + 3 0 @@ -198,7 +355,7 @@ - Current time: + Time: @@ -228,11 +385,24 @@ 11 + + Qt::AlignCenter + + + + + QFrame::Sunken + + + Qt::Vertical + + + @@ -243,16 +413,16 @@ - 5 + 3 - 0 + 3 0 - 0 + 3 0 @@ -266,7 +436,7 @@ - Current frame: + Frame: @@ -278,6 +448,9 @@ 30 + + Qt::AlignCenter + QAbstractSpinBox::NoButtons @@ -295,6 +468,22 @@ + + + + false + + + QFrame::Plain + + + 1 + + + Qt::Vertical + + + @@ -305,7 +494,7 @@ - 0 + 3 3 @@ -360,6 +549,13 @@ + + + + Qt::Vertical + + + @@ -370,7 +566,7 @@ - 5 + 3 3 @@ -405,9 +601,18 @@ 0 + + + 60 + 30 + + Set a fps limit (0 for no limit) + + Qt::AlignCenter + 1 @@ -419,6 +624,13 @@ + + + + Qt::Vertical + + + diff --git a/Src/main.cpp b/Src/main.cpp index bac5d51d..dbc935a1 100644 --- a/Src/main.cpp +++ b/Src/main.cpp @@ -28,6 +28,7 @@ //#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") #endif +/* // Get the default Qt message handler. static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(0); @@ -46,6 +47,7 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QS (*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg); } +*/ int main(int argc, char* argv[]) { QApplication app(argc, argv); @@ -80,8 +82,10 @@ int main(int argc, char* argv[]) { qRegisterMetaType("playerParameters*"); qRegisterMetaType("CameraConfiguration"); qRegisterMetaTypeStreamOperators>("QList"); + qRegisterMetaType("QFileInfo"); + qRegisterMetaType("std::string"); - qInstallMessageHandler(myMessageOutput); + //qInstallMessageHandler(myMessageOutput); QDir qd; qd.mkpath(IConfig::configLocation); diff --git a/Src/util/CLIcommands.h b/Src/util/CLIcommands.h index 5444ad0c..28fcb802 100644 --- a/Src/util/CLIcommands.h +++ b/Src/util/CLIcommands.h @@ -14,6 +14,7 @@ #include #include +#include #include "util/types.h" #include "util/Config.h" @@ -32,6 +33,11 @@ class CLI { ("usePlugin", value(), "Uses plugin from given filepath") ("video", value(), "Loads a video from given filepath") ("cfg", value(), "Provide custom path to a config file") + ("autoPlay,a", "Automatically play video") + ("autoTrack,t",value(), "Automatically enable tracking with the set number of tracks") + ("autoClose,c","Automatically close program after last medium") + ("useMediaName,m", "Use tracked mediums name as name for tracking file") + ("loadTrack,l", value(), "Load tracking file") ; options_description gui("GUI options"); @@ -73,6 +79,28 @@ class CLI { auto str = vm["cfg"].as(); cfg->CfgCustomLocation = QString(str.c_str()); } + + if (vm.count("autoPlay")) { + cfg->AutoPlay = true; + } + + if(vm.count("autoTrack")){ + cfg->AutoTrack = vm["autoTrack"].as(); + } + + if(vm.count("autoClose")){ + cfg->AutoClose = true; + } + + if(vm.count("useMediaName")){ + cfg->UseMediaName = true; + } + + if(vm.count("loadTrack")){ + auto str = vm["loadTrack"].as(); + cfg->LoadTrack = QString(str.c_str()); + } + } catch (std::exception& e) { std::cout << e.what() << "\n"; diff --git a/Src/util/Config.cpp b/Src/util/Config.cpp index 8076e959..cc42b8bd 100644 --- a/Src/util/Config.cpp +++ b/Src/util/Config.cpp @@ -9,6 +9,10 @@ #include #include #include +#include +#include +#include +#include const QString Config::DefaultArena = "10,10;10,100;100,100;100,10"; @@ -64,8 +68,15 @@ void Config::load(QString dir, QString file) fin.open(QIODevice::ReadWrite); fin.close(); } + try{ + read_ini((dir + "/" + file).toStdString(), tree); + } + catch (std::exception const& e){ + qDebug() << e.what(); + QMessageBox::critical(NULL, QString("Can't read config.ini file!"), QString("%1\n\n%2").arg(e.what(), "\n Closing BioTracker..."), QMessageBox::Ok, QMessageBox::NoButton); + QTimer::singleShot(250, qApp, SLOT(quit())); //TODO this is hacky! change return value of load() to bool for better quitting + } - read_ini((dir + "/" + file).toStdString(), tree); Config* config = this; @@ -129,5 +140,13 @@ void Config::save(QString dir, QString file) tree.put(globalPrefix+"AreaDefinitions", config->AreaDefinitions); tree.put(globalPrefix+"UseRegistryLocations", config->UseRegistryLocations); - write_ini((dir + "/" + file).toStdString(), tree); + // write_ini((dir + "/" + file).toStdString(), tree); + + try{ + write_ini((dir + "/" + file).toStdString(), tree); + } + catch (std::exception const& e){ + qDebug() << e.what(); + QTimer::singleShot(250, qApp, SLOT(quit())); + } } diff --git a/Src/util/Config.h b/Src/util/Config.h index bcdd3be0..8e33afa0 100644 --- a/Src/util/Config.h +++ b/Src/util/Config.h @@ -37,6 +37,11 @@ class Config : public IConfig QString LoadVideo = ""; QString UsePlugins = ""; QString CfgCustomLocation = ""; + bool AutoPlay = false; + int AutoTrack = -1; + bool AutoClose = false; + bool UseMediaName = false; + QString LoadTrack = ""; void load(QString dir, QString file = "config.ini") override; void save(QString dir, QString file) override;