diff --git a/applications/mne_scan/libs/scDisp/realtimeneurofeedbackwidget.cpp b/applications/mne_scan/libs/scDisp/realtimeneurofeedbackwidget.cpp new file mode 100644 index 00000000000..9de6065b0e1 --- /dev/null +++ b/applications/mne_scan/libs/scDisp/realtimeneurofeedbackwidget.cpp @@ -0,0 +1,539 @@ +//============================================================================================================= +/** + * @file realtimeneurofeedbackwidget.cpp + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the RealTimeNeurofeedbackWidget Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "realtimeneurofeedbackwidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include +#include +#include +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace SCDISPLIB; +using namespace SCMEASLIB; +using namespace DISPLIB; +using namespace RTPROCESSINGLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +RealTimeNeurofeedbackWidget::RealTimeNeurofeedbackWidget(QSharedPointer &pTime, + QWidget* parent) +: MeasurementWidget(parent) +, m_iMaxFilterTapSize(-1) +{ + Q_UNUSED(pTime) + + qRegisterMetaType > > >(); + +} + +//============================================================================================================= + +RealTimeNeurofeedbackWidget::~RealTimeNeurofeedbackWidget() +{ + QSettings settings("MNECPP"); + + if(m_pChannelDataView && m_pRTNR) { + settings.setValue(QString("RTNW/showHideBad"), m_pChannelDataView->getBadChannelHideStatus()); + } +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::update(SCMEASLIB::Measurement::SPtr pMeasurement) +{ + + if(!m_pRTNR) { + m_pRTNR = qSharedPointerDynamicCast(pMeasurement); + } + + if(m_pRTNR) { + if(m_pRTNR->isChInit() && !m_pFiffInfo) { + m_pFiffInfo = m_pRTNR->info(); + m_iMaxFilterTapSize = m_pRTNR->getNeurofeedback().first().cols(); + + + if(!m_bDisplayWidgetsInitialized) { + initDisplayControllWidgets(); + if(m_pRTNR->getNeuroOutput()=="Frequency"){ + if(m_pRTNR->getallCh() == true || (unsigned int)m_pRTNR->getSlider()>m_pRTNR->getNumChannels()){ + m_pRTNR->setSlider(m_pRTNR->getNumChannels()); + } + QStringList startchannels; + for(int k = 0; kgetSlider(); ++k){ + startchannels.append(m_pRTNR->chInfo()[k].getChannelName()); + } + m_pChannelSelectionView->selectChannels(startchannels); + + } + else if(m_pRTNR->getNeuroOutput()=="Balloon"){ + QStringList balloonchannel; + balloonchannel.append(m_pRTNR->chInfo()[0].getChannelName()); + m_pChannelSelectionView->selectChannels(balloonchannel); + } + } + } else if (!m_pRTNR->getNeurofeedback().isEmpty()) { + m_matNeurofeedbackData = m_pRTNR->getNeurofeedback().last(); + QStringList selectedchannels; + selectedchannels = m_pChannelSelectionView->getSelectedChannels(); + if (m_pRTNR->getNeuroOutput() == "Classifier"){ + bool noClass = true; + for(int i = 0; igetNumbofClass(); ++i){ + unsigned int j = 0; + if(selectedchannels.isEmpty()){ + updateLabel("no Channels selected", "red"); + } + else{ + while(selectedchannels[0]!=m_pRTNR->chInfo()[j].getChannelName()){ + ++j; + if(j==m_pRTNR->getNumChannels()){ + updateLabel("no Channel available", "red"); + break; + } + } + if(j < m_matNeurofeedbackData.rows()){ + if(m_matNeurofeedbackData(j,0) == m_pRTNR->getClassI(i)){ + if(m_pRTNR->getClassImg(i).isNull()){ + updateLabel(m_pRTNR->getClassL(i), m_pRTNR->getClassCol(i)); + } + else{ + updateImage(m_pRTNR->getClassImg(i)); + } + noClass = false; + } + if(noClass == true){ + updateLabel("no Classification available", "black"); + } + } + else{ + updateLabel("no Channel available", "red"); + } + } + } + } + else if (m_pRTNR->getNeuroOutput() == "Frequency"){ + clearLayout(m_pLayout); + m_pRTNR->setSlider(selectedchannels.size()); + + if(selectedchannels.isEmpty()){ + updateLabel("no Channels selected", "red"); + } + else{ + for(int i = 0; igetSlider(); ++i){ + unsigned int j = 0; + bool channelavail = true; + while(selectedchannels[i]!=m_pRTNR->chInfo()[j].getChannelName()){ + ++j; + if(j==m_pRTNR->getNumChannels()){ + channelavail = false; + break; + } + } + + bool resetMinimum = false; + if(j < m_matNeurofeedbackData.rows() && channelavail == true){ + if(m_pRTNR->getMaxAutoScale()==true){ + for(int l = 0; lgetNumChannels(); m++){ + if(selectedchannels[l]== m_pRTNR->chInfo()[m].getChannelName()){ + if(m_pRTNR->getResetAutoscale()==true){ + m_pRTNR->setFMax(m_matNeurofeedbackData(m,0)); + m_pRTNR->setResetAutoScale(false); + resetMinimum = true; + } + else if((m_pRTNR->getNeurofeedback().last())(m,0)>m_pRTNR->getFMax()){ + m_pRTNR->setFMax(m_matNeurofeedbackData(m,0)); + } + } + } + } + } + if(m_pRTNR->getMinAutoScale()==true){ + for(int l = 0; lgetNumChannels(); m++){ + if(selectedchannels[l]== m_pRTNR->chInfo()[m].getChannelName()){ + if(resetMinimum == true || m_pRTNR->getResetAutoscale()==true){ + m_pRTNR->setFMin(m_matNeurofeedbackData(m,0)); + resetMinimum = false; + m_pRTNR->setResetAutoScale(false); + } + else if((m_pRTNR->getNeurofeedback().last())(m,0)getFMin()){ + m_pRTNR->setFMin(m_matNeurofeedbackData(m,0)); + } + } + } + } + } + + addSlider(i, m_matNeurofeedbackData(j,0), m_pRTNR->getFMax(), m_pRTNR->getFMin()); + + + QLabel* Label= new QLabel(this); + Label->setText(m_pRTNR->chInfo()[j].getChannelName()); + Label->setAlignment(Qt::AlignCenter); + QFont font; + font.setBold(true); + font.setPointSize(20); + Label->setFont(font); + m_pLayout->addWidget(Label, 6, 2*i, 1, 2); + } + else{ + QLabel* Label= new QLabel(this); + Label->setText("not available"); + Label->setAlignment(Qt::AlignCenter); + QFont font; + font.setBold(true); + font.setPointSize(20); + Label->setFont(font); + m_pLayout->addWidget(Label, 3, i+1); + break; + } + + } + } + m_pLayout->setContentsMargins(3,0,3,0); + m_pLayout->update(); + } + else if(m_pRTNR->getNeuroOutput() == "Balloon"){ + + QLabel* Label= new QLabel(this); + QPixmap background = m_pRTNR->getImgBackground(); + Label->setPixmap(background.scaledToHeight(300, Qt::FastTransformation)); + Label->setAlignment(Qt::AlignCenter); + + QLabel* Label1 = new QLabel(this); + QPixmap Balloon = m_pRTNR->getImgObject(); + + Label1->setPixmap(Balloon.scaled(40,40, Qt::KeepAspectRatio)); + Label1->setAlignment(Qt::AlignCenter); + + int maximum = m_pRTNR->getBMax(); + int minimum = m_pRTNR->getBMin(); + if(maximum <= minimum){ + maximum = minimum + 1; + } + int span = 300; + unsigned int i = 0; + while(selectedchannels[0]!=m_pRTNR->chInfo()[i].getChannelName()){ + ++i; + if(i==m_pRTNR->getNumChannels()){ + i = 0; + break; + } + } + int heightballoon = qRound(-span/(maximum-minimum)*m_matNeurofeedbackData(i,0)+250); + if (heightballoon<5){ + heightballoon = 5; + } + + clearLayout(m_pLayout); + + m_pLayout->addWidget(Label1, heightballoon, 0, Qt::AlignTop); + m_pLayout->addWidget(Label, 0, 0, 300, 0, Qt::AlignTop); + m_pLayout->update(); + + } + } + } +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::initDisplayControllWidgets() +{ + qDebug()<<"RealTimeNeurofeedbackWidget initDisplayContorllWidgets"; + if(m_pFiffInfo) { + //Create table view and set layout + m_pChannelDataView = new RtFiffRawView(QString("MNESCAN/RTNW"), + this); + m_pChannelDataView->hide(); + + QGridLayout *rtnLayout = new QGridLayout(this); + rtnLayout->setContentsMargins(0,0,0,0); + this->setLayout(rtnLayout); + this->setMinimumSize(300,50); + + m_pLayout = new QGridLayout(); + + QToolBar* pToolBar = new QToolBar; + + QAction* pActionSelectSensors = new QAction(QIcon(":/images/selectSensors.png"), tr("Show the channel selection view"),this); + pActionSelectSensors->setToolTip(tr("Show the channel selection view")); + connect(pActionSelectSensors, &QAction::triggered, + this, &RealTimeNeurofeedbackWidget::showSensorSelectionWidget); + pActionSelectSensors->setVisible(true); + pToolBar->addAction(pActionSelectSensors); + + + clearLayout(m_pLayout); + rtnLayout->addWidget(pToolBar, 0, 0); + rtnLayout->addWidget(m_pChannelDataView); + rtnLayout->addLayout(m_pLayout, 1, 0, -1, -1, Qt::AlignCenter); + rtnLayout->update(); + + // Init channel view + QSettings settings("MNECPP"); + QString sRTNWName = m_pRTNR->getName(); + +// m_pChannelDataView->show(); + m_pChannelDataView->init(m_pFiffInfo); + + if(settings.value(QString("RTNW/showHideBad"), false).toBool()) { + this->onHideBadChannels(); + } + + m_pChannelInfoModel = ChannelInfoModel::SPtr::create(m_pFiffInfo, + this); + + m_pChannelSelectionView = ChannelSelectionView::SPtr::create(QString("MNESCAN/RTNW"), + this, + m_pChannelInfoModel, + Qt::Window); + m_pChannelSelectionView->setWindowTitle(tr(QString("%1: Channel Selection Window").arg(sRTNWName).toUtf8())); + + connect(m_pChannelSelectionView.data(), &ChannelSelectionView::loadedLayoutMap, + m_pChannelInfoModel.data(), &ChannelInfoModel::layoutChanged); + + + m_pChannelInfoModel->layoutChanged(m_pChannelSelectionView->getLayoutMap()); + + //Init control widgets + QList lControlWidgets; + + + //Initialized + m_bDisplayWidgetsInitialized = true; + } +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::showSensorSelectionWidget() +{ + qDebug()<<"RealTimeNeurofeedbackWidget showSensorSelectionWidget"; + if(m_pChannelSelectionView->isActiveWindow()) { + m_pChannelSelectionView->hide(); + } else { + m_pChannelSelectionView->activateWindow(); + m_pChannelSelectionView->show(); + } +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::onMakeScreenshot(const QString& imageType) +{ + qDebug()<<"RealTimeNeurofeedbackWidget onMakeScreenshot"; + // Create file name + QString sDate = QDate::currentDate().toString("yyyy_MM_dd"); + QString sTime = QTime::currentTime().toString("hh_mm_ss"); + + if(!QDir("./Screenshots").exists()) { + QDir().mkdir("./Screenshots"); + } + + QString fileName; + + if(imageType.contains("SVG")) { + fileName = QString("./Screenshots/%1-%2-DataView.svg").arg(sDate).arg(sTime); + } else if(imageType.contains("PNG")) { + fileName = QString("./Screenshots/%1-%2-DataView.png").arg(sDate).arg(sTime); + } + + m_pChannelDataView->takeScreenshot(fileName); +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::onHideBadChannels() +{ + qDebug()<<"RealTimeNeurofeedbackWidget onHIdeBadChannels"; + m_pChannelDataView->hideBadChannels(); + + if(m_pActionHideBad->toolTip() == "Show all bad channels") { + m_pActionHideBad->setIcon(QIcon(":/images/hideBad.png")); + m_pActionHideBad->setToolTip("Hide all bad channels"); + m_pActionHideBad->setStatusTip(tr("Hide all bad channels")); + } else { + m_pActionHideBad->setIcon(QIcon(":/images/showBad.png")); + m_pActionHideBad->setToolTip("Show all bad channels"); + m_pActionHideBad->setStatusTip(tr("Show all bad channels")); + } +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::updateOpenGLViewport() +{ + qDebug()<<"RealTimeNeurofeedbackWidget updateOpbenGLViewport"; + if(m_pChannelDataView) { + m_pChannelDataView->updateOpenGLViewport(); + } +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::updateLabel(QString text, QString color) +{ + qDebug()<<"RealTimeNeurofeedbackWidget updateLabel"; + + + QLabel* Label= new QLabel(this); + Label->setText(text); + Label->setAlignment(Qt::AlignCenter); + QFont font; + font.setBold(true); + font.setPointSize(20); + Label->setFont(font); + if(color == "red"){ + Label->setStyleSheet("QLabel {color: red;}"); + } + else if (color == "green"){ + Label->setStyleSheet("QLabel {color: green;}"); + } + else if(color =="black"){ + Label->setStyleSheet("QLabel {color: black;}"); + } + clearLayout(m_pLayout); + m_pLayout->addWidget(Label); + m_pLayout->setContentsMargins(3,0,3,0); + m_pLayout->update(); +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::updateImage(QPixmap image) +{ + qDebug()<<"RealTimeNeurofeedbackWidget updateImage"; + + QLabel* Label= new QLabel(this); + Label->setPixmap(image.scaled(600, 300, Qt::KeepAspectRatio)); + Label->setAlignment(Qt::AlignCenter); + clearLayout(m_pLayout); + m_pLayout->addWidget(Label); + m_pLayout->setContentsMargins(3,0,3,0); + m_pLayout->update(); +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::addSlider(int value, int output, int Max, int Min) +{ + int tickint; + QVector vec; + vec.push_back(1); + vec.push_back(2); + vec.push_back(5); + vec.push_back(10); + int j = round((Max-Min)/10); + + auto const i = std::lower_bound(vec.begin(), vec.end(), j); + if(i == vec.end()){ + tickint = 10; + } + else{ + tickint = *i; + } + + QSlider* slider = new QSlider(Qt::Vertical); + slider->setMaximum(Max); + slider->setMinimum(Min); + slider->setValue(output); + slider->setTickPosition(QSlider::TicksBelow); + slider->setTickInterval(tickint); + slider->setMinimumHeight(300); + + QLabel* labelmin = new QLabel(this); + QLabel* labelmax = new QLabel(this); + labelmin->setText(QString::number(Min)); + labelmin->setAlignment(Qt::AlignBottom); + labelmax->setText(QString::number(Max)); + labelmax->setAlignment(Qt::AlignTop); + m_pLayout->addWidget(slider, 2, 2*value, 4, 1); + m_pLayout->addWidget(labelmin, 5, 2*value+1, 1, 1); + m_pLayout->addWidget(labelmax, 2, 2*value+1, 1, 1); +} + +//============================================================================================================= + +void RealTimeNeurofeedbackWidget::clearLayout(QLayout *layout){ + if(layout == NULL) + return; + QLayoutItem *item; + + while((item = layout->takeAt(0))){ + if(item->layout()){ + clearLayout(item->layout()); + delete item->layout(); + } + if(item->widget()){ + delete item->widget(); + } + delete item; + } +} diff --git a/applications/mne_scan/libs/scDisp/realtimeneurofeedbackwidget.h b/applications/mne_scan/libs/scDisp/realtimeneurofeedbackwidget.h new file mode 100644 index 00000000000..12f62baa04c --- /dev/null +++ b/applications/mne_scan/libs/scDisp/realtimeneurofeedbackwidget.h @@ -0,0 +1,228 @@ +//============================================================================================================= +/** + * @file realtimeneurofeedbackwidget.h + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the RealTimeNeurofeedbackWidget Class. + * + */ + +#ifndef REALTIMENEUROFEEDBACKWIDGET_H +#define REALTIMENEUROFEEDBACKWIDGET_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "scdisp_global.h" +#include "measurementwidget.h" + + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace DISPLIB { + class ChannelSelectionView; + class ChannelInfoModel; + class RtFiffRawView; + class ChannelDataViewNew; +} + +namespace FIFFLIB { + class FiffInfo; +} + +namespace SCMEASLIB{ + class RealTimeNeurofeedbackResult; + class RealTimeSampleArrayChInfo; +} + + +//============================================================================================================= +// DEFINE NAMESPACE SCDISPLIB +//============================================================================================================= + +namespace SCDISPLIB +{ + +//============================================================================================================= +// SCDISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * DECLARE CLASS RealTimeMultiSampleArrayWidget + * + * @brief The RealTimeMultiSampleArrayWidget class provides a real-time curve display. + */ +class SCDISPSHARED_EXPORT RealTimeNeurofeedbackWidget : public MeasurementWidget +{ + Q_OBJECT + +public: + //========================================================================================================= + /** + * Constructs a RealTimeMultiSampleArrayWidget which is a child of parent. + * + * @param [in] pTime pointer to application time. + * @param [in] parent pointer to parent widget; If parent is 0, the new NumericWidget becomes a window. If parent is another widget, NumericWidget becomes a child window inside parent. NumericWidget is deleted when its parent is deleted. + */ + RealTimeNeurofeedbackWidget(QSharedPointer &pTime, + QWidget* parent = 0); + + //========================================================================================================= + /** + * Destroys the RealTimeNeurofeedbackWidget. + */ + ~RealTimeNeurofeedbackWidget(); + + //========================================================================================================= + /** + * Initialise the MeasurementWidget. + */ + virtual void init(){} + + //========================================================================================================= + /** + * Is called when new data are available. + * + * @param [in] pMeasurement pointer to measurement -> not used because its direct attached to the measurement. + */ + virtual void update(SCMEASLIB::Measurement::SPtr pMeasurement); + + //========================================================================================================= + /** + * Update the OpenGL viewport. This, e.g., necessary if this widget was set to a QDockWidget which changes + * its floating state. + */ + void updateOpenGLViewport(); + + +private: + //========================================================================================================= + /** + * Initialise the display control widgets to be shown in the QuickControlView. + */ + void initDisplayControllWidgets(); + + //========================================================================================================= + /** + * Shows sensor selection widget + */ + void showSensorSelectionWidget(); + + //========================================================================================================= + /** + * Call this slot whenever you want to make a screenshot current view. + * + * @param[in] imageType The current iamge type: png, svg. + */ + void onMakeScreenshot(const QString& imageType); + + //========================================================================================================= + /** + * Toggle bad channel visibility + */ + void onHideBadChannels(); + + //========================================================================================================= + /** + * Update Label - Textoutput (Classification Output). + */ + void updateLabel(QString text, QString Color); + + //========================================================================================================= + /** + * Update Slider (Frequency Output). + */ + void updateSlider(int slider, bool allCh, int numCh); + + //========================================================================================================= + /** + * Update Imageoutput (Classification Output). + */ + void updateImage(QPixmap image); + + //========================================================================================================= + /** + * Add Slider to Layout (Frequency Output). + */ + void addSlider(int value, int output, int Max, int Min); + + //========================================================================================================= + /** + * clear Layout. + */ + void clearLayout(QLayout *layout); + +private: + QSharedPointer m_pRTNR; /**< The real-time sample array measurement. */ + + QSharedPointer m_pQuickControlView; /**< quick control widget. */ + QSharedPointer m_pChannelInfoModel; /**< channel info model. */ + QSharedPointer m_pChannelSelectionView; /**< ChannelSelectionView. */ + QPointer m_pChannelDataView; /**< the QTableView being part of the model/view framework of Qt. */ + QSharedPointer m_pFiffInfo; /**< FiffInfo, which is used insteadd of ListChInfo*/ + + QPointer m_pActionHideBad; /**< Hide bad channels. */ + + qint32 m_iMaxFilterTapSize; /**< Maximum number of allowed filter taps. This number depends on the size of the receiving blocks. */ + + Eigen::MatrixXd m_matNeurofeedbackData; + QGridLayout * m_pLayout; + + Eigen::MatrixXd m_iClassification; + + QString m_sOutput; + + + + +}; +} // NAMESPACE SCDISPLIB + +#endif // REALTIMENEUROFEEDBACKWIDGET_H diff --git a/applications/mne_scan/libs/scDisp/scDisp.pro b/applications/mne_scan/libs/scDisp/scDisp.pro index e60fa11016a..fe7aa386b59 100644 --- a/applications/mne_scan/libs/scDisp/scDisp.pro +++ b/applications/mne_scan/libs/scDisp/scDisp.pro @@ -95,10 +95,12 @@ SOURCES += \ realtimemultisamplearraywidget.cpp \ realtimeevokedsetwidget.cpp \ realtimecovwidget.cpp \ + realtimeneurofeedbackwidget.cpp \ realtimespectrumwidget.cpp \ realtime3dwidget.cpp \ HEADERS += \ + realtimeneurofeedbackwidget.h \ scdisp_global.h \ measurementwidget.h \ realtimemultisamplearraywidget.h \ diff --git a/applications/mne_scan/libs/scMeas/measurementtypes.cpp b/applications/mne_scan/libs/scMeas/measurementtypes.cpp index 04a3da162c2..86b0280567e 100644 --- a/applications/mne_scan/libs/scMeas/measurementtypes.cpp +++ b/applications/mne_scan/libs/scMeas/measurementtypes.cpp @@ -48,6 +48,7 @@ #include "realtimesamplearraychinfo.h" #include "realtimecov.h" #include "realtimeevokedset.h" +#include "realtimeneurofeedbackresult.h" //============================================================================================================= // USED NAMESPACES @@ -77,4 +78,5 @@ void MeasurementTypes::registerTypes() qRegisterMetaType< RealTimeCov::SPtr >("RealTimeCov::SPtr"); qRegisterMetaType< RealTimeEvokedSet::SPtr >("RealTimeEvokedSet::SPtr"); qRegisterMetaType< RealTimeSampleArrayChInfo::SPtr >("RealTimeSampleArrayChInfo::SPtr"); + qRegisterMetaType< RealTimeNeurofeedbackResult::SPtr >("RealTimeNeurofeedbackResult::SPtr"); } diff --git a/applications/mne_scan/libs/scMeas/realtimeneurofeedbackresult.cpp b/applications/mne_scan/libs/scMeas/realtimeneurofeedbackresult.cpp new file mode 100644 index 00000000000..efc23de4f78 --- /dev/null +++ b/applications/mne_scan/libs/scMeas/realtimeneurofeedbackresult.cpp @@ -0,0 +1,153 @@ +//============================================================================================================= +/** + * @file realtimeneurofeedbackresult.cpp + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the RealTimeNeurofeedbackResult class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "realtimeneurofeedbackresult.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace SCMEASLIB; +using namespace FIFFLIB; +using namespace Eigen; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +RealTimeNeurofeedbackResult::RealTimeNeurofeedbackResult(QObject *parent) +: Measurement(QMetaType::type("RealTimeNeurofeedbackResult::SPtr"), parent) +, m_fSamplingRate(0) +, m_iMultiArraySize(10) +, m_bChInfoIsInit(false) +{ +} + +//============================================================================================================= + +RealTimeNeurofeedbackResult::~RealTimeNeurofeedbackResult() +{ +} + +//============================================================================================================= + +void RealTimeNeurofeedbackResult::init(QList &chInfo) +{ + qDebug()<<"RealTimeNeurofeedbackResult::init"; + QMutexLocker locker(&m_qMutex); + m_qListChInfo = chInfo; + + m_bChInfoIsInit = true; +} + +//============================================================================================================= + +void RealTimeNeurofeedbackResult::initFromFiffInfo(FiffInfo::SPtr pFiffInfo) +{ + qDebug()<<"RealTimeNeurofeedbackResult::initFromFiffInfo"; + QMutexLocker locker(&m_qMutex); + m_qListChInfo.clear(); + m_bChInfoIsInit = false; + + bool t_bIsBabyMEG = false; + + if(pFiffInfo->acq_pars == "BabyMEG") + t_bIsBabyMEG = true; + + for(qint32 i = 0; i < pFiffInfo->nchan; ++i) + { + RealTimeSampleArrayChInfo initChInfo; + initChInfo.setChannelName(pFiffInfo->chs[i].ch_name); + + // set channel Unit + initChInfo.setUnit(pFiffInfo->chs[i].unit); + + //Treat stimulus channels different + if(pFiffInfo->chs[i].kind == FIFFV_STIM_CH) + { +// initChInfo.setUnit(""); + initChInfo.setMinValue(0); + initChInfo.setMaxValue(1.0e6); + } +// else +// { + + // set channel Kind + initChInfo.setKind(pFiffInfo->chs[i].kind); + + // set channel coil + initChInfo.setCoil(pFiffInfo->chs[i].chpos.coil_type); + + m_qListChInfo.append(initChInfo); + } + + //Sampling rate + m_fSamplingRate = pFiffInfo->sfreq; + + m_pFiffInfo_orig = pFiffInfo; + + m_bChInfoIsInit = true; +} + +//============================================================================================================= + +void RealTimeNeurofeedbackResult::setValue(const MatrixXd& mat) +{ + if(!m_bChInfoIsInit) + return; + m_qMutex.lock(); + + m_Neurolist.push_back(mat); + + m_qMutex.unlock(); + if(m_Neurolist.size() >= m_iMultiArraySize){ + emit notify(); + m_qMutex.lock(); + m_Neurolist.clear(); + m_qMutex.unlock(); + } +} + diff --git a/applications/mne_scan/libs/scMeas/realtimeneurofeedbackresult.h b/applications/mne_scan/libs/scMeas/realtimeneurofeedbackresult.h new file mode 100644 index 00000000000..97c9fad65d7 --- /dev/null +++ b/applications/mne_scan/libs/scMeas/realtimeneurofeedbackresult.h @@ -0,0 +1,974 @@ +//============================================================================================================= +/** + * @file realtimeneurofeedbackresult.h + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the RealTimeNeurofeedbackResult class. + * + */ + +#ifndef REALTIMENEUROFEEDBACKRESULT_H +#define REALTIMENEUROFEEDBACKRESULT_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "scmeas_global.h" +#include "measurement.h" +#include "realtimesamplearraychinfo.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include +#include + +//============================================================================================================= +// DEFINE NAMESPACE SCMEASLIB +//============================================================================================================= + +namespace SCMEASLIB +{ + +//========================================================================================================= +/** + * DECLARE CLASS RealTimeNeurofeedbackResult + */ +class SCMEASSHARED_EXPORT RealTimeNeurofeedbackResult : public Measurement +{ + Q_OBJECT + +public: + typedef QSharedPointer SPtr; /**< Shared pointer type for RealTimeNeurofeedbackResult. */ + typedef QSharedPointer ConstSPtr; /**< Const shared pointer type for RealTimeNeurofeedbackResult. */ + + //========================================================================================================= + /** + * Constructs a RealTimeNeurofeedbackResult. + */ + explicit RealTimeNeurofeedbackResult(QObject *parent = 0); + + //========================================================================================================= + /** + * Destroys the RealTimeNeurofeedbackResult. + */ + virtual ~RealTimeNeurofeedbackResult(); + + //========================================================================================================= + /** + * Clears all the data stored in the buffer. + */ + void clear(); + + //========================================================================================================= + /** + * Inits RealTimeNeurofeedbackResult and adds uiNumChannels empty channel information + * + * @param [in] uiNumChannels the number of channels to init. + */ + void init(QList &chInfo); + + //========================================================================================================= + /** + * Init channel infos using fiff info + * + * @param[in] pFiffInfo Info to init from + */ + void initFromFiffInfo(FIFFLIB::FiffInfo::SPtr pFiffInfo); + + //========================================================================================================= + /** + * Returns whether channel info is initialized + * + * @return true whether the channel info is available. + */ + inline bool isChInit() const; + + //========================================================================================================= + /** + * Returns the file name of the xml layout file. + * + * @return the file name of the layout file. + */ + inline const QString& getXMLLayoutFile() const; + + //========================================================================================================= + /** + * Sets the file name of the xml layout. + * + * @param[in] layout which should be set. + */ + inline void setXMLLayoutFile(const QString& layout); + + //========================================================================================================= + /** + * Sets the sampling rate of the RealTimeNeurofeedbackResult Measurement. + * + * @param[in] fSamplingRate the sampling rate of the RealTimeNeurofeedbackResult. + */ + inline void setSamplingRate(float fSamplingRate); + + //========================================================================================================= + /** + * Returns the sampling rate of the RealTimeMultiSampleArray Measurement. + * + * @return the sampling rate of the RealTimeMultiSampleArray. + */ + inline float getSamplingRate() const; + + //========================================================================================================= + /** + * Returns the number of channels. + * + * @return the number of values which are gathered before a notify() is called. + */ + inline unsigned int getNumChannels() const; + + //========================================================================================================= + /** + * Returns the reference to the channel list. + * + * @return the reference to the channel list. + */ + inline QList& chInfo(); + + //========================================================================================================= + /** + * Returns the reference to the orig FiffInfo. + * + * @return the reference to the orig FiffInfo. + */ + inline FIFFLIB::FiffInfo::SPtr info(); + + //========================================================================================================= + /** + * Sets the number of sample vectors which should be gathered before attached observers are notified by calling the Subject notify() method. + * + * @param [in] iMultiArraySize the number of values. + */ + inline void setMultiArraySize(qint32 iMultiArraySize); + + //========================================================================================================= + /** + * Returns the number of values which should be gathered before attached observers are notified by calling the Subject notify() method. + * + * @return the number of values which are gathered before a notify() is called. + */ + inline qint32 getMultiArraySize() const; + + //========================================================================================================= + /** + * Returns the gathered Neurofeedback. + * + * @return the current Neurofeedback. + */ + inline const QList& getNeurofeedback(); + + //========================================================================================================= + /** + * Attaches a value to the Neurofeedback list. + * + * @param [in] mat the value which is attached to the Neurofeedback list. + */ + virtual void setValue(const Eigen::MatrixXd& mat); + + //========================================================================================================= + /** + * Sets the Neurofeedback Output. + * + * @param[in] routput Neurofeedback Output. + */ + inline void setNeuroOutput(QString routput); + + //========================================================================================================= + /** + * Sets the textoutput for the Classifications. + * + * @param[in] Class textoutput for Classification. + * @param[in] value Classification. + */ + inline void setClassL(QString Class, qint32 value); + + //========================================================================================================= + /** + * Sets the Integer for the Classifications. + * + * @param[in] Class Integer for Classification. + * @param[in] value Classification. + */ + inline void setClassI(qint32 Class, qint32 value); + + //========================================================================================================= + /** + * Sets the colour for the Textoutput (Classification Output). + * + * @param[in] ColClass Colour for Textoutput. + * @param[in] value Classification. + */ + inline void setClassCol(QString ColClass, qint32 value); + + //========================================================================================================= + /** + * Sets the Image for the Classifications. + * + * @param[in] ImgClass Pixmap for Imageoutput. + * @param[in] value Classification. + */ + inline void setClassImg(QPixmap ImgClass, qint32 value); + + //========================================================================================================= + /** + * Sets the Image for the Background (Balloon Output). + * + * @param[in] ImgBackground Pixmap for Background. + */ + inline void setImgBackground(QPixmap ImgBackground); + + //========================================================================================================= + /** + * Sets the Image for the Object (Balloon Output). + * + * @param[in] ImgObject Pixmap for Object. + */ + inline void setImgObject(QPixmap ImgObject); + + //========================================================================================================= + /** + * Sets the number of sliders (Frequency Output). + * + * @param[in] value number of sliders. + */ + inline void setSlider(qint32 value); + + //========================================================================================================= + /** + * Sets the number of Classifications (Classification Output). + * + * @param[in] value number of classifications. + */ + inline void setNumbofClass(qint32 value); + + //========================================================================================================= + /** + * Sets the bool for all Channels (Frequency Output). + * + * @param[in] ballCh bool for all Channels selected. + */ + inline void setallCh(bool ballCh); + + //========================================================================================================= + /** + * Sets the bool for AutoScale for the minimum (Frequency Output). + * + * @param[in] bMinAutoScale bool for Autoscale for the minimum. + */ + inline void setMinAutoScale(bool bMinAutoScale); + + //========================================================================================================= + /** + * Sets the bool for Autoscale for the maximum (Frequency Output). + * + * @param[in] bMaxAutoScale bool for Autoscale for the maximum. + */ + inline void setMaxAutoScale(bool bMaxAutoScale); + + //========================================================================================================= + /** + * Sets the bool for Reset Autoscale (Frequency Output). + * + * @param[in] bResetAutoscale bool for Reset Autoscale. + */ + inline void setResetAutoScale(bool bResetAutoScale); + + //========================================================================================================= + /** + * Sets the slidermaximum (Frequency Output). + * + * @param[in] value slidermaximum. + */ + inline void setFMax(qint32 value); + + //========================================================================================================= + /** + * Sets the sliderminimum (Frequency Output). + * + * @param[in] value sliderminimum. + */ + inline void setFMin(qint32 value); + + //========================================================================================================= + /** + * Sets the maximum height of the balloon (Balloon Output). + * + * @param[in] value height maximum of the balloon. + */ + inline void setBMax(qint32 value); + + //========================================================================================================= + /** + * Sets the minimum height of the balloon (Balloon Output). + * + * @param[in] value height minimum of the balloon. + */ + inline void setBMin(qint32 value); + + //========================================================================================================= + /** + * Sets the channel (Balloon Output). + * + * @param[in] value channelnumber. + */ + inline void setChannel(qint32 value); + + //========================================================================================================= + /** + * Sets the Bool for new AutoScale Start. + * + * @param[in] bScaleStart new AutoScale Start. + */ + inline void setScaleStart(bool bScaleStart); + + //========================================================================================================= + /** + * Returns the Neurofeedback Output. + * + * @return the current Neurofeedback. + */ + inline QString getNeuroOutput(); + + //========================================================================================================= + /** + * Returns the label/textoutput (Classification Output). + * + * @param[in] value Classification. + * @return textoutput for Classification. + */ + inline QString getClassL(qint32 value); + + //========================================================================================================= + /** + * Returns the integer (Classification Output). + * + * @param[in] value Classification. + * @return integers for Classification. + */ + inline qint32 getClassI(qint32 value); + + //========================================================================================================= + /** + * Returns the colour for textoutput (Classification Output). + * + * @param[in] value Classification. + * @return colour for textoutput. + */ + inline QString getClassCol(qint32 value); + + //========================================================================================================= + /** + * Returns the image (Classification Output). + * + * @param[in] value Classification. + * @return pixmap for Classification. + */ + inline QPixmap getClassImg(qint32 value); + + //========================================================================================================= + /** + * Returns the background (Balloon Output). + * + * @return pixmap for background. + */ + inline QPixmap getImgBackground(); + + //========================================================================================================= + /** + * Returns the object (Balloon Output). + * + * @return pixmap for object. + */ + inline QPixmap getImgObject(); + + //========================================================================================================= + /** + * Returns the number of sliders (Frequency Output). + * + * @return number of sliders. + */ + inline qint32 getSlider(); + + //========================================================================================================= + /** + * Returns the number of Classifications (Classification Output). + * + * @return number of Classifications. + */ + inline qint32 getNumbofClass(); + + //========================================================================================================= + /** + * Returns the slidermaximum (Frequency Output). + * + * @return slidermaximum. + */ + inline qint32 getFMax(); + + //========================================================================================================= + /** + * Returns the sliderminimum (Frequency Output). + * + * @return sliderminimum. + */ + inline qint32 getFMin(); + + //========================================================================================================= + /** + * Returns the maximum height of the balloon (Balloon Output). + * + * @return maximum height of the balloon. + */ + inline qint32 getBMax(); + + //========================================================================================================= + /** + * Returns the minimum height of the balloon (Balloon Output). + * + * @return minimum height of the balloon. + */ + inline qint32 getBMin(); + + //========================================================================================================= + /** + * Returns the current channel (Balloon Output). + * + * @return current channel selected. + */ + inline qint32 getChannel(); + + //========================================================================================================= + /** + * Returns the bool for all Channels selected (Frequency Output). + * + * @return bool for all channels selected. + */ + inline bool getallCh(); + + //========================================================================================================= + /** + * Returns the bool for Minimum Autoscale (Frequency Output). + * + * @return bool for minimum Autoscale. + */ + inline bool getMinAutoScale(); + + //========================================================================================================= + /** + * Returns the bool for Maximum Autoscale (Frequency Output). + * + * @return bool for maximum Autoscale. + */ + inline bool getMaxAutoScale(); + + //========================================================================================================= + /** + * Returns the bool for Reset Autoscale (Frequency Output). + * + * @return bool for reset Autoscale. + */ + inline bool getResetAutoscale(); + +private: + mutable QMutex m_qMutex; /**< Mutex to ensure thread safety */ + + FIFFLIB::FiffInfo::SPtr m_pFiffInfo_orig; /**< Original Fiff Info if initialized by fiff info. */ + + QString m_sXMLLayoutFile; /**< Layout file name. */ + float m_fSamplingRate; /**< Sampling rate of the RealTimeSampleArray.*/ + qint32 m_iMultiArraySize; /**< Sample size of the multi sample array.*/ + QList m_Neurolist; /**< The multi sample array.*/ + + bool m_bChInfoIsInit; /**< If channel info is initialized.*/ + + qint32 m_iActionres; + QString m_sNeuroOutput; + qint32 m_iSlider; + qint32 m_iNumbofClass; + qint32 m_iFMax; + qint32 m_iFMin; + qint32 m_iBMax; + qint32 m_iBMin; + qint32 m_iChannel; + + QString m_sClass0; + QString m_sClass1; + QString m_sClass2; + QString m_sClass3; + QString m_sClass4; + QString m_sDist; + + bool m_ballCh; + bool m_bMinAutoScale; + bool m_bMaxAutoScale; + bool m_bResetAutoScale; + + QVector m_vClassL; + QVector m_vClassI; + QVector m_vClassCol; + QVector m_vClassImg; + + QPixmap m_ImgBackground; + QPixmap m_ImgObject; + + QList m_qListChInfo; /**< Channel info list.*/ + +}; + +//============================================================================================================= +// INLINE DEFINITIONS +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::clear() +{ + QMutexLocker locker(&m_qMutex); + m_Neurolist.clear(); +} + +//============================================================================================================= + +inline bool RealTimeNeurofeedbackResult::isChInit() const +{ + QMutexLocker locker(&m_qMutex); + return m_bChInfoIsInit; +} + +//============================================================================================================= + +inline const QString& RealTimeNeurofeedbackResult::getXMLLayoutFile() const +{ + QMutexLocker locker(&m_qMutex); + return m_sXMLLayoutFile; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setXMLLayoutFile(const QString& layout) +{ + QMutexLocker locker(&m_qMutex); + m_sXMLLayoutFile = layout; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setSamplingRate(float fSamplingRate) +{ + QMutexLocker locker(&m_qMutex); + m_fSamplingRate = fSamplingRate; +} + +//============================================================================================================= + +inline float RealTimeNeurofeedbackResult::getSamplingRate() const +{ + QMutexLocker locker(&m_qMutex); + return m_fSamplingRate; +} + +//============================================================================================================= + +inline unsigned int RealTimeNeurofeedbackResult::getNumChannels() const +{ + QMutexLocker locker(&m_qMutex); + return m_qListChInfo.size(); +} + +//============================================================================================================= + +inline QList& RealTimeNeurofeedbackResult::chInfo() +{ + QMutexLocker locker(&m_qMutex); + return m_qListChInfo; +} + +//============================================================================================================= + +inline FIFFLIB::FiffInfo::SPtr RealTimeNeurofeedbackResult::info() +{ + QMutexLocker locker(&m_qMutex); + return m_pFiffInfo_orig; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setMultiArraySize(qint32 iMultiArraySize) +{ + m_iMultiArraySize = iMultiArraySize; +} + +//============================================================================================================= + +qint32 RealTimeNeurofeedbackResult::getMultiArraySize() const +{ + QMutexLocker locker(&m_qMutex); + return m_iMultiArraySize; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setNeuroOutput(QString routput) +{ + QMutexLocker locker(&m_qMutex); + m_sNeuroOutput = routput; +} + +//============================================================================================================= + +inline QString RealTimeNeurofeedbackResult::getNeuroOutput() +{ + QMutexLocker locker(&m_qMutex); + return m_sNeuroOutput; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setNumbofClass(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_iNumbofClass = value; +} + +//============================================================================================================= + +inline int RealTimeNeurofeedbackResult::getNumbofClass() +{ + QMutexLocker locker(&m_qMutex); + return m_iNumbofClass; +} + +//============================================================================================================ + +inline void RealTimeNeurofeedbackResult::setallCh(bool ballCh) +{ + QMutexLocker locker(&m_qMutex); + m_ballCh = ballCh; + +} + +//============================================================================================================ + +inline bool RealTimeNeurofeedbackResult::getallCh() +{ + QMutexLocker locker(&m_qMutex); + return m_ballCh; +} + +//============================================================================================================ + +inline void RealTimeNeurofeedbackResult::setMaxAutoScale(bool bMaxAutoScale) +{ + QMutexLocker locker(&m_qMutex); + m_bMaxAutoScale = bMaxAutoScale; + +} + +//============================================================================================================ + +inline bool RealTimeNeurofeedbackResult::getMaxAutoScale() +{ + QMutexLocker locker(&m_qMutex); + return m_bMaxAutoScale; +} + +//============================================================================================================ + +inline void RealTimeNeurofeedbackResult::setMinAutoScale(bool bMinAutoScale) +{ + QMutexLocker locker(&m_qMutex); + m_bMinAutoScale = bMinAutoScale; + +} + +//============================================================================================================ + +inline bool RealTimeNeurofeedbackResult::getMinAutoScale() +{ + QMutexLocker locker(&m_qMutex); + return m_bMinAutoScale; +} + +//============================================================================================================ + +inline void RealTimeNeurofeedbackResult::setResetAutoScale(bool bResetAutoScale) +{ + QMutexLocker locker(&m_qMutex); + m_bResetAutoScale = bResetAutoScale; + +} + +//============================================================================================================ + +inline bool RealTimeNeurofeedbackResult::getResetAutoscale() +{ + QMutexLocker locker(&m_qMutex); + return m_bResetAutoScale; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setClassL(QString Class, qint32 value) +{ + QMutexLocker locker(&m_qMutex); + if(m_vClassL.isEmpty()){ + m_vClassL.resize(5); + m_vClassL.fill("Empty"); + } + if(m_vClassCol.isEmpty()){ + m_vClassCol.resize(5); + m_vClassCol.fill("black"); + } + if(m_vClassImg.isEmpty()){ + m_vClassImg.resize(5); + } + m_vClassL[value] = Class; +} + +//============================================================================================================= + +inline QString RealTimeNeurofeedbackResult::getClassL(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + return m_vClassL[value]; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setClassI(qint32 Class, qint32 value) +{ + QMutexLocker locker(&m_qMutex); + if(m_vClassI.isEmpty()){ + m_vClassI.resize(5); + m_vClassI.fill(0); + } + m_vClassI[value] = Class; +} + +//============================================================================================================= + +inline int RealTimeNeurofeedbackResult::getClassI(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + return m_vClassI[value]; +} + + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setClassCol(QString ColClass, qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_vClassCol[value] = ColClass; +} + +//============================================================================================================= + +inline QString RealTimeNeurofeedbackResult::getClassCol(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + return m_vClassCol[value]; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setClassImg(QPixmap ImgClass, qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_vClassImg[value] = ImgClass; +} + +//============================================================================================================= + +inline QPixmap RealTimeNeurofeedbackResult::getClassImg(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + return m_vClassImg[value]; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setImgBackground(QPixmap ImgBackground) +{ + QMutexLocker locker(&m_qMutex); + m_ImgBackground = ImgBackground; +} + +//============================================================================================================= + +inline QPixmap RealTimeNeurofeedbackResult::getImgBackground() +{ + QMutexLocker locker(&m_qMutex); + return m_ImgBackground; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setImgObject(QPixmap ImgObject) +{ + QMutexLocker locker(&m_qMutex); + m_ImgObject = ImgObject; +} + +//============================================================================================================= + +inline QPixmap RealTimeNeurofeedbackResult::getImgObject() +{ + QMutexLocker locker(&m_qMutex); + return m_ImgObject; +} + +//============================================================================================================= + + +inline void RealTimeNeurofeedbackResult::setSlider(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_iSlider = value; +} + +//============================================================================================================= + +inline int RealTimeNeurofeedbackResult::getSlider() +{ + QMutexLocker locker(&m_qMutex); + return m_iSlider; +} + +//============================================================================================================= + + +inline void RealTimeNeurofeedbackResult::setFMax(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_iFMax = value; +} + +//============================================================================================================= + +inline int RealTimeNeurofeedbackResult::getFMax() +{ + QMutexLocker locker(&m_qMutex); + return m_iFMax; +} + +//============================================================================================================= + + +inline void RealTimeNeurofeedbackResult::setFMin(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_iFMin = value; +} + +//============================================================================================================= + +inline int RealTimeNeurofeedbackResult::getFMin() +{ + QMutexLocker locker(&m_qMutex); + return m_iFMin; +} + +//============================================================================================================= + + +inline void RealTimeNeurofeedbackResult::setBMax(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_iBMax = value; +} + +//============================================================================================================= + +inline int RealTimeNeurofeedbackResult::getBMax() +{ + QMutexLocker locker(&m_qMutex); + return m_iBMax; +} + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setBMin(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_iBMin = value; +} + +//============================================================================================================= + +inline int RealTimeNeurofeedbackResult::getBMin() +{ + QMutexLocker locker(&m_qMutex); + return m_iBMin; +} + + +//============================================================================================================= + +inline void RealTimeNeurofeedbackResult::setChannel(qint32 value) +{ + QMutexLocker locker(&m_qMutex); + m_iChannel = value; +} + +//============================================================================================================= + +inline qint32 RealTimeNeurofeedbackResult::getChannel() +{ + QMutexLocker locker(&m_qMutex); + return m_iChannel; +} + +//============================================================================================================= + +inline const QList& RealTimeNeurofeedbackResult::getNeurofeedback() +{ + QMutexLocker locker(&m_qMutex); + return m_Neurolist; +} + + + +} // NAMESPACE + +Q_DECLARE_METATYPE(SCMEASLIB::RealTimeNeurofeedbackResult::SPtr) + +#endif // REALTIMENEUROFEEDBACKRESULT_H diff --git a/applications/mne_scan/libs/scMeas/scMeas.pro b/applications/mne_scan/libs/scMeas/scMeas.pro index 5ac0c4717ae..588a3cf2621 100644 --- a/applications/mne_scan/libs/scMeas/scMeas.pro +++ b/applications/mne_scan/libs/scMeas/scMeas.pro @@ -71,6 +71,7 @@ CONFIG(debug, debug|release) { } SOURCES += \ + realtimeneurofeedbackresult.cpp \ realtimesourceestimate.cpp \ realtimeconnectivityestimate.cpp \ realtimemultisamplearray.cpp \ @@ -85,6 +86,7 @@ SOURCES += \ realtimefwdsolution.cpp HEADERS += \ + realtimeneurofeedbackresult.h \ scmeas_global.h \ realtimesourceestimate.h \ realtimeconnectivityestimate.h \ diff --git a/applications/mne_scan/libs/scShared/Management/displaymanager.cpp b/applications/mne_scan/libs/scShared/Management/displaymanager.cpp index fe5d49c6975..edfe527c98d 100644 --- a/applications/mne_scan/libs/scShared/Management/displaymanager.cpp +++ b/applications/mne_scan/libs/scShared/Management/displaymanager.cpp @@ -44,7 +44,7 @@ #include #include #include - +#include #include #include #include @@ -52,6 +52,7 @@ #include #include #include +#include //============================================================================================================= // QT INCLUDES @@ -182,6 +183,17 @@ QWidget* DisplayManager::show(AbstractPlugin::OutputConnectorList &outputConnect vboxLayout->addWidget(fsWidget); fsWidget->init(); + } else if (pPluginOutputConnector.dynamicCast< PluginOutputData >()) { + + RealTimeNeurofeedbackWidget* nfWidget = new RealTimeNeurofeedbackWidget(pT, newDisp); + + qListActions.append(nfWidget->getDisplayActions()); + + connect(pPluginOutputConnector.data(), &PluginOutputConnector::notify, + nfWidget, &RealTimeNeurofeedbackWidget::update, Qt::BlockingQueuedConnection); + + vboxLayout->addWidget(nfWidget); + nfWidget->init(); } } diff --git a/applications/mne_scan/libs/scShared/Management/pluginconnectorconnection.cpp b/applications/mne_scan/libs/scShared/Management/pluginconnectorconnection.cpp index 089485ce627..d25a47d3219 100644 --- a/applications/mne_scan/libs/scShared/Management/pluginconnectorconnection.cpp +++ b/applications/mne_scan/libs/scShared/Management/pluginconnectorconnection.cpp @@ -47,6 +47,7 @@ #include #include #include +#include //============================================================================================================= // USED NAMESPACES @@ -117,6 +118,20 @@ bool PluginConnectorConnection::createConnection() break; } + //Cast to RealTimeNeurofeedbackResult + QSharedPointer< PluginOutputData > senderRTNR = m_pSender->getOutputConnectors()[i].dynamicCast< PluginOutputData >(); + QSharedPointer< PluginInputData > receiverRTNR = m_pReceiver->getInputConnectors()[j].dynamicCast< PluginInputData >(); + if(senderRTNR && receiverRTNR) + { + // We need to use BlockingQueuedConnection here because the FiffSimulator is still dispatching its data from a different thread via the direct connect signal method + m_qHashConnections.insert(QPair(m_pSender->getOutputConnectors()[i]->getName(), + m_pReceiver->getInputConnectors()[j]->getName()), + connect(m_pSender->getOutputConnectors()[i].data(), &PluginOutputConnector::notify, + m_pReceiver->getInputConnectors()[j].data(), &PluginInputConnector::update, Qt::BlockingQueuedConnection)); + bConnected = true; + break; + } + //Cast to RealTimeEvokedSet QSharedPointer< PluginOutputData > senderRTESet = m_pSender->getOutputConnectors()[i].dynamicCast< PluginOutputData >(); QSharedPointer< PluginInputData > receiverRTESet = m_pReceiver->getInputConnectors()[j].dynamicCast< PluginInputData >(); @@ -212,6 +227,11 @@ ConnectorDataType PluginConnectorConnection::getDataType(QSharedPointer > RTNR_Out = pPluginConnector.dynamicCast< PluginOutputData >(); + QSharedPointer< PluginInputData > RTNR_In = pPluginConnector.dynamicCast< PluginInputData >(); + if(RTNR_Out || RTNR_In) + return ConnectorDataType::_RTNR; + QSharedPointer< PluginOutputData > RTC_Out = pPluginConnector.dynamicCast< PluginOutputData >(); QSharedPointer< PluginInputData > RTC_In = pPluginConnector.dynamicCast< PluginInputData >(); if(RTC_Out || RTC_In) diff --git a/applications/mne_scan/libs/scShared/Management/pluginconnectorconnection.h b/applications/mne_scan/libs/scShared/Management/pluginconnectorconnection.h index d56eeab29c8..b6ff0fcba4b 100644 --- a/applications/mne_scan/libs/scShared/Management/pluginconnectorconnection.h +++ b/applications/mne_scan/libs/scShared/Management/pluginconnectorconnection.h @@ -66,14 +66,15 @@ namespace SCSHAREDLIB */ enum ConnectorDataType { - _N, /**< Numeric. */ - _RTMSA, /**< Real-Time Multi Sample Array. */ - _RTES, /**< Real-Time Evoked Set. */ - _RTC, /**< Real-Time Covariance. */ - _RTSE, /**< Real-Time Source Estimate. */ - _RTHR, /**< Real-Time Hpi Result. */ - _RTFS, /**< Real-Time Forward Solution. */ - _None, /**< None. */ + _N, /**< Numeric */ + _RTMSA, /**< Real-Time Multi Sample Array */ + _RTES, /**< Real-Time Evoked Set */ + _RTC, /**< Real-Time Covariance */ + _RTSE, /**< Real-Time Source Estimate */ + _RTHR, /**< Real-Time Hpi Result */ + _RTFS, /**< Real-Time Forward Solution */ + _RTNR, /**< Real-Time Neurofeedback Result */ + _None, /**< None */ }; //============================================================================================================= diff --git a/applications/mne_scan/mne_scan/main.cpp b/applications/mne_scan/mne_scan/main.cpp index 89461d06455..9a9b8338093 100644 --- a/applications/mne_scan/mne_scan/main.cpp +++ b/applications/mne_scan/mne_scan/main.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -92,6 +93,7 @@ Q_IMPORT_PLUGIN(NeuronalConnectivity) Q_IMPORT_PLUGIN(FtBuffer) Q_IMPORT_PLUGIN(WriteToFile) Q_IMPORT_PLUGIN(Hpi) +Q_IMPORT_PLUGIN(Neurofeedback) //Q_IMPORT_PLUGIN(DummyToolbox) #ifdef WITHGUSBAMP Q_IMPORT_PLUGIN(GUSBAmp) @@ -136,6 +138,7 @@ int main(int argc, char *argv[]) Q_INIT_RESOURCE(hpi); Q_INIT_RESOURCE(disp3d); Q_INIT_RESOURCE(scDisp); + Q_INIT_RESOURCE(neurofeedback); #ifdef WITHBRAINAMP Q_INIT_RESOURCE(brainamp); #endif diff --git a/applications/mne_scan/mne_scan/mainwindow.cpp b/applications/mne_scan/mne_scan/mainwindow.cpp index 1300ba0cfd1..89f40076d1f 100644 --- a/applications/mne_scan/mne_scan/mainwindow.cpp +++ b/applications/mne_scan/mne_scan/mainwindow.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -844,6 +845,8 @@ void MainWindow::onDockLocationChanged(QWidget* pWidget) pView->updateOpenGLViewport(); } else if(RealTimeEvokedSetWidget* pView = qobject_cast(widget)) { pView->updateOpenGLViewport(); + } else if(RealTimeNeurofeedbackWidget* pView = qobject_cast(widget)) { + pView->updateOpenGLViewport(); } } } @@ -851,6 +854,8 @@ void MainWindow::onDockLocationChanged(QWidget* pWidget) pView->updateOpenGLViewport(); } else if(RealTimeEvokedSetWidget* pView = qobject_cast(pWidget)) { pView->updateOpenGLViewport(); + } else if(RealTimeNeurofeedbackWidget* pView = qobject_cast(pWidget)) { + pView->updateOpenGLViewport(); } } diff --git a/applications/mne_scan/mne_scan/mne_scan.pro b/applications/mne_scan/mne_scan/mne_scan.pro index 3ebc58c0b63..ee779001f25 100755 --- a/applications/mne_scan/mne_scan/mne_scan.pro +++ b/applications/mne_scan/mne_scan/mne_scan.pro @@ -77,7 +77,8 @@ contains(MNECPP_CONFIG, static) { -lftbuffer \ -lwritetofile \ -lhpi \ - -lrtfwd + -lrtfwd \ + -lneurofeedback \ #-ldummytoolbox contains(MNECPP_CONFIG, withGUSBAmp) { diff --git a/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetup.ui b/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetup.ui new file mode 100644 index 00000000000..f5f7e93c2ec --- /dev/null +++ b/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetup.ui @@ -0,0 +1,160 @@ + + + NeurofeedbackSetupWidgetClass + + + + 0 + 0 + 713 + 645 + + + + TMSi EEG Connector Setup + + + + + + + 75 + true + + + + Neurofeedback Plugin + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + 6 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 50000 + + + + Options + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Information + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600;">Description:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt;">This plugin connects to the EEGoSports device. It parses the incoming stream and provides it to subsequent connected plugins. For inspection the data stream is visualized in real-time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8.25pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600;">How to setup this plugin?</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt;">1. Make sure the EEGoSports SDK is installed on the computer connected to the device.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt;">2. Set the wanted control options.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8.25pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600;">How to control this plugin during the measurement?</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt;">All control elements can be found in the QuickControlView's EEGoSports tab.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8.25pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600;">Input data type:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Test</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8.25pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600;">Output data type:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt;">This plugin streams raw data blocks to subsequent connected plugins.</span></p></body></html> + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + + + + + diff --git a/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetupwidget.cpp b/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetupwidget.cpp new file mode 100644 index 00000000000..8a38eacdad7 --- /dev/null +++ b/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetupwidget.cpp @@ -0,0 +1,208 @@ +//============================================================================================================= +/** + * @file neurofeedbacksetupwidget.cpp + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the NeurofeedbackSetupWidget class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "neurofeedbacksetupwidget.h" +#include "../neurofeedback.h" + +#include "disp/viewers/neurofeedbackcsettingsview.h" +#include "disp/viewers/neurofeedbackfsettingsview.h" +#include "disp/viewers/neurofeedbackbsettingsview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace NEUROFEEDBACKPLUGIN; +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +NeurofeedbackSetupWidget::NeurofeedbackSetupWidget(Neurofeedback* pNeurofeedback, const QString& sSettingsPath, QWidget *parent) +: QWidget(parent) +, m_pNeurofeedback(pNeurofeedback) +, m_sSettingsPath(sSettingsPath) +{ + + ui.setupUi(this); + + loadSettings(m_sSettingsPath); + + NeurofeedbackCSettingsView* pNeurofeedbackCSettingsView = new NeurofeedbackCSettingsView(QString("MNESCAN/%1/").arg(m_pNeurofeedback->getName())); + NeurofeedbackFSettingsView* pNeurofeedbackFSettingsView = new NeurofeedbackFSettingsView(QString("MNESCAN/%1/").arg(m_pNeurofeedback->getName())); + NeurofeedbackBSettingsView* pNeurofeedbackBSettingsView = new NeurofeedbackBSettingsView(QString("MNESCAN/%1/").arg(m_pNeurofeedback->getName())); + + QGridLayout* settingsLayoutN = new QGridLayout; + + QLabel* NeuroOutputLabel = new QLabel("Output"); + QRadioButton* ClassifierButton = new QRadioButton("Classifier"); + QRadioButton* FrequencyButton = new QRadioButton("Frequency"); + QRadioButton* BalloonButton = new QRadioButton("Balloon"); + + settingsLayoutN->addWidget(NeuroOutputLabel); + settingsLayoutN->addWidget(ClassifierButton,0,1); + settingsLayoutN->addWidget(FrequencyButton,0,2); + settingsLayoutN->addWidget(BalloonButton,0,3); + + QTabWidget* settingsTab = new QTabWidget; + + settingsTab->addTab(pNeurofeedbackCSettingsView, "Classifier Settings"); + settingsTab->addTab(pNeurofeedbackFSettingsView, "Frequency Settings"); + settingsTab->addTab(pNeurofeedbackBSettingsView, "Balloon Setting"); + + + settingsLayoutN->addWidget(settingsTab,1,0,1,10); + + QButtonGroup* buttonGroupOutput = new QButtonGroup(); + buttonGroupOutput->addButton(ClassifierButton); + buttonGroupOutput->addButton(FrequencyButton); + buttonGroupOutput->addButton(BalloonButton); + + buttonGroupOutput->setId(ClassifierButton, 0); + buttonGroupOutput->setId(FrequencyButton, 1); + buttonGroupOutput->setId(BalloonButton, 2); + + if(m_iOutput == 0){ + ClassifierButton->setChecked(true); + } + else if(m_iOutput == 1){ + FrequencyButton->setChecked(true); + } + else if(m_iOutput == 2){ + BalloonButton->setChecked(true); + } + + + ui.m_qGroupBox_NeurofeedbackOptions->setLayout(settingsLayoutN); + + + connect(buttonGroupOutput, static_cast(&QButtonGroup::buttonClicked), m_pNeurofeedback, &Neurofeedback::changeOutput); + connect(buttonGroupOutput, static_cast(&QButtonGroup::buttonClicked), this, &NeurofeedbackSetupWidget::changeiOutput); + connect(pNeurofeedbackFSettingsView, &NeurofeedbackFSettingsView::changeSliders, m_pNeurofeedback, &Neurofeedback::changeSliders); + connect(pNeurofeedbackFSettingsView, &NeurofeedbackFSettingsView::changeballCh, m_pNeurofeedback, &Neurofeedback::changeballCh); + connect(pNeurofeedbackFSettingsView, &NeurofeedbackFSettingsView::changeMax, m_pNeurofeedback, &Neurofeedback::changeFMax); + connect(pNeurofeedbackFSettingsView, &NeurofeedbackFSettingsView::changeMin, m_pNeurofeedback, &Neurofeedback::changeFMin); + connect(pNeurofeedbackFSettingsView, &NeurofeedbackFSettingsView::changeMaxAutoScale, m_pNeurofeedback, &Neurofeedback::changeMaxAutoScale); + connect(pNeurofeedbackFSettingsView, &NeurofeedbackFSettingsView::changeMinAutoScale, m_pNeurofeedback, &Neurofeedback::changeMinAutoScale); + connect(pNeurofeedbackFSettingsView, &NeurofeedbackFSettingsView::changeResetAutoScale, m_pNeurofeedback, &Neurofeedback::changeResetAutoScale); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeNumbofClass, m_pNeurofeedback, &Neurofeedback::changeNumbofClass); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeClass0, m_pNeurofeedback, &Neurofeedback::changeClass0); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeClass1, m_pNeurofeedback, &Neurofeedback::changeClass1); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeClass2, m_pNeurofeedback, &Neurofeedback::changeClass2); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeClass3, m_pNeurofeedback, &Neurofeedback::changeClass3); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeClass4, m_pNeurofeedback, &Neurofeedback::changeClass4); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeButtonGroupC0, m_pNeurofeedback, &Neurofeedback::changeGBC0); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeButtonGroupC1, m_pNeurofeedback, &Neurofeedback::changeGBC1); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeButtonGroupC2, m_pNeurofeedback, &Neurofeedback::changeGBC2); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeButtonGroupC3, m_pNeurofeedback, &Neurofeedback::changeGBC3); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeButtonGroupC4, m_pNeurofeedback, &Neurofeedback::changeGBC4); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeiClass0, m_pNeurofeedback, &Neurofeedback::changeiClass0); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeiClass1, m_pNeurofeedback, &Neurofeedback::changeiClass1); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeiClass2, m_pNeurofeedback, &Neurofeedback::changeiClass2); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeiClass3, m_pNeurofeedback, &Neurofeedback::changeiClass3); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeiClass4, m_pNeurofeedback, &Neurofeedback::changeiClass4); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeImgClass0, m_pNeurofeedback, &Neurofeedback::changeImgClass0); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeImgClass1, m_pNeurofeedback, &Neurofeedback::changeImgClass1); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeImgClass2, m_pNeurofeedback, &Neurofeedback::changeImgClass2); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeImgClass3, m_pNeurofeedback, &Neurofeedback::changeImgClass3); + connect(pNeurofeedbackCSettingsView, &NeurofeedbackCSettingsView::changeImgClass4, m_pNeurofeedback, &Neurofeedback::changeImgClass4); + connect(pNeurofeedbackBSettingsView, &NeurofeedbackBSettingsView::changeMax, m_pNeurofeedback, &Neurofeedback::changeBMax); + connect(pNeurofeedbackBSettingsView, &NeurofeedbackBSettingsView::changeMin, m_pNeurofeedback, &Neurofeedback::changeBMin); + connect(pNeurofeedbackBSettingsView, &NeurofeedbackBSettingsView::changeImgBackground, m_pNeurofeedback, &Neurofeedback::changeImgBackground); + connect(pNeurofeedbackBSettingsView, &NeurofeedbackBSettingsView::changeImgObject, m_pNeurofeedback, &Neurofeedback::changeImgObject); + + + pNeurofeedbackCSettingsView->emitSignals(); + pNeurofeedbackBSettingsView->emitSignals(); + pNeurofeedbackFSettingsView->emitSignals(); + + ClassifierButton->click(); +} + +//============================================================================================================= + +NeurofeedbackSetupWidget::~NeurofeedbackSetupWidget() +{ + +} + +//============================================================================================================= + +void NeurofeedbackSetupWidget::saveSettings(const QString& settingsPath) +{ + if(settingsPath.isEmpty()) { + return; + } + + // Store Settings + QSettings settings; + + settings.setValue(settingsPath + QString("/iOutput"), m_iOutput); + +} + +//============================================================================================================= + +void NeurofeedbackSetupWidget::loadSettings(const QString& settingsPath) +{ + if(settingsPath.isEmpty()) { + return; + } + + // Load Settings + QSettings settings; + + m_iOutput = settings.value(settingsPath + QString("/iOutput"), m_iOutput).toInt(); +} + +//============================================================================================================= + +void NeurofeedbackSetupWidget::changeiOutput(int value) +{ + m_iOutput = value; + saveSettings(m_sSettingsPath); +} diff --git a/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetupwidget.h b/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetupwidget.h new file mode 100644 index 00000000000..cda81cd3814 --- /dev/null +++ b/applications/mne_scan/plugins/neurofeedback/FormFiles/neurofeedbacksetupwidget.h @@ -0,0 +1,123 @@ +//============================================================================================================= +/** + * @file neurofeedbacksetupwidget.h + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the NeurofeedbackSetupWidget class. + * + */ + +#ifndef NEUROFEEDBACKSETUPWIDGET_H +#define NEUROFEEDBACKSETUPWIDGET_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "ui_neurofeedbacksetup.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// DEFINE NAMESPACE NEUROFEEDBACKPLUGIN +//============================================================================================================= + +namespace NEUROFEEDBACKPLUGIN +{ + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class Neurofeedback; + + +//============================================================================================================= +/** + * DECLARE CLASS NeurofeedbackSetupWidget + * + * @brief The NeurofeedbackSetupWidget class provides the Neurofeedback configuration window. + */ +class NeurofeedbackSetupWidget : public QWidget +{ + Q_OBJECT + +public: + + //========================================================================================================= + /** + * Constructs a NeurofeedbackSetupWidget which is a child of parent. + * + * @param [in] toolbox a pointer to the corresponding Neurofeedback. + * @param [in] parent pointer to parent widget; If parent is 0, the new NeurofeedbackSetupWidget becomes a window. If parent is another widget, NeurofeedbackSetupWidget becomes a child window inside parent. DummySetupWidget is deleted when its parent is deleted. + */ + explicit NeurofeedbackSetupWidget(Neurofeedback* pNeurofeedback, const QString& sSettingsPath = "", QWidget *parent = nullptr); + + //========================================================================================================= + /** + * Destroys the NeurofeedbackSetupWidget. + * All NeurofeedbackSetupWidget's children are deleted first. The application exits if NeurofeedbackSetupWidget is the main widget. + */ + ~NeurofeedbackSetupWidget(); + +protected: + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + * + * @param[in] settingsPath the path to store the settings to. + */ + void saveSettings(const QString& settingsPath); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + * + * @param[in] settingsPath the path to load the settings from. + */ + void loadSettings(const QString& settingsPath); + + void changeiOutput(int value); + +private: + Neurofeedback* m_pNeurofeedback; /**< Holds a pointer to corresponding Neurofeedback.*/ + + Ui::NeurofeedbackSetupWidgetClass ui; /**< Holds the user interface for the NeurofeedbackSetupWidget.*/ + + QString m_sSettingsPath; + qint32 m_iOutput; + +}; +} // NAMESPACE + +#endif // NEUROFEEDBACKSETUPWIDGET_H diff --git a/applications/mne_scan/plugins/neurofeedback/neurofeedback.cpp b/applications/mne_scan/plugins/neurofeedback/neurofeedback.cpp new file mode 100644 index 00000000000..bdb2b13caf0 --- /dev/null +++ b/applications/mne_scan/plugins/neurofeedback/neurofeedback.cpp @@ -0,0 +1,478 @@ +//============================================================================================================= +/** + * @file neurofeedback.cpp + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the Neurofeedback class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "neurofeedback.h" +#include "FormFiles/neurofeedbacksetupwidget.h" + +#include +#include +#include +#include + +#include +#include + +#include + + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace NEUROFEEDBACKPLUGIN; +using namespace SCSHAREDLIB; +using namespace SCMEASLIB; +using namespace UTILSLIB; +using namespace FIFFLIB; +using namespace DISPLIB; +using namespace Eigen; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +Neurofeedback::Neurofeedback() +: m_pNeurofeedbackInput(NULL) +, m_pNeurofeedbackOutput(NULL) +, m_pCircularBuffer(QSharedPointer(new CircularBuffer_Matrix_double(10))) +{ +} + +//============================================================================================================= + +Neurofeedback::~Neurofeedback() +{ + if(this->isRunning()) + stop(); +} + +//============================================================================================================= + +void Neurofeedback::init() +{ + // Input + m_pNeurofeedbackInput = PluginInputData::create(this, "NeurofeedbackIn", "Neurofeedback input data"); + connect(m_pNeurofeedbackInput.data(), &PluginInputConnector::notify, this, &Neurofeedback::update, Qt::DirectConnection); + m_inputConnectors.append(m_pNeurofeedbackInput); + + // Output + m_pNeurofeedbackOutput = PluginOutputData::create(this, "NeurofeedbackOut", "Neurofeedback Output Data"); + m_pNeurofeedbackOutput->measurementData()->setName(this->getName());//Provide name to auto store widget settings + m_outputConnectors.append(m_pNeurofeedbackOutput); + +} + +//============================================================================================================= + +QSharedPointer Neurofeedback::clone() const +{ + QSharedPointer pNeurofeedbackClone(new Neurofeedback); + return pNeurofeedbackClone; +} + +//============================================================================================================= + +void Neurofeedback::unload() +{ +} + +//============================================================================================================= + +bool Neurofeedback::start() +{ + QThread::start(); + + return true; +} + +//============================================================================================================= + +bool Neurofeedback::stop() +{ + requestInterruption(); + wait(500); + + m_bPluginControlWidgetsInit = false; + + m_pNeurofeedbackOutput->measurementData().clear(); + m_pCircularBuffer->clear(); + + return true; +} + +//============================================================================================================= + +AbstractPlugin::PluginType Neurofeedback::getType() const +{ + return _IAlgorithm; +} + +//============================================================================================================= + +QString Neurofeedback::getName() const +{ + return "Neurofeedback"; +} + +//============================================================================================================= + +QWidget* Neurofeedback::setupWidget() +{ + NeurofeedbackSetupWidget* setupWidget = new NeurofeedbackSetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new + return setupWidget; +} + +//============================================================================================================= + +void Neurofeedback::update(SCMEASLIB::Measurement::SPtr pMeasurement) +{ + qDebug()<<"Neurofeedback::update"; + if(QSharedPointer pRTMSA = pMeasurement.dynamicCast()) { + //Fiff information + if(!m_pFiffInfo) { + m_pFiffInfo = pRTMSA->info(); + + m_pNeurofeedbackOutput->measurementData()->initFromFiffInfo(m_pFiffInfo); + m_pNeurofeedbackOutput->measurementData()->setMultiArraySize(1); + + } + + if(!m_bPluginControlWidgetsInit) { + initPluginControlWidgets(); + } + + emit updateMin(m_pNeurofeedbackOutput->measurementData()->getFMin()); + emit updateMax(m_pNeurofeedbackOutput->measurementData()->getFMax()); + + for(unsigned char i = 0; i < pRTMSA->getMultiArraySize(); ++i) { + // Please note that we do not need a copy here since this function will block until + // the buffer accepts new data again. Hence, the data is not deleted in the actual + // Mesaurement function after it emitted the notify signal. + while(!m_pCircularBuffer->push(pRTMSA->getMultiSampleArray()[i])) { + //Do nothing until the circular buffer is ready to accept new data again + } + + } + } +} + + + +//============================================================================================================= + +void Neurofeedback::initPluginControlWidgets() +{ + if(m_pFiffInfo) { + QList plNControlWidgets; + + bool bMaxAutoScale = m_pNeurofeedbackOutput->measurementData()->getMaxAutoScale(); + bool bMinAutoScale = m_pNeurofeedbackOutput->measurementData()->getMinAutoScale(); + QString sOutput = m_pNeurofeedbackOutput->measurementData()->getNeuroOutput(); + int iMax = 0; + int iMin = 0; + + if(sOutput == "Frequency"){ + iMax = m_pNeurofeedbackOutput->measurementData()->getFMax(); + iMin = m_pNeurofeedbackOutput->measurementData()->getFMin(); + } + else if(sOutput == "Balloon"){ + iMax = m_pNeurofeedbackOutput->measurementData()->getBMax(); + iMin = m_pNeurofeedbackOutput->measurementData()->getBMin(); + } + + NeurofeedbackSettingsView* pNeurofeedbackSettingsView = new NeurofeedbackSettingsView(QString("MNESCAN/%1/").arg(this->getName()), iMin, iMax, + bMinAutoScale, bMaxAutoScale, 0); + pNeurofeedbackSettingsView->setObjectName("group_tab_Settings_Neurofeedback"); + plNControlWidgets.append(pNeurofeedbackSettingsView); + + if(sOutput == "Frequency"){ + connect(pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::MaxChanged, this, &Neurofeedback::changeFMax); + connect(pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::MinChanged, this, &Neurofeedback::changeFMin); + connect(this, &Neurofeedback::updateMax, pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::changeMax); + connect(this, &Neurofeedback::updateMin, pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::changeMin); + } + else if(sOutput == "Balloon"){ + connect(pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::MaxChanged, this, &Neurofeedback::changeBMax); + connect(pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::MinChanged, this, &Neurofeedback::changeBMin); + } + + connect(pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::MaxAutoScaleChanged, this, &Neurofeedback::changeMaxAutoScale); + connect(pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::MinAutoScaleChanged, this, &Neurofeedback::changeMinAutoScale); + connect(pNeurofeedbackSettingsView, &NeurofeedbackSettingsView::ResetAutoScaleChanged, this, &Neurofeedback::changeResetAutoScale); + + + + + emit pluginControlWidgetsChanged(plNControlWidgets, this->getName()); + + m_bPluginControlWidgetsInit = true; + } +} + + + +//============================================================================================================= + +void Neurofeedback::run() + +{ + MatrixXd matData; + + // Wait for Fiff Info + while(!m_pFiffInfo) { + msleep(10); + } + while(!isInterruptionRequested()) { + // Get the current data + if(m_pCircularBuffer->pop(matData)) { + //ToDo: Implement your algorithm here + + //Send the data to the connected plugins and the online display + //Unocmment this if you also uncommented the m_pOutput in the constructor above + if(!isInterruptionRequested()) { + m_pNeurofeedbackOutput->measurementData()->setValue(matData); + } + } + } +} + + +//============================================================================================================== +void Neurofeedback::changeOutput(int value){ + if(value == 0){ + m_pNeurofeedbackOutput->measurementData()->setNeuroOutput("Classifier"); + } + else if(value == 1){ + m_pNeurofeedbackOutput->measurementData()->setNeuroOutput("Frequency"); + } + else{ + m_pNeurofeedbackOutput->measurementData()->setNeuroOutput("Balloon"); + } +} + +//============================================================================================================== +void Neurofeedback::changeSliders(int value){ + m_pNeurofeedbackOutput->measurementData()->setSlider(value); +} + +//============================================================================================================== +void Neurofeedback::changeballCh(bool ballCh){ + m_pNeurofeedbackOutput->measurementData()->setallCh(ballCh); +} + +//============================================================================================================== +void Neurofeedback::changeNumbofClass(int value){ + m_pNeurofeedbackOutput->measurementData()->setNumbofClass(value); +} + +//============================================================================================================== +void Neurofeedback::changeClass0(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassL(text, 0); +} +//============================================================================================================== +void Neurofeedback::changeClass1(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassL(text, 1); +} + +//=============================================================================================================== +void Neurofeedback::changeClass2(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassL(text, 2); +} + +//=============================================================================================================== +void Neurofeedback::changeClass3(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassL(text, 3); +} + +//=============================================================================================================== +void Neurofeedback::changeClass4(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassL(text, 4); +} + +//=============================================================================================================== +void Neurofeedback::changeGBC0(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassCol(text, 0); +} + +//=============================================================================================================== +void Neurofeedback::changeGBC1(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassCol(text, 1); +} + +//=============================================================================================================== +void Neurofeedback::changeGBC2(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassCol(text, 2); +} + +//=============================================================================================================== +void Neurofeedback::changeGBC3(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassCol(text, 3); +} + +//=============================================================================================================== +void Neurofeedback::changeGBC4(QString text){ + m_pNeurofeedbackOutput->measurementData()->setClassCol(text, 4); +} + +//=============================================================================================================== +void Neurofeedback::changeiClass0(int value){ + m_pNeurofeedbackOutput->measurementData()->setClassI(value, 0); +} + +//=============================================================================================================== +void Neurofeedback::changeiClass1(int value){ + m_pNeurofeedbackOutput->measurementData()->setClassI(value, 1); +} + +//=============================================================================================================== +void Neurofeedback::changeiClass2(int value){ + m_pNeurofeedbackOutput->measurementData()->setClassI(value, 2); +} + +//=============================================================================================================== +void Neurofeedback::changeiClass3(int value){ + m_pNeurofeedbackOutput->measurementData()->setClassI(value, 3); +} + +//=============================================================================================================== +void Neurofeedback::changeiClass4(int value){ + m_pNeurofeedbackOutput->measurementData()->setClassI(value, 4); +} + +//=============================================================================================================== +void Neurofeedback::changeImgClass0(QPixmap image){ + m_pNeurofeedbackOutput->measurementData()->setClassImg(image, 0); +} + +//=============================================================================================================== +void Neurofeedback::changeImgClass1(QPixmap image){ + m_pNeurofeedbackOutput->measurementData()->setClassImg(image, 1); +} + +//=============================================================================================================== +void Neurofeedback::changeImgClass2(QPixmap image){ + m_pNeurofeedbackOutput->measurementData()->setClassImg(image, 2); +} + +//=============================================================================================================== +void Neurofeedback::changeImgClass3(QPixmap image){ + m_pNeurofeedbackOutput->measurementData()->setClassImg(image, 3); +} + +//=============================================================================================================== +void Neurofeedback::changeImgClass4(QPixmap image){ + m_pNeurofeedbackOutput->measurementData()->setClassImg(image, 4); +} + +//============================================================================================================= +void Neurofeedback::changeImgBackground(QPixmap image){ + m_pNeurofeedbackOutput->measurementData()->setImgBackground(image); +} + +//============================================================================================================= + +void Neurofeedback::changeImgObject(QPixmap image){ + m_pNeurofeedbackOutput->measurementData()->setImgObject(image); +} + +//============================================================================================================= + +void Neurofeedback::changeBMax(int value){ + m_pNeurofeedbackOutput->measurementData()->setBMax(value); +} + +//============================================================================================================= + +void Neurofeedback::changeBMin(int value){ + m_pNeurofeedbackOutput->measurementData()->setBMin(value); +} + +//============================================================================================================= + +void Neurofeedback::changeFMax(int value){ + m_pNeurofeedbackOutput->measurementData()->setFMax(value); +} + +//============================================================================================================= + +void Neurofeedback::changeFMin(int value){ + m_pNeurofeedbackOutput->measurementData()->setFMin(value); +} + +//============================================================================================================= + +void Neurofeedback::changeMaxAutoScale(bool bMaxAutoScale){ + m_pNeurofeedbackOutput->measurementData()->setMaxAutoScale(bMaxAutoScale); +} + +//============================================================================================================= + +void Neurofeedback::changeMinAutoScale(bool bMinAutoScale){ + m_pNeurofeedbackOutput->measurementData()->setMinAutoScale(bMinAutoScale); +} + +//============================================================================================================= + +void Neurofeedback::changeResetAutoScale(bool bResetAutoScale){ + m_pNeurofeedbackOutput->measurementData()->setResetAutoScale(bResetAutoScale); +} + +//============================================================================================================= + +void Neurofeedback::changeChannel(int value){ + m_pNeurofeedbackOutput->measurementData()->setChannel(value); +} + +//============================================================================================================= + +QString Neurofeedback::getBuildInfo() +{ + return QString(NEUROFEEDBACKPLUGIN::buildDateTime()) + QString(" - ") + QString(NEUROFEEDBACKPLUGIN::buildHash()); +} diff --git a/applications/mne_scan/plugins/neurofeedback/neurofeedback.h b/applications/mne_scan/plugins/neurofeedback/neurofeedback.h new file mode 100644 index 00000000000..6cbc637cd68 --- /dev/null +++ b/applications/mne_scan/plugins/neurofeedback/neurofeedback.h @@ -0,0 +1,497 @@ +//============================================================================================================= +/** + * @file neurofeedback.h + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the Neurofeedback class. + * + */ + +#ifndef NEUROFEEDBACK_H +#define NEUROFEEDBACK_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "neurofeedback_global.h" + +#include +#include + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace SCMEASLIB{ + class RealTimeMultiSampleArray; + class RealTimeNeurofeedbackResult; +} + + + +//============================================================================================================= +// DEFINE NAMESPACE NEUROFEEDBACKPLUGIN +//============================================================================================================= + +namespace NEUROFEEDBACKPLUGIN +{ + +//============================================================================================================= +// NEUROFEEDBACKPLUGIN FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * DECLARE CLASS Neurofeedback + * + * @brief The Neurofeedback class provides a Neurofeedback algorithm structure. + */ +class NEUROFEEDBACKSHARED_EXPORT Neurofeedback : public SCSHAREDLIB::AbstractAlgorithm +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "scsharedlib/1.0" FILE "neurofeedback.json") //New Qt5 Plugin system replaces Q_EXPORT_PLUGIN2 macro + // Use the Q_INTERFACES() macro to tell Qt's meta-object system about the interfaces + Q_INTERFACES(SCSHAREDLIB::AbstractAlgorithm) + + friend class NeurofeedbackSettingsWidget; + +public: + //========================================================================================================= + /** + * Constructs a Neurofeedback. + */ + Neurofeedback(); + + //========================================================================================================= + /** + * Destroys the Neurofeedback. + */ + ~Neurofeedback(); + + //========================================================================================================= + /** + * Inits widgets which are used to control this plugin, then emits them in form of a QList. + */ + void initPluginControlWidgets(); + + //========================================================================================================= + /** + * Reimplemented virtual functions + */ + virtual void unload(); + virtual QSharedPointer clone() const; + virtual bool start(); + virtual bool stop(); + virtual SCSHAREDLIB::AbstractPlugin::PluginType getType() const; + virtual QString getName() const; + virtual QWidget* setupWidget(); + virtual QString getBuildInfo(); + + //========================================================================================================= + /** + * Udates the pugin with new (incoming) data. + * + * @param[in] pMeasurement The incoming data in form of a generalized Measurement. + */ + void update(SCMEASLIB::Measurement::SPtr pMeasurement); + + //========================================================================================================= + /** + * Initialise input and output connectors. + */ + virtual void init(); + + //========================================================================================================= + /** + * Changes the Type of Output. + * + * @param[in] value Type of Output for Neurofeedback. + */ + void changeOutput(int value); + + //========================================================================================================= + /** + * Changes the Number of Sliders. + * + * @param[in] value Number of Sliders. + */ + void changeSliders(int value); + + //========================================================================================================= + /** + * Changes the Bool for all Channels. + * + * @param[in] ballCh Bool for all Channels selected or not. + */ + void changeballCh(bool ballCh); + + //========================================================================================================= + /** + * Changes the Bool for minimum autoscale. + * + * @param[in] bMinAutoScale Bool for minimum autoscale. + */ + void changeMinAutoScale(bool bMinAutoScale); + + //========================================================================================================= + /** + * Changes the Bool for maximum autoscale. + * + * @param[in] bMaxAutoScale Bool for maximum autoscale. + */ + void changeMaxAutoScale(bool bMaxAutoScale); + + //========================================================================================================= + /** + * Changes the Bool for reset autoscale. + * + * @param[in] bResetAutoScale Bool for reset autoscale. + */ + void changeResetAutoScale(bool bResetAutoScale); + + //========================================================================================================= + /** + * Changes the Number of Classification. + * + * @param[in] value Number of Classification. + */ + void changeNumbofClass(int value); + + //========================================================================================================= + /** + * Changes the Textoutput for Classification 0. + * + * @param[in] text Textouptut for Classification 0. + */ + void changeClass0(QString text); + + //========================================================================================================= + /** + * Changes the Textoutput for Classification 1. + * + * @param[in] text Textouptut for Classification 1. + */ + void changeClass1(QString text); + + //========================================================================================================= + /** + * Changes the Textoutput for Classification 2. + * + * @param[in] text Textouptut for Classification 2. + */ + void changeClass2(QString text); + + //========================================================================================================= + /** + * Changes the Textoutput for Classification 3. + * + * @param[in] text Textouptut for Classification 3. + */ + void changeClass3(QString text); + + //========================================================================================================= + /** + * Changes the Textoutput for Classification 4. + * + * @param[in] text Textouptut for Classification 4. + */ + void changeClass4(QString text); + + //========================================================================================================= + /** + * Changes the Color for Textouput Classification 0. + * + * @param[in] text Color for Textouput Classification 0. + */ + void changeGBC0(QString text); + + //========================================================================================================= + /** + * Changes the Color for Textouput Classification 1. + * + * @param[in] text Color for Textouput Classification 1. + */ + void changeGBC1(QString text); + + //========================================================================================================= + /** + * Changes the Color for Textouput Classification 2. + * + * @param[in] text Color for Textouput Classification 2. + */ + void changeGBC2(QString text); + + //========================================================================================================= + /** + * Changes the Color for Textouput Classification 3. + * + * @param[in] text Color for Textouput Classification 3. + */ + void changeGBC3(QString text); + + //========================================================================================================= + /** + * Changes the Color for Textouput Classification 4. + * + * @param[in] text Color for Textouput Classification 4. + */ + void changeGBC4(QString text); + + //========================================================================================================= + /** + * Changes the Integer for Classification 0. + * + * @param[in] value Integer for Classification 0. + */ + void changeiClass0(int value); + + //========================================================================================================= + /** + * Changes the Integer for Classification 1. + * + * @param[in] value Integer for Classification 1. + */ + void changeiClass1(int value); + + //========================================================================================================= + /** + * Changes the Integer for Classification 2. + * + * @param[in] value Integer for Classification 2. + */ + void changeiClass2(int value); + + //========================================================================================================= + /** + * Changes the Integer for Classification 3. + * + * @param[in] value Integer for Classification 3. + */ + void changeiClass3(int value); + + //========================================================================================================= + /** + * Changes the Integer for Classification 4. + * + * @param[in] value Integer for Classification 4. + */ + void changeiClass4(int value); + + //========================================================================================================= + /** + * Changes the Directory for the Imageoutput Classification 0. + * + * @param[im] text Directory for Imageoutput Classification 0. + */ + void changeDirClass0(QString text); + + //========================================================================================================= + /** + * Changes the Directory for the Imageoutput Classification 1. + * + * @param[im] text Directory for Imageoutput Classification 1. + */ + void changeDirClass1(QString text); + + //========================================================================================================= + /** + * Changes the Directory for the Imageoutput Classification 2. + * + * @param[im] text Directory for Imageoutput Classification 2. + */ + void changeDirClass2(QString text); + + //========================================================================================================= + /** + * Changes the Directory for the Imageoutput Classification 3. + * + * @param[im] text Directory for Imageoutput Classification 3. + */ + void changeDirClass3(QString text); + + //========================================================================================================= + /** + * Changes the Directory for the Imageoutput Classification 4. + * + * @param[im] text Directory for Imageoutput Classification 4. + */ + void changeDirClass4(QString text); + + //========================================================================================================= + /** + * Changes the Imageoutput for Classification 0. + * + * @param[im] image Imageoutput for Classification 0. + */ + void changeImgClass0(QPixmap image); + + //========================================================================================================= + /** + * Changes the Imageoutput for Classification 1. + * + * @param[im] image Imageoutput for Classification 1. + */ + void changeImgClass1(QPixmap image); + + //========================================================================================================= + /** + * Changes the Imageoutput for Classification 2. + * + * @param[im] image Imageoutput for Classification 2. + */ + void changeImgClass2(QPixmap image); + + //========================================================================================================= + /** + * Changes the Imageoutput for Classification 3. + * + * @param[im] image Imageoutput for Classification 3. + */ + void changeImgClass3(QPixmap image); + + //========================================================================================================= + /** + * Changes the Imageoutput for Classification 4. + * + * @param[im] image Imageoutput for Classification 4. + */ + void changeImgClass4(QPixmap image); + + //========================================================================================================= + /** + * Changes the Backgroundimage. + * + * @param[im] image Backgroundimage. + */ + void changeImgBackground(QPixmap image); + + //========================================================================================================= + /** + * Changes the Directory for the Objectimage. + * + * @param[im] image Objectimage. + */ + void changeImgObject(QPixmap image); + + //========================================================================================================= + /** + * Changes the Miniumumfrequency for Sliders. + * + * @param[im] value Minimumfrequency Slider. + */ + void changeFMin(int value); + + //========================================================================================================= + /** + * Changes the Maximumfrequency for Sliders. + * + * @param[im] value Maximumfrequency Slider. + */ + void changeFMax(int value); + + //========================================================================================================= + /** + * Changes the Minimumfrequency for the Balloon. + * + * @param[im] value Minimumfrequency Balloon. + */ + void changeBMin(int value); + + //========================================================================================================= + /** + * Changes the Maximumfrequency for the Balloon. + * + * @param[im] value Maximumfrequency Balloon. + */ + void changeBMax(int value); + + //========================================================================================================= + /** + * Changes the Channel for the Balloon. + * + * @param[im] value Channel for Balloon. + */ + void changeChannel(int value); + //========================================================================================================= + + + +protected: + virtual void run(); + +private: + + SCSHAREDLIB::PluginInputData::SPtr m_pNeurofeedbackInput; + SCSHAREDLIB::PluginOutputData::SPtr m_pNeurofeedbackOutput; + + QSharedPointer m_pCircularBuffer; /**< Holds incoming raw data. */ + + QMutex m_qMutex; /**< Provides access serialization between threads. */ + + FIFFLIB::FiffInfo::SPtr m_pFiffInfo; /**< Fiff measurement info.*/ + + QStringList m_lResponsibleTriggerTypes; /**< List of all trigger types which lead to the recent emit of a new evoked set. */ + + QMap m_mapStimChsIndexNames; /**< The currently available stim channels and their corresponding index in the data. */ + + int m_iSliders; + int m_iNumbofclass; + int m_iClass0; + int m_iClass1; + int m_iClass2; + int m_iClass3; + int m_iClass4; + + QString m_sClass0; + QString m_sClass1; + QString m_sClass2; + QString m_sClass3; + QString m_sClass4; + QString m_sNeurooutput; + + bool m_ballCh; + + + +signals: + void stimChannelsChanged(const QMap& mapStimChsIndexNames); + void fiffChInfoChanged(const QList& fiffChInfoList); + void evokedSetChanged(const FIFFLIB::FiffEvokedSet& evokedSet); + void updateMin(int iMin); + void updateMax(int iMax); +}; +} // NAMESPACE + +#endif // NEUROFEEDBACK_H diff --git a/applications/mne_scan/plugins/neurofeedback/neurofeedback.json b/applications/mne_scan/plugins/neurofeedback/neurofeedback.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/applications/mne_scan/plugins/neurofeedback/neurofeedback.pro b/applications/mne_scan/plugins/neurofeedback/neurofeedback.pro new file mode 100644 index 00000000000..52fa7bbd897 --- /dev/null +++ b/applications/mne_scan/plugins/neurofeedback/neurofeedback.pro @@ -0,0 +1,158 @@ +#============================================================================================================== +# +# @file neurofeedback.pro +# @author Simon Marxgut +# @since 0.1.0 +# @date November, 2021 +# +# @section LICENSE +# +# Copyright (C) 2021, Simon Marxgut. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that +# the following conditions are met: +# * Redistributions of source code must retain the above copyright notice, this list of conditions and the +# following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and +# the following disclaimer in the documentation and/or other materials provided with the distribution. +# * Neither the name of MNE-CPP authors nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# +# @brief This project file generates the makefile for the Neurofeedback Plugin. +# +#============================================================================================================== + +include(../../../../mne-cpp.pri) + +TEMPLATE = lib + +QT += core widgets + +CONFIG += skip_target_version_ext plugin + +DEFINES += NEUROFEEDBACK_PLUGIN + +DESTDIR = $${MNE_BINARY_DIR}/mne_scan_plugins + +TARGET = neurofeedback +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static){ + CONFIG += staticlib + DEFINES += STATICBUILD +} else { + CONFIG += shared +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lscSharedd \ + -lscDispd \ + -lscMeasd \ + -lmnecppFiffd \ + -lmnecppUtilsd \ +} else { + LIBS += -lscShared \ + -lscDisp \ + -lscMeas \ + -lmnecppFiff \ + -lmnecppUtils \ +} + +SOURCES += \ + FormFiles/neurofeedbacksetupwidget.cpp \ + neurofeedback.cpp \ + neurofeedback_global.cpp + +HEADERS += \ + FormFiles/neurofeedbacksetupwidget.h \ + neurofeedback.h \ + neurofeedback_global.h + +FORMS += \ + FormFiles/neurofeedbacksetup.ui + +clang { + QMAKE_CXXFLAGS += -isystem $${EIGEN_INCLUDE_DIR} +} else { + INCLUDEPATH += $${EIGEN_INCLUDE_DIR} +} + +INCLUDEPATH += $${MNE_INCLUDE_DIR} +INCLUDEPATH += $${MNE_SCAN_INCLUDE_DIR} + +OTHER_FILES += neurofeedback.json + +unix:!macx { + QMAKE_RPATHDIR += $ORIGIN/../../lib +} + +# Activate FFTW backend in Eigen for non-static builds only +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { + DEFINES += EIGEN_FFTW_DEFAULT + INCLUDEPATH += $$shell_path($${FFTW_DIR_INCLUDE}) + LIBS += -L$$shell_path($${FFTW_DIR_LIBS}) + + win32 { + # On Windows + LIBS += -llibfftw3-3 \ + -llibfftw3f-3 \ + -llibfftw3l-3 \ + } + + unix:!macx { + # On Linux + LIBS += -lfftw3 \ + -lfftw3_threads \ + } +} + +#DISTFILES += \ +# neurofeedback.json \ +# neurofeedback.pro.user + +################################################## BUILD TIMESTAMP/HASH UPDATER ############################################ + +FILE_TO_UPDATE = neurofeedback_global.cpp +win32 { + CONFIG(debug, debug|release) { + OBJ_TARJET = debug\neurofeedback_global.obj + } else { + OBJ_TARJET = release\neurofeedback_global.obj + } +} + +ALL_FILES += $$HEADERS +ALL_FILES += $$SOURCES +ALL_FILES -= $$FILE_TO_UPDATE + +FileUpdater.target = phonyFileUpdater +for (I_FILE, ALL_FILES) { + FileUpdater.depends += $${PWD}/$${I_FILE} +} + +unix|macx { + FileUpdater.commands = touch $${PWD}/$${FILE_TO_UPDATE} ; echo PASTA > phonyFileUpdater +} + +win32 { + FileUpdater.commands = copy /y $$shell_path($${PWD})\\$${FILE_TO_UPDATE} +,, $$shell_path($${PWD})\\$${FILE_TO_UPDATE} & echo PASTA > phonyFileUpdater + OrderForcerTarget.target = $${OBJ_TARJET} + OrderForcerTarget.depends += phonyFileUpdater + QMAKE_EXTRA_TARGETS += OrderForcerTarget +} + +PRE_TARGETDEPS += phonyFileUpdater +QMAKE_EXTRA_TARGETS += FileUpdater diff --git a/applications/mne_scan/plugins/neurofeedback/neurofeedback_global.cpp b/applications/mne_scan/plugins/neurofeedback/neurofeedback_global.cpp new file mode 100644 index 00000000000..57f8b0a6154 --- /dev/null +++ b/applications/mne_scan/plugins/neurofeedback/neurofeedback_global.cpp @@ -0,0 +1,53 @@ +//============================================================================================================= +/** + * @file neurofeedback_global.cpp + * @author Simon Marxgut + * @since 0.1.9 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief neurofeedback plugin global definitions. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "neurofeedback_global.h" + +//============================================================================================================= +// DEFINE METHODS +//============================================================================================================= + +const char* NEUROFEEDBACKPLUGIN::buildDateTime(){ return UTILSLIB::dateTimeNow();}; + +//============================================================================================================= + +const char* NEUROFEEDBACKPLUGIN::buildHash(){ return UTILSLIB::gitHash();}; + +//============================================================================================================= + +const char* NEUROFEEDBACKPLUGIN::buildHashLong(){ return UTILSLIB::gitHashLong();}; diff --git a/applications/mne_scan/plugins/neurofeedback/neurofeedback_global.h b/applications/mne_scan/plugins/neurofeedback/neurofeedback_global.h new file mode 100644 index 00000000000..cd6f21b32ae --- /dev/null +++ b/applications/mne_scan/plugins/neurofeedback/neurofeedback_global.h @@ -0,0 +1,81 @@ +//============================================================================================================= +/** + * @file neurofeedback_global.h + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the Neurofeedback library export/import macros. + * + */ + +#ifndef NEUROFEEDBACK_GLOBAL_H +#define NEUROFEEDBACK_GLOBAL_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// PREPROCESSOR DEFINES +//============================================================================================================= + +#if defined(NEUROFEEDBACK_PLUGIN) +# define NEUROFEEDBACKSHARED_EXPORT Q_DECL_EXPORT /**< Q_DECL_EXPORT must be added to the declarations of symbols used when compiling a shared library. */ +#else +# define NEUROFEEDBACKSHARED_EXPORT Q_DECL_IMPORT /**< Q_DECL_IMPORT must be added to the declarations of symbols used when compiling a client that uses the shared library. */ +#endif + +namespace NEUROFEEDBACKPLUGIN{ + +//============================================================================================================= +/** + * Returns build date and time. + */ +NEUROFEEDBACKSHARED_EXPORT const char* buildDateTime(); + +//============================================================================================================= +/** + * Returns abbreviated build git hash. + */ +NEUROFEEDBACKSHARED_EXPORT const char* buildHash(); + +//============================================================================================================= +/** + * Returns full build git hash. + */ +NEUROFEEDBACKSHARED_EXPORT const char* buildHashLong(); +} + +#endif // NEUROFEEDBACK_GLOBAL_H diff --git a/applications/mne_scan/plugins/plugins.pro b/applications/mne_scan/plugins/plugins.pro index 9e4b48f69b5..a01d5361135 100644 --- a/applications/mne_scan/plugins/plugins.pro +++ b/applications/mne_scan/plugins/plugins.pro @@ -47,6 +47,8 @@ SUBDIRS += \ babymeg \ natus \ + + contains(MNECPP_CONFIG, withBrainAmp) { SUBDIRS += brainamp \ # Build guide -> https://mne-cpp.github.io/pages/development/brainamp.html } @@ -72,8 +74,12 @@ SUBDIRS += \ rtcmne \ averaging \ covariance \ + neurofeedback \ noisereduction \ neuronalconnectivity \ writetofile \ hpi \ rtfwd \ + + + diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index 2531e9518f4..653fea5afd5 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -107,6 +107,10 @@ SOURCES += \ viewers/averagelayoutview.cpp \ viewers/fwdsettingsview.cpp \ viewers/helpers/scalecontrol.cpp \ + viewers/neurofeedbackbsettingsview.cpp \ + viewers/neurofeedbackcsettingsview.cpp \ + viewers/neurofeedbackfsettingsview.cpp \ + viewers/neurofeedbacksettingsview.cpp \ viewers/progressview.cpp \ viewers/spectrumview.cpp \ viewers/modalityselectionview.cpp \ @@ -166,6 +170,10 @@ HEADERS += \ viewers/averagelayoutview.h \ viewers/fwdsettingsview.h \ viewers/helpers/scalecontrol.h \ + viewers/neurofeedbackbsettingsview.h \ + viewers/neurofeedbackcsettingsview.h \ + viewers/neurofeedbackfsettingsview.h \ + viewers/neurofeedbacksettingsview.h \ viewers/progressview.h \ viewers/spectrumview.h \ viewers/modalityselectionview.h \ @@ -228,6 +236,10 @@ FORMS += \ viewers/formfiles/channelselectionview.ui \ viewers/formfiles/coregsettingsview.ui \ viewers/formfiles/fwdsettingsview.ui \ + viewers/formfiles/neurofeedbackbsettingsview.ui \ + viewers/formfiles/neurofeedbackcsettingsview.ui \ + viewers/formfiles/neurofeedbackfsettingsview.ui \ + viewers/formfiles/neurofeedbacksettingsview.ui \ viewers/formfiles/progressview.ui \ viewers/formfiles/spharasettingsview.ui \ viewers/formfiles/fiffrawviewsettings.ui \ @@ -286,6 +298,7 @@ contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { } } + ################################################## BUILD TIMESTAMP/HASH UPDATER ############################################ FILE_TO_UPDATE = disp_global.cpp @@ -319,3 +332,4 @@ win32 { PRE_TARGETDEPS += phonyFileUpdater QMAKE_EXTRA_TARGETS += FileUpdater + diff --git a/libraries/disp/viewers/formfiles/neurofeedbackbsettingsview.ui b/libraries/disp/viewers/formfiles/neurofeedbackbsettingsview.ui new file mode 100644 index 00000000000..546c37e7613 --- /dev/null +++ b/libraries/disp/viewers/formfiles/neurofeedbackbsettingsview.ui @@ -0,0 +1,136 @@ + + + NeurofeedbackBSettingsViewWidget + + + + 0 + 0 + 631 + 492 + + + + Form + + + + + + 0 + + + 20 + + + 9 + + + + + not loaded + + + + + + + Max + + + + + + + Standard + + + + + + + not loaded + + + + + + + Load + + + + + + + Load + + + + + + + + + + + + + Min + + + + + + + Object + + + + + + + Standard + + + + + + + Background + + + + + + + + + + + + + Reset Settings + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/libraries/disp/viewers/formfiles/neurofeedbackcsettingsview.ui b/libraries/disp/viewers/formfiles/neurofeedbackcsettingsview.ui new file mode 100644 index 00000000000..8e7fedeb529 --- /dev/null +++ b/libraries/disp/viewers/formfiles/neurofeedbackcsettingsview.ui @@ -0,0 +1,393 @@ + + + NeurofeedbackCSettingsViewWidget + + + + 0 + 0 + 760 + 492 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0 + + + 20 + + + 9 + + + + + + + + Load + + + + + + + Load + + + + + + + Load + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Delete + + + + + + + + + + Reset Settings + + + + + + + Class 4 + + + + + + + + + + + + + + Text Output + + + + + + + Class. + + + + + + + + + + + + + + not loaded + + + + + + + Delete + + + + + + + + + + + + + Class 1 + + + + + + + + + + + + + + + + + + + + + + + + not loaded + + + + + + + Delete + + + + + + + + + + + + + + + + + Class 0 + + + + + + + Classifications + + + + + + + Load + + + + + + + + + + Load + + + + + + + + + + + + + + + + + + + + <html><head/><body><p>✔</p></body></html> + + + + + + + Class 3 + + + + + + + Delete + + + + + + + + + + + + + + + + + Class 2 + + + + + + + + + + + + + + + + + not loaded + + + + + + + 99 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Delete + + + + + + + not loaded + + + + + + + + + + + + + + + + + + + + ✘ + + + + + + + not loaded + + + + + + + Graphic Output + + + + + + + + + + diff --git a/libraries/disp/viewers/formfiles/neurofeedbackfsettingsview.ui b/libraries/disp/viewers/formfiles/neurofeedbackfsettingsview.ui new file mode 100644 index 00000000000..a82d1b5d3b8 --- /dev/null +++ b/libraries/disp/viewers/formfiles/neurofeedbackfsettingsview.ui @@ -0,0 +1,130 @@ + + + NeurofeedbackFSettingsViewWidget + + + + 0 + 0 + 451 + 492 + + + + Form + + + + + + 0 + + + 20 + + + 9 + + + + + Reset Settings + + + + + + + all Channels + + + + + + + Standard + + + + + + + autoscale + + + + + + + Standard + + + + + + + true + + + Sliders + + + + + + + Min + + + + + + + 1000 + + + + + + + 1000 + + + + + + + Max + + + + + + + autoscale + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/libraries/disp/viewers/formfiles/neurofeedbacksettingsview.ui b/libraries/disp/viewers/formfiles/neurofeedbacksettingsview.ui new file mode 100644 index 00000000000..e11f79c54dc --- /dev/null +++ b/libraries/disp/viewers/formfiles/neurofeedbacksettingsview.ui @@ -0,0 +1,95 @@ + + + NeurofeedbackSettingsViewWidget + + + + 0 + 0 + 313 + 172 + + + + + 0 + 0 + + + + false + + + Form + + + 0.950000000000000 + + + + + + + 8 + + + + + 0 + + + + + Min + + + + + + + 1000 + + + + + + + Max + + + + + + + 1000 + + + + + + + Autoscale + + + + + + + Autoscale + + + + + + + Reset Autoscale + + + + + + + + + + diff --git a/libraries/disp/viewers/neurofeedbackbsettingsview.cpp b/libraries/disp/viewers/neurofeedbackbsettingsview.cpp new file mode 100644 index 00000000000..86a825d7ec8 --- /dev/null +++ b/libraries/disp/viewers/neurofeedbackbsettingsview.cpp @@ -0,0 +1,295 @@ +//============================================================================================================= +/** + * @file neurofeedbackbsettingsview.cpp + * @author Simon Marxgut + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the NeurofeedbackBSettingsView Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "neurofeedbackbsettingsview.h" +#include "ui_neurofeedbackbsettingsview.h" + +#include "neurofeedbackfsettingsview.h" +#include "ui_neurofeedbackfsettingsview.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include +#include + +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +NeurofeedbackBSettingsView::NeurofeedbackBSettingsView(const QString& sSettingsPath, int ibMax, int ibMin, QWidget *parent, Qt::WindowFlags f) +: QWidget(parent, f) +, m_pui(new Ui::NeurofeedbackBSettingsViewWidget) +, m_sSettingsPath(sSettingsPath) +, m_ibMax(ibMax) +, m_ibMin(ibMin) +{ + m_pui->setupUi(this); + + this->setWindowTitle("Neurofeedback Settings"); + this->setMinimumWidth(550); + this->setMaximumWidth(550); + + loadSettings(m_sSettingsPath); + + m_pui->lineEdit_DirBackground->setReadOnly(true); + m_pui->lineEdit_DirObject->setReadOnly(true); + + onUpdateSpinBoxMax(m_ibMax); + onUpdateSpinBoxMin(m_ibMin); + + connect(m_pui->pushButton_Background, &QPushButton::released, this, &NeurofeedbackBSettingsView::clickedLoadBackground); + connect(m_pui->pushButton_Object, &QPushButton::released, this, &NeurofeedbackBSettingsView::clickedLoadObject); + connect(m_pui->spinBox_Max,static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackBSettingsView::onUpdateSpinBoxMax); + connect(m_pui->spinBox_Min,static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackBSettingsView::onUpdateSpinBoxMin); + connect(m_pui->pushButton_StdMax, &QPushButton::released, this, &NeurofeedbackBSettingsView::clickedStdMax); + connect(m_pui->pushButton_StdMin, &QPushButton::released, this, &NeurofeedbackBSettingsView::clickedStdMin); + connect(m_pui->pushButton_ResetSettings, &QPushButton::released, this, &NeurofeedbackBSettingsView::clickedResetSettings); + + emitSignals(); + updateDisplay(); + +} +//============================================================================================================= + +NeurofeedbackBSettingsView::~NeurofeedbackBSettingsView() +{ + saveSettings(m_sSettingsPath); + + delete m_pui; +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::saveSettings(const QString& settingsPath) +{ + if(settingsPath.isEmpty()) { + return; + } + + // Store Settings + QSettings settings; + + settings.setValue(settingsPath + QString("/ibMax"), m_ibMax); + settings.setValue(settingsPath + QString("/ibMin"), m_ibMin); + settings.setValue(settingsPath + QString("/sDirBackground"), m_sDirBackground); + settings.setValue(settingsPath + QString("/sDirObject"), m_sDirObject); + +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::loadSettings(const QString& settingsPath) +{ + if(settingsPath.isEmpty()) { + return; + } + + // Load Settings + QSettings settings; + + m_ibMax = settings.value(settingsPath + QString("/ibMax"), m_ibMax).toInt(); + m_ibMin = settings.value(settingsPath + QString("/ibMin"), m_ibMin).toInt(); + m_sDirBackground = settings.value(settingsPath + QString("/sDirBackground"), m_sDirBackground).toString(); + m_sDirObject = settings.value(settingsPath + QString("/sDirObject"), m_sDirObject).toString(); + +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::clickedResetSettings() +{ + m_ibMax = 25; + m_ibMin = 0; + m_sDirBackground = ""; + m_sDirObject = ""; + + saveSettings(m_sSettingsPath); + emitSignals(); + updateDisplay(); +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::updateDisplay() +{ + m_pui->lineEdit_DirBackground->setText(m_sDirBackground); + m_pui->lineEdit_DirObject->setText(m_sDirObject); + m_pui->spinBox_Max->setValue(m_ibMax); + m_pui->spinBox_Min->setValue(m_ibMin); + updateStatusBackground(); + updateStatusObject(); +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::emitSignals() +{ + emit changeMax(m_ibMax); + emit changeMin(m_ibMin); + emit changeImgBackground(m_imgBackground); + emit changeImgObject(m_imgObject); +} + + +//============================================================================================================= + +void NeurofeedbackBSettingsView::clickedLoadBackground() +{ + m_sDirBackground = QFileDialog::getOpenFileName(this, tr("Open File"), "/home", tr("Images (*.png *.xpm *.jpg)")); + m_pui->lineEdit_DirBackground->setText(m_sDirBackground); + updateStatusBackground(); + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::clickedLoadObject() +{ + m_sDirObject = QFileDialog::getOpenFileName(this, tr("Open File"), "/home", tr("Images (*.png *.xpm *.jpg)")); + m_pui->lineEdit_DirObject->setText(m_sDirObject); + updateStatusObject(); + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::onUpdateSpinBoxMax(int value) +{ + m_ibMax = value; + emit changeMax(m_ibMax); + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::updateStatusBackground() +{ + if(m_sDirBackground.isEmpty()){ + m_pui->label_StatusBackground->setText("not loaded"); + m_pui->label_StatusBackground->setStyleSheet("QLabel {color: black;}"); + } + else { + QPixmap img(m_sDirBackground); + m_imgBackground = img; + if(m_imgBackground.load(m_sDirBackground) == true){ + emit changeImgBackground(m_imgBackground); + m_pui->label_StatusBackground->setText("loaded"); + m_pui->label_StatusBackground->setStyleSheet("QLabel {color: green;}"); + } + else{ + m_pui->label_StatusBackground->setText("not loaded"); + m_pui->label_StatusBackground->setStyleSheet("QLabel {color: black;}"); + } + + } +} + +//============================================================================================================= + +void NeurofeedbackBSettingsView::updateStatusObject() +{ + if(m_sDirObject.isEmpty()){ + m_pui->label_StatusObject->setText("not loaded"); + m_pui->label_StatusObject->setStyleSheet("QLabel {color: black;}"); + } + else { + QImage image(m_sDirObject); + image = image.convertToFormat(QImage::Format_ARGB32); + for(int i = 0; ilabel_StatusObject->setText("loaded"); + m_pui->label_StatusObject->setStyleSheet("QLabel {color: green;}"); + } + else{ + m_pui->label_StatusObject->setText("not loaded"); + m_pui->label_StatusObject->setStyleSheet("QLabel {color: black;}"); + } + } +} + +//============================================================================================================== + +void NeurofeedbackBSettingsView::onUpdateSpinBoxMin(int value) +{ + m_ibMin = value; + emit changeMin(m_ibMin); + saveSettings(m_sSettingsPath); +} + +//=============================================================================================================== + +void NeurofeedbackBSettingsView::clickedStdMax() +{ + onUpdateSpinBoxMax(25); + m_pui->spinBox_Max->setValue(25); +} + +//=============================================================================================================== + +void NeurofeedbackBSettingsView::clickedStdMin() +{ + onUpdateSpinBoxMin(0); + m_pui->spinBox_Min->setValue(0); +} diff --git a/libraries/disp/viewers/neurofeedbackbsettingsview.h b/libraries/disp/viewers/neurofeedbackbsettingsview.h new file mode 100644 index 00000000000..8ff8e4d2968 --- /dev/null +++ b/libraries/disp/viewers/neurofeedbackbsettingsview.h @@ -0,0 +1,234 @@ +//============================================================================================================= +/** + * @file neurofeedbackbsettingsview.h + * @author Simon Marxgut + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the NeurofeedbackBSettingsView Class. + * + */ + +#ifndef NEUROFEEDBACKBSETTINGSVIEW_H +#define NEUROFEEDBACKBSETTINGSVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class QSlider; +class QDoubleSpinBox; + + +namespace Ui { +class NeurofeedbackBSettingsViewWidget; +} + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// DISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * DECLARE CLASS NeurofeedbackBSettingsView + */ +class DISPSHARED_EXPORT NeurofeedbackBSettingsView : public QWidget +{ + Q_OBJECT + +public: + typedef QSharedPointer SPtr; /**< Shared pointer type for NeurofeedbackBSettingsView. */ + typedef QSharedPointer ConstSPtr; /**< Const shared pointer type for NeurofeedbackBSettingsView. */ + + //========================================================================================================= + /** + * Constructs a NeurofeedbackBSettingsView which is a child of parent. + * + * @param [in] parent parent of widget + */ + NeurofeedbackBSettingsView(const QString& sSettingsPath = "", + int ibMax = 25, + int ibMin = 0, + QWidget *parent = 0, + Qt::WindowFlags f = Qt::Widget); + + //========================================================================================================= + + ~NeurofeedbackBSettingsView(); + + //========================================================================================================= + /** + * Emits all settings once. + * + */ + void emitSignals(); + + +protected: + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + * + * @param[in] settingsPath the path to store the settings to. + */ + void saveSettings(const QString& settingsPath); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + * + * @param[in] settingsPath the path to load the settings from. + */ + void loadSettings(const QString& settingsPath); + + //========================================================================================================= + /** + * Slot is called when Load Button for Background is clicked + */ + void clickedLoadBackground(); + + //========================================================================================================= + /** + * Slot is called when Load Button for Objectimage is clicked + */ + void clickedLoadObject(); + + //========================================================================================================= + /** + * Slot is called when value in the Spinbox for maximum is changed + * + * @param[in] value maximum of frequency. + */ + void onUpdateSpinBoxMax(int value); + + //========================================================================================================= + /** + * Slot is called when value in the Spinbox for minimum is changed + * + * @param[in] value minimum of frequency. + */ + void onUpdateSpinBoxMin(int value); + + //========================================================================================================= + /** + * Slot is called when standard Button for maximum is clicked + */ + void clickedStdMax(); + + //========================================================================================================= + /** + * Slot is called when standard Button for minimum is clicked + */ + void clickedStdMin(); + + //========================================================================================================= + /** + * Slot is called when value in the Spinbox for the selected Channel is changed + * + * @param[in] value selected channel. + */ + void onUpdateSpinBoxChannel(int value); + + //========================================================================================================= + /** + * Slot is called when Reset Settings Button is clicked + */ + void clickedResetSettings(); + + //========================================================================================================= + /** + * Update all Settings on the NeurofeedbackBSettingsView Display. + */ + void updateDisplay(); + + //========================================================================================================= + /** + * Update the Status Label for the Background. + */ + void updateStatusBackground(); + + //========================================================================================================= + /** + * Update the Status Label for the Object. + */ + void updateStatusObject(); + + + + Ui::NeurofeedbackBSettingsViewWidget *m_pui; + + QString m_sSettingsPath; + QString m_sDirBackground; + QString m_sDirObject; + int m_ibMax; + int m_ibMin; + QPixmap m_imgBackground; + QPixmap m_imgObject; + + + + +signals: + //========================================================================================================= + /** + * Emitted whenever the settings changed and are ready to be retreived. + */ + void changeImgBackground(QPixmap ImgBackground); + void changeImgObject(QPixmap ImgObject); + void changeMax(int ibMax); + void changeMin(int ibMin); + + + +}; +} // NAMESPACE + +#endif // NEUROFEEDBACKBSETTINGSVIEW_H diff --git a/libraries/disp/viewers/neurofeedbackcsettingsview.cpp b/libraries/disp/viewers/neurofeedbackcsettingsview.cpp new file mode 100644 index 00000000000..a77274c6141 --- /dev/null +++ b/libraries/disp/viewers/neurofeedbackcsettingsview.cpp @@ -0,0 +1,970 @@ +//============================================================================================================= +/** + * @file neurofeedbackcsettingsview.cpp + * @author Simon Marxgut + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the NeurofeedbackCSettingsView Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "neurofeedbackcsettingsview.h" +#include "ui_neurofeedbackcsettingsview.h" + +#include "neurofeedbackfsettingsview.h" +#include "ui_neurofeedbackfsettingsview.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +NeurofeedbackCSettingsView::NeurofeedbackCSettingsView(const QString& sSettingsPath, const QString& sClass0, const QString& sClass1, const QString& sClass2, + const QString& sClass3, const QString& sClass4, int iClass0, int iClass1, + int iClass2, int iClass3, int iClass4, int iNumbofClass, bool bIsRunning, + QWidget *parent, Qt::WindowFlags f) +: QWidget(parent, f) +, m_pui(new Ui::NeurofeedbackCSettingsViewWidget) +, m_sSettingsPath(sSettingsPath) +, m_sClass0(sClass0) +, m_sClass1(sClass1) +, m_sClass2(sClass2) +, m_sClass3(sClass3) +, m_sClass4(sClass4) +, m_iClass0(iClass0) +, m_iClass1(iClass1) +, m_iClass2(iClass2) +, m_iClass3(iClass3) +, m_iClass4(iClass4) +, m_iNumbofClass(iNumbofClass) +, m_bIsRunning(bIsRunning) +{ + m_pui->setupUi(this); + + this->setWindowTitle("Neurofeedback Settings"); + this->setMinimumWidth(850); + this->setMaximumWidth(850); + + loadSettings(m_sSettingsPath); + + m_pui->spinBox_C0->setValue(m_iClass0); + m_pui->spinBox_C1->setValue(m_iClass1); + m_pui->spinBox_C2->setValue(m_iClass2); + m_pui->spinBox_C3->setValue(m_iClass3); + m_pui->spinBox_C4->setValue(m_iClass4); + + m_vSpinboxClass.push_back(m_pui->spinBox_C0); + m_vSpinboxClass.push_back(m_pui->spinBox_C1); + m_vSpinboxClass.push_back(m_pui->spinBox_C2); + m_vSpinboxClass.push_back(m_pui->spinBox_C3); + m_vSpinboxClass.push_back(m_pui->spinBox_C4); + + m_pui->lineEdit_Class0->setText(m_sClass0); + m_pui->lineEdit_Class1->setText(m_sClass1); + m_pui->lineEdit_Class2->setText(m_sClass2); + m_pui->lineEdit_Class3->setText(m_sClass3); + m_pui->lineEdit_Class4->setText(m_sClass4); + + QButtonGroup* buttonGroupC0 = new QButtonGroup(); + buttonGroupC0->addButton(m_pui->radioButton_C0b); + buttonGroupC0->addButton(m_pui->radioButton_C0g); + buttonGroupC0->setId(m_pui->radioButton_C0b,0); + buttonGroupC0->setId(m_pui->radioButton_C0g,1); + m_vRadioButtonClassb.push_back(m_pui->radioButton_C0b); + m_vRadioButtonClassg.push_back(m_pui->radioButton_C0g); + + QButtonGroup* buttonGroupC1 = new QButtonGroup(); + buttonGroupC1->addButton(m_pui->radioButton_C1b); + buttonGroupC1->addButton(m_pui->radioButton_C1g); + buttonGroupC1->setId(m_pui->radioButton_C1b,0); + buttonGroupC1->setId(m_pui->radioButton_C1g,1); + m_vRadioButtonClassb.push_back(m_pui->radioButton_C1b); + m_vRadioButtonClassg.push_back(m_pui->radioButton_C1g); + + QButtonGroup* buttonGroupC2 = new QButtonGroup(); + buttonGroupC2->addButton(m_pui->radioButton_C2b); + buttonGroupC2->addButton(m_pui->radioButton_C2g); + buttonGroupC2->setId(m_pui->radioButton_C2b,0); + buttonGroupC2->setId(m_pui->radioButton_C2g,1); + m_vRadioButtonClassb.push_back(m_pui->radioButton_C2b); + m_vRadioButtonClassg.push_back(m_pui->radioButton_C2g); + + QButtonGroup* buttonGroupC3 = new QButtonGroup(); + buttonGroupC3->addButton(m_pui->radioButton_C3b); + buttonGroupC3->addButton(m_pui->radioButton_C3g); + buttonGroupC3->setId(m_pui->radioButton_C3b,0); + buttonGroupC3->setId(m_pui->radioButton_C3g,1); + m_vRadioButtonClassb.push_back(m_pui->radioButton_C3b); + m_vRadioButtonClassg.push_back(m_pui->radioButton_C3g); + + QButtonGroup* buttonGroupC4 = new QButtonGroup(); + buttonGroupC4->addButton(m_pui->radioButton_C4b); + buttonGroupC4->addButton(m_pui->radioButton_C4g); + buttonGroupC4->setId(m_pui->radioButton_C4b,0); + buttonGroupC4->setId(m_pui->radioButton_C4g,1); + m_vRadioButtonClassb.push_back(m_pui->radioButton_C4b); + m_vRadioButtonClassg.push_back(m_pui->radioButton_C4g); + + m_vLineEditsClass.push_back(m_pui->lineEdit_Class0); + m_vLineEditsClass.push_back(m_pui->lineEdit_Class1); + m_vLineEditsClass.push_back(m_pui->lineEdit_Class2); + m_vLineEditsClass.push_back(m_pui->lineEdit_Class3); + m_vLineEditsClass.push_back(m_pui->lineEdit_Class4); + + m_vLabelClass.push_back(m_pui->label_Class0); + m_vLabelClass.push_back(m_pui->label_Class1); + m_vLabelClass.push_back(m_pui->label_Class2); + m_vLabelClass.push_back(m_pui->label_Class3); + m_vLabelClass.push_back(m_pui->label_Class4); + + m_pui->lineEdit_DirClass0->setReadOnly(true); + m_pui->lineEdit_DirClass1->setReadOnly(true); + m_pui->lineEdit_DirClass2->setReadOnly(true); + m_pui->lineEdit_DirClass3->setReadOnly(true); + m_pui->lineEdit_DirClass4->setReadOnly(true); + + m_vLabelStatusClass.push_back(m_pui->label_StatusClass0); + m_vLabelStatusClass.push_back(m_pui->label_StatusClass1); + m_vLabelStatusClass.push_back(m_pui->label_StatusClass2); + m_vLabelStatusClass.push_back(m_pui->label_StatusClass3); + m_vLabelStatusClass.push_back(m_pui->label_StatusClass4); + + m_vLabelImgClass.push_back(m_pui->label_imgClass0); + m_vLabelImgClass.push_back(m_pui->label_imgClass1); + m_vLabelImgClass.push_back(m_pui->label_imgClass2); + m_vLabelImgClass.push_back(m_pui->label_imgClass3); + m_vLabelImgClass.push_back(m_pui->label_imgClass4); + + m_vLineEditsDirClass.push_back(m_pui->lineEdit_DirClass0); + m_vLineEditsDirClass.push_back(m_pui->lineEdit_DirClass1); + m_vLineEditsDirClass.push_back(m_pui->lineEdit_DirClass2); + m_vLineEditsDirClass.push_back(m_pui->lineEdit_DirClass3); + m_vLineEditsDirClass.push_back(m_pui->lineEdit_DirClass4); + + m_vPushButtonsClass.push_back(m_pui->pushButton_Class0); + m_vPushButtonsClass.push_back(m_pui->pushButton_Class1); + m_vPushButtonsClass.push_back(m_pui->pushButton_Class2); + m_vPushButtonsClass.push_back(m_pui->pushButton_Class3); + m_vPushButtonsClass.push_back(m_pui->pushButton_Class4); + + m_vDeleteButtonsClass.push_back(m_pui->pushButton_DClass0); + m_vDeleteButtonsClass.push_back(m_pui->pushButton_DClass1); + m_vDeleteButtonsClass.push_back(m_pui->pushButton_DClass2); + m_vDeleteButtonsClass.push_back(m_pui->pushButton_DClass3); + m_vDeleteButtonsClass.push_back(m_pui->pushButton_DClass4); + + m_pui->spinBoxnC->setMinimum(2); + m_pui->spinBoxnC->setMaximum(5); + m_pui->spinBoxnC->setValue(m_iNumbofClass); + onUpdateSpinBoxNumbofClass(m_iNumbofClass); + + + connect(m_pui->spinBoxnC, static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackCSettingsView::onUpdateSpinBoxNumbofClass); + connect(m_pui->lineEdit_Class0, static_cast (&QLineEdit::textEdited), this, &NeurofeedbackCSettingsView::onUpdateLineEditClass0); + connect(m_pui->lineEdit_Class1, static_cast (&QLineEdit::textEdited), this, &NeurofeedbackCSettingsView::onUpdateLineEditClass1); + connect(m_pui->lineEdit_Class2, static_cast (&QLineEdit::textEdited), this, &NeurofeedbackCSettingsView::onUpdateLineEditClass2); + connect(m_pui->lineEdit_Class3, static_cast (&QLineEdit::textEdited), this, &NeurofeedbackCSettingsView::onUpdateLineEditClass3); + connect(m_pui->lineEdit_Class4, static_cast (&QLineEdit::textEdited), this, &NeurofeedbackCSettingsView::onUpdateLineEditClass4); + connect(buttonGroupC0, static_cast(&QButtonGroup::buttonClicked), this, &NeurofeedbackCSettingsView::onUpdateButtonGroupC0); + connect(buttonGroupC1, static_cast(&QButtonGroup::buttonClicked), this, &NeurofeedbackCSettingsView::onUpdateButtonGroupC1); + connect(buttonGroupC2, static_cast(&QButtonGroup::buttonClicked), this, &NeurofeedbackCSettingsView::onUpdateButtonGroupC2); + connect(buttonGroupC3, static_cast(&QButtonGroup::buttonClicked), this, &NeurofeedbackCSettingsView::onUpdateButtonGroupC3); + connect(buttonGroupC4, static_cast(&QButtonGroup::buttonClicked), this, &NeurofeedbackCSettingsView::onUpdateButtonGroupC4); + connect(m_pui->spinBox_C0, static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackCSettingsView::onUpdateSpinboxClass0); + connect(m_pui->spinBox_C1, static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackCSettingsView::onUpdateSpinboxClass1); + connect(m_pui->spinBox_C2, static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackCSettingsView::onUpdateSpinboxClass2); + connect(m_pui->spinBox_C3, static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackCSettingsView::onUpdateSpinboxClass3); + connect(m_pui->spinBox_C4, static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackCSettingsView::onUpdateSpinboxClass4); + connect(m_pui->pushButton_Class0, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedLoadButton0); + connect(m_pui->pushButton_Class1, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedLoadButton1); + connect(m_pui->pushButton_Class2, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedLoadButton2); + connect(m_pui->pushButton_Class3, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedLoadButton3); + connect(m_pui->pushButton_Class4, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedLoadButton4); + connect(m_pui->pushButton_DClass0, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedDeleteButton0); + connect(m_pui->pushButton_DClass1, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedDeleteButton1); + connect(m_pui->pushButton_DClass2, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedDeleteButton2); + connect(m_pui->pushButton_DClass3, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedDeleteButton3); + connect(m_pui->pushButton_DClass4, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedDeleteButton4); + connect(m_pui->pushButton_ResetSettings, &QPushButton::released, this, &NeurofeedbackCSettingsView::clickedResetSettings); + + updateDisplay(); +} +//============================================================================================================= + +NeurofeedbackCSettingsView::~NeurofeedbackCSettingsView() +{ + saveSettings(m_sSettingsPath); + delete m_pui; +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::saveSettings(const QString& settingsPath) +{ + if(settingsPath.isEmpty()) { + return; + } + + // Store Settings + QSettings settings; + + settings.setValue(settingsPath + QString("/numbofClass"), m_iNumbofClass); + settings.setValue(settingsPath + QString("/Class0"), m_sClass0); + settings.setValue(settingsPath + QString("/Class1"), m_sClass1); + settings.setValue(settingsPath + QString("/Class2"), m_sClass2); + settings.setValue(settingsPath + QString("/Class3"), m_sClass3); + settings.setValue(settingsPath + QString("/Class4"), m_sClass4); + settings.setValue(settingsPath + QString("/iClass0"), m_iClass0); + settings.setValue(settingsPath + QString("/iClass1"), m_iClass1); + settings.setValue(settingsPath + QString("/iClass2"), m_iClass2); + settings.setValue(settingsPath + QString("/iClass3"), m_iClass3); + settings.setValue(settingsPath + QString("/iClass4"), m_iClass4); + settings.setValue(settingsPath + QString("/sDirClass0"), m_sDirClass0); + settings.setValue(settingsPath + QString("/sDirClass1"), m_sDirClass1); + settings.setValue(settingsPath + QString("/sDirClass2"), m_sDirClass2); + settings.setValue(settingsPath + QString("/sDirClass3"), m_sDirClass3); + settings.setValue(settingsPath + QString("/sDirClass4"), m_sDirClass4); + settings.setValue(settingsPath + QString("/sColClass0"), m_sColClass0); + settings.setValue(settingsPath + QString("/sColClass1"), m_sColClass1); + settings.setValue(settingsPath + QString("/sColClass2"), m_sColClass2); + settings.setValue(settingsPath + QString("/sColClass3"), m_sColClass3); + settings.setValue(settingsPath + QString("/sColClass4"), m_sColClass4); + + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::loadSettings(const QString& settingsPath) +{ + if(settingsPath.isEmpty()) { + return; + } + + // Load Settings + QSettings settings; + + m_iNumbofClass = settings.value(settingsPath + QString("/numbofClass"), m_iNumbofClass).toInt(); + m_sClass0 = settings.value(settingsPath + QString("/Class0"), m_sClass0).toString(); + m_sClass1 = settings.value(settingsPath + QString("/Class1"), m_sClass1).toString(); + m_sClass2 = settings.value(settingsPath + QString("/Class2"), m_sClass2).toString(); + m_sClass3 = settings.value(settingsPath + QString("/Class3"), m_sClass3).toString(); + m_sClass4 = settings.value(settingsPath + QString("/Class4"), m_sClass4).toString(); + m_iClass0 = settings.value(settingsPath + QString("/iClass0"), m_iClass0).toInt(); + m_iClass1 = settings.value(settingsPath + QString("/iClass1"), m_iClass1).toInt(); + m_iClass2 = settings.value(settingsPath + QString("/iClass2"), m_iClass2).toInt(); + m_iClass3 = settings.value(settingsPath + QString("/iClass3"), m_iClass3).toInt(); + m_iClass4 = settings.value(settingsPath + QString("/iClass4"), m_iClass4).toInt(); + m_sDirClass0 = settings.value(settingsPath + QString("/sDirClass0"), m_sDirClass0).toString(); + m_sDirClass1 = settings.value(settingsPath + QString("/sDirClass1"), m_sDirClass1).toString(); + m_sDirClass2 = settings.value(settingsPath + QString("/sDirClass2"), m_sDirClass2).toString(); + m_sDirClass3 = settings.value(settingsPath + QString("/sDirClass3"), m_sDirClass3).toString(); + m_sDirClass4 = settings.value(settingsPath + QString("/sDirClass4"), m_sDirClass4).toString(); + m_sColClass0 = settings.value(settingsPath + QString("/sColClass0"), m_sColClass0).toString(); + m_sColClass1 = settings.value(settingsPath + QString("/sColClass1"), m_sColClass1).toString(); + m_sColClass2 = settings.value(settingsPath + QString("/sColClass2"), m_sColClass2).toString(); + m_sColClass3 = settings.value(settingsPath + QString("/sColClass3"), m_sColClass3).toString(); + m_sColClass4 = settings.value(settingsPath + QString("/sColClass4"), m_sColClass4).toString(); + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedResetSettings() +{ + m_iNumbofClass = 2; + + m_sClass0 = "Class0"; + m_sClass1 = "Class1"; + m_sClass2 = "Class2"; + m_sClass3 = "Class3"; + m_sClass4 = "Class4"; + + m_iClass0 = 0; + m_iClass1 = 1; + m_iClass2 = 2; + m_iClass3 = 3; + m_iClass4 = 4; + + m_sColClass0 = "black"; + m_sColClass1 = "black"; + m_sColClass2 = "black"; + m_sColClass3 = "black"; + m_sColClass4 = "black"; + + m_sDirClass0 = ""; + m_sDirClass1 = ""; + m_sDirClass2 = ""; + m_sDirClass3 = ""; + m_sDirClass4 = ""; + + + saveSettings(m_sSettingsPath); + emitSignals(); + updateDisplay(); + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::updateDisplay() +{ + onUpdateSpinBoxNumbofClass(m_iNumbofClass); + m_pui->spinBoxnC->setValue(m_iNumbofClass); + + m_pui->lineEdit_Class0->setText(m_sClass0); + m_pui->lineEdit_Class1->setText(m_sClass1); + m_pui->lineEdit_Class2->setText(m_sClass2); + m_pui->lineEdit_Class3->setText(m_sClass3); + m_pui->lineEdit_Class4->setText(m_sClass4); + + m_pui->spinBox_C0->setValue(m_iClass0); + m_pui->spinBox_C1->setValue(m_iClass1); + m_pui->spinBox_C2->setValue(m_iClass2); + m_pui->spinBox_C3->setValue(m_iClass3); + m_pui->spinBox_C4->setValue(m_iClass4); + + if(m_sColClass0 == "red"){ + onUpdateButtonGroupC0(0); + m_pui->radioButton_C0b->setChecked(true); + } + else if(m_sColClass0 == "green"){ + onUpdateButtonGroupC0(1); + m_pui->radioButton_C0g->setChecked(true); + } + else if(m_sColClass0 == "black"){ + + } + + if(m_sColClass1 == "red"){ + onUpdateButtonGroupC1(0); + m_pui->radioButton_C1b->setChecked(true); + } + else if(m_sColClass1 == "green"){ + onUpdateButtonGroupC1(1); + m_pui->radioButton_C1g->setChecked(true); + } + else if(m_sColClass1 == "black"){ + + } + + if(m_sColClass2 == "red"){ + onUpdateButtonGroupC2(0); + m_pui->radioButton_C2b->setChecked(true); + } + else if(m_sColClass2 == "green"){ + onUpdateButtonGroupC2(1); + m_pui->radioButton_C2g->setChecked(true); + } + else if(m_sColClass2 == "black"){ + + } + + if(m_sColClass3 == "red"){ + onUpdateButtonGroupC3(0); + m_pui->radioButton_C3b->setChecked(true); + } + else if(m_sColClass3 == "green"){ + onUpdateButtonGroupC3(1); + m_pui->radioButton_C3g->setChecked(true); + } + else if(m_sColClass3 == "black"){ + + } + + if(m_sColClass4 == "red"){ + onUpdateButtonGroupC4(0); + m_pui->radioButton_C4b->setChecked(true); + } + else if(m_sColClass4 == "green"){ + onUpdateButtonGroupC4(1); + m_pui->radioButton_C4g->setChecked(true); + } + else if(m_sColClass4 == "black"){ + + } + + updateImgClass0(); + updateImgClass1(); + updateImgClass2(); + updateImgClass3(); + updateImgClass4(); + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::emitSignals() +{ + emit changeNumbofClass(m_iNumbofClass); + emit changeClass0(m_sClass0); + emit changeClass1(m_sClass1); + emit changeClass2(m_sClass2); + emit changeClass3(m_sClass3); + emit changeClass4(m_sClass4); + emit changeiClass0(m_iClass0); + emit changeiClass1(m_iClass1); + emit changeiClass2(m_iClass2); + emit changeiClass3(m_iClass3); + emit changeiClass4(m_iClass4); + emit changeImgClass0(m_imgClass0); + emit changeImgClass1(m_imgClass1); + emit changeImgClass2(m_imgClass2); + emit changeImgClass3(m_imgClass3); + emit changeImgClass4(m_imgClass4); + emit changeButtonGroupC0(m_sColClass0); + emit changeButtonGroupC1(m_sColClass1); + emit changeButtonGroupC2(m_sColClass2); + emit changeButtonGroupC3(m_sColClass3); + emit changeButtonGroupC4(m_sColClass4); +} + +//============================================================================================================ + +void NeurofeedbackCSettingsView::onUpdateSpinBoxNumbofClass(int value){ + m_iNumbofClass = value; + emit changeNumbofClass(m_iNumbofClass); + + saveSettings(m_sSettingsPath); + + for(int i = 0; ishow(); + m_vLabelClass[i]->show(); + m_vSpinboxClass[i]->show(); + m_vLabelStatusClass[i]->show(); + m_vLineEditsDirClass[i]->show(); + m_vPushButtonsClass[i]->show(); + m_vRadioButtonClassb[i]->show(); + m_vRadioButtonClassg[i]->show(); + m_vDeleteButtonsClass[i]->show(); + m_vLabelImgClass[i]->show(); + } + else{ + m_vLineEditsClass[i]->hide(); + m_vLabelClass[i]->hide(); + m_vSpinboxClass[i]->hide(); + m_vLabelStatusClass[i]->hide(); + m_vLineEditsDirClass[i]->hide(); + m_vPushButtonsClass[i]->hide(); + m_vRadioButtonClassb[i]->hide(); + m_vRadioButtonClassg[i]->hide(); + m_vDeleteButtonsClass[i]->hide(); + m_vLabelImgClass[i]->hide(); + } + } +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateLineEditClass0() +{ + + m_sClass0 = m_pui->lineEdit_Class0->text(); + + emit changeClass0(m_sClass0); + + saveSettings(m_sSettingsPath); + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateLineEditClass1() +{ + + m_sClass1 = m_pui->lineEdit_Class1->text(); + + emit changeClass1(m_sClass1); + + saveSettings(m_sSettingsPath); + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateLineEditClass2() +{ + + m_sClass2 = m_pui->lineEdit_Class2->text(); + + emit changeClass2(m_sClass2); + + saveSettings(m_sSettingsPath); + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateLineEditClass3() +{ + + m_sClass3 = m_pui->lineEdit_Class3->text(); + + emit changeClass3(m_sClass3); + + saveSettings(m_sSettingsPath); + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateLineEditClass4() +{ + + m_sClass4 = m_pui->lineEdit_Class4->text(); + + emit changeClass4(m_sClass4); + + saveSettings(m_sSettingsPath); + +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateButtonGroupC0(int value) +{ + if(value==0){ + m_sColClass0 = "red"; + } + else if(value==1){ + m_sColClass0 = "green"; + } + emit changeButtonGroupC0(m_sColClass0); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateButtonGroupC1(int value) +{ + if(value==0){ + m_sColClass1 = "red"; + } + else if(value==1){ + m_sColClass1 = "green"; + } + emit changeButtonGroupC1(m_sColClass1); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateButtonGroupC2(int value) +{ + if(value==0){ + m_sColClass2 = "red"; + } + else if(value==1){ + m_sColClass2 = "green"; + } + emit changeButtonGroupC2(m_sColClass2); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateButtonGroupC3(int value) +{ + if(value==0){ + m_sColClass3 = "red"; + } + else if(value==1){ + m_sColClass3 = "green"; + } + emit changeButtonGroupC3(m_sColClass3); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateButtonGroupC4(int value) +{ + if(value==0){ + m_sColClass4 = "red"; + } + else if(value==1){ + m_sColClass4 = "green"; + } + emit changeButtonGroupC4(m_sColClass4); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateSpinboxClass0(int value) +{ + + m_iClass0 = value; + + emit changeiClass0(m_iClass0); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateSpinboxClass1(int value) +{ + + m_iClass1 = value; + + emit changeiClass1(m_iClass1); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateSpinboxClass2(int value) +{ + + m_iClass2 = value; + + emit changeiClass2(m_iClass2); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateSpinboxClass3(int value) +{ + + m_iClass3 = value; + + emit changeiClass3(m_iClass3); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::onUpdateSpinboxClass4(int value) +{ + + m_iClass4 = value; + + emit changeiClass4(m_iClass4); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedLoadButton0() +{ + m_sDirClass0 = QFileDialog::getOpenFileName(this, tr("Open File"), "/home", tr("Images (*.png *.xpm *.jpg)")); + m_pui->lineEdit_DirClass0->setEnabled(true); + updateImgClass0(); + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedLoadButton1() +{ + m_sDirClass1 = QFileDialog::getOpenFileName(this, tr("Open File"), "/home", tr("Images (*.png *.xpm *.jpg)")); + updateImgClass1(); + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedLoadButton2() +{ + m_sDirClass2 = QFileDialog::getOpenFileName(this, tr("Open File"), "/home", tr("Images (*.png *.xpm *.jpg)")); + updateImgClass2(); + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedLoadButton3() +{ + m_sDirClass3 = QFileDialog::getOpenFileName(this, tr("Open File"), "/home", tr("Images (*.png *.xpm *.jpg)")); + updateImgClass3(); + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedLoadButton4() +{ + m_sDirClass4 = QFileDialog::getOpenFileName(this, tr("Open File"), "/home", tr("Images (*.png *.xpm *.jpg)")); + updateImgClass4(); + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::updateImgClass0() +{ + m_pui->lineEdit_DirClass0->setText(m_sDirClass0); + if(m_sDirClass0.isEmpty()){ + clickedDeleteButton0(); + } + else { + QPixmap image(m_sDirClass0); + m_imgClass0 = image; + if(m_imgClass0.load(m_sDirClass0) == true){ + emit changeImgClass0(m_imgClass0); + m_pui->label_StatusClass0->setText("loaded"); + m_pui->label_StatusClass0->setStyleSheet("QLabel {color: green;}"); + m_pui->label_imgClass0->setPixmap(image.scaled(50, 50, Qt::KeepAspectRatio)); + m_pui->lineEdit_Class0->setEnabled(false); + m_pui->lineEdit_DirClass0->setEnabled(true); + } + else{ + m_pui->label_StatusClass0->setText("not loaded"); + m_pui->label_StatusClass0->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass0->setText(""); + } + } + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::updateImgClass1() +{ + m_pui->lineEdit_DirClass1->setText(m_sDirClass1); + if(m_sDirClass1.isEmpty()){ + clickedDeleteButton1(); + } + else { + QPixmap image(m_sDirClass1); + m_imgClass1 = image; + if(m_imgClass1.load(m_sDirClass1) == true){ + emit changeImgClass1(m_imgClass1); + m_pui->label_StatusClass1->setText("loaded"); + m_pui->label_StatusClass1->setStyleSheet("QLabel {color: green;}"); + m_pui->label_imgClass1->setPixmap(image.scaled(50, 50, Qt::KeepAspectRatio)); + m_pui->lineEdit_Class1->setEnabled(false); + m_pui->lineEdit_DirClass1->setEnabled(true); + } + else{ + m_pui->label_StatusClass1->setText("not loaded"); + m_pui->label_StatusClass1->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass1->setText(""); + } + } + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::updateImgClass2() +{ + m_pui->lineEdit_DirClass2->setText(m_sDirClass2); + if(m_sDirClass2.isEmpty()){ + clickedDeleteButton2(); + } + else { + QPixmap image(m_sDirClass2); + m_imgClass2 = image; + if(m_imgClass2.load(m_sDirClass2) == true){ + emit changeImgClass2(m_imgClass2); + m_pui->label_StatusClass2->setText("loaded"); + m_pui->label_StatusClass2->setStyleSheet("QLabel {color: green;}"); + m_pui->label_imgClass2->setPixmap(image.scaled(50, 50, Qt::KeepAspectRatio)); + m_pui->lineEdit_Class2->setEnabled(false); + m_pui->lineEdit_DirClass2->setEnabled(true); + } + else{ + m_pui->label_StatusClass2->setText("not loaded"); + m_pui->label_StatusClass2->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass2->setText(""); + } + } + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::updateImgClass3() +{ + m_pui->lineEdit_DirClass3->setText(m_sDirClass3); + if(m_sDirClass3.isEmpty()){ + clickedDeleteButton3(); + } + else { + QPixmap image(m_sDirClass3); + m_imgClass3 = image; + if(m_imgClass3.load(m_sDirClass3) == true){ + emit changeImgClass3(m_imgClass3); + m_pui->label_StatusClass3->setText("loaded"); + m_pui->label_StatusClass3->setStyleSheet("QLabel {color: green;}"); + m_pui->label_imgClass3->setPixmap(image.scaled(50, 50, Qt::KeepAspectRatio)); + m_pui->lineEdit_Class3->setEnabled(false); + m_pui->lineEdit_DirClass3->setEnabled(true); + } + else{ + m_pui->label_StatusClass3->setText("not loaded"); + m_pui->label_StatusClass3->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass3->setText(""); + } + } + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::updateImgClass4() +{ + m_pui->lineEdit_DirClass4->setText(m_sDirClass4); + if(m_sDirClass4.isEmpty()){ + clickedDeleteButton4(); + } + else { + QPixmap image(m_sDirClass4); + m_imgClass4 = image; + if(m_imgClass4.load(m_sDirClass4) == true){ + emit changeImgClass4(m_imgClass4); + m_pui->label_StatusClass4->setText("loaded"); + m_pui->label_StatusClass4->setStyleSheet("QLabel {color: green;}"); + m_pui->label_imgClass4->setPixmap(image.scaled(50, 50, Qt::KeepAspectRatio)); + m_pui->lineEdit_Class4->setEnabled(false); + m_pui->lineEdit_DirClass4->setEnabled(true); + } + else{ + m_pui->label_StatusClass4->setText("not loaded"); + m_pui->label_StatusClass4->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass4->setText(""); + } + } + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedDeleteButton0() +{ + m_pui->lineEdit_DirClass0->setText(""); + m_pui->lineEdit_DirClass0->setEnabled(false); + m_pui->label_StatusClass0->setText("not loaded"); + m_pui->label_StatusClass0->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass0->clear(); + m_imgClass0 = QPixmap(); + m_sDirClass0= ""; + m_pui->lineEdit_Class0->setEnabled(true); + emit changeImgClass0(m_imgClass0); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedDeleteButton1() +{ + m_pui->lineEdit_DirClass1->setText(""); + m_pui->lineEdit_DirClass1->setEnabled(false); + m_pui->label_StatusClass1->setText("not loaded"); + m_pui->label_StatusClass1->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass1->clear(); + m_imgClass1 = QPixmap(); + m_sDirClass1 = ""; + m_pui->lineEdit_Class1->setEnabled(true); + emit changeImgClass1(m_imgClass1); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedDeleteButton2() +{ + m_pui->lineEdit_DirClass2->setText(""); + m_pui->lineEdit_DirClass2->setEnabled(false); + m_pui->label_StatusClass2->setText("not loaded"); + m_pui->label_StatusClass2->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass2->clear(); + m_imgClass2 = QPixmap(); + m_sDirClass2 = ""; + m_pui->lineEdit_Class2->setEnabled(true); + emit changeImgClass2(m_imgClass2); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedDeleteButton3() +{ + m_pui->lineEdit_DirClass3->setText(""); + m_pui->lineEdit_DirClass3->setEnabled(false); + m_pui->label_StatusClass3->setText("not loaded"); + m_pui->label_StatusClass3->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass3->clear(); + m_imgClass3 = QPixmap(); + m_sDirClass3 = ""; + m_pui->lineEdit_Class3->setEnabled(true); + emit changeImgClass3(m_imgClass3); +} + +//============================================================================================================= + +void NeurofeedbackCSettingsView::clickedDeleteButton4() +{ + m_pui->lineEdit_DirClass4->setText(""); + m_pui->lineEdit_DirClass4->setEnabled(false); + m_pui->label_StatusClass4->setText("not loaded"); + m_pui->label_StatusClass4->setStyleSheet("QLabel {color: black;}"); + m_pui->label_imgClass4->clear(); + m_imgClass4 = QPixmap(); + m_sDirClass4 = ""; + m_pui->lineEdit_Class4->setEnabled(true); + emit changeImgClass4(m_imgClass4); +} diff --git a/libraries/disp/viewers/neurofeedbackcsettingsview.h b/libraries/disp/viewers/neurofeedbackcsettingsview.h new file mode 100644 index 00000000000..90805cf21f5 --- /dev/null +++ b/libraries/disp/viewers/neurofeedbackcsettingsview.h @@ -0,0 +1,441 @@ +//============================================================================================================= +/** + * @file neurofeedbackcsettingsview.h + * @author Simon Marxgut + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the NeurofeedbackCSettingsView Class. + * + */ + +#ifndef NEUROFEEDBACKCSETTINGSVIEW_H +#define NEUROFEEDBACKCSETTINGSVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class QSlider; +class QDoubleSpinBox; + + +namespace Ui { +class NeurofeedbackCSettingsViewWidget; +} + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// DISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * DECLARE CLASS NeurofeedbackCSettingsView + */ +class DISPSHARED_EXPORT NeurofeedbackCSettingsView : public QWidget +{ + Q_OBJECT + +public: + typedef QSharedPointer SPtr; /**< Shared pointer type for NeurofeedbackCSettingsView. */ + typedef QSharedPointer ConstSPtr; /**< Const shared pointer type for NeurofeedbackCSettingsView. */ + + //========================================================================================================= + /** + * Constructs a NeurofeedbackCSettingsView which is a child of parent. + * + * @param [in] parent parent of widget + */ + NeurofeedbackCSettingsView(const QString& sSettingsPath = "", + const QString& sClass0 = QString::fromStdString("Class0"), + const QString& sClass1 = QString::fromStdString("Class1"), + const QString& sClass2 = QString::fromStdString("Class2"), + const QString& sClass3 = QString::fromStdString("Class3"), + const QString& sClass4 = QString::fromStdString("Class4"), + int iClass0 = 0, + int iClass1 = 1, + int iClass2 = 2, + int iClass3 = 3, + int iClass4 = 4, + int iNumbofClass = 2, + bool bIsRunning = false, + QWidget *parent = 0, + Qt::WindowFlags f = Qt::Widget); + + //========================================================================================================= + + ~NeurofeedbackCSettingsView(); + + //========================================================================================================= + /** + * Emits all settings once. + * + */ + void emitSignals(); + + +protected: + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + * + * @param[in] settingsPath the path to store the settings to. + */ + void saveSettings(const QString& settingsPath); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + * + * @param[in] settingsPath the path to load the settings from. + */ + void loadSettings(const QString& settingsPath); + + //========================================================================================================= + /** + * Slot called when number of classifications spin box changes + * + * @param[in] value number of classifications. + */ + void onUpdateSpinBoxNumbofClass(int value); + + //========================================================================================================= + /** + * Slot called when Class0 line edit changes + */ + void onUpdateLineEditClass0(); + + //========================================================================================================= + /** + * Slot called when Class1 line edit changes + */ + void onUpdateLineEditClass1(); + + //========================================================================================================= + /** + * Slot called when Class2 line edit changes + */ + void onUpdateLineEditClass2(); + + //========================================================================================================= + /** + * Slot called when Class3 line edit changes + */ + void onUpdateLineEditClass3(); + + //========================================================================================================= + /** + * Slot called when Class4 line edit changes + */ + void onUpdateLineEditClass4(); + + //========================================================================================================= + /** + * Slot called when Class0 spin box changes + * + * @param[in] value Integer Class0. + */ + void onUpdateSpinboxClass0(int value); + + //========================================================================================================= + /** + * Slot called when Class1 spin box changes + * + * @param[in] value Integer Class0. + */ + void onUpdateSpinboxClass1(int value); + + //========================================================================================================= + /** + * Slot called when Class2 spin box changes + * + * @param[in] value Integer Class0. + */ + void onUpdateSpinboxClass2(int value); + + //========================================================================================================= + /** + * Slot called when Class3 spin box changes + * + * @param[in] value Integer Class0. + */ + void onUpdateSpinboxClass3(int value); + + //========================================================================================================= + /** + * Slot called when Class4 spin box changes + * + * @param[in] value Integer Class0. + */ + void onUpdateSpinboxClass4(int value); + + //========================================================================================================= + /** + * Slot called when Class0 Button Group changes + * + * @param[in] value Integer for Color Class0. + */ + void onUpdateButtonGroupC0(int value); + + //========================================================================================================= + /** + * Slot called when Class1 Button Group changes + * + * @param[in] value Integer for Color Class0. + */ + void onUpdateButtonGroupC1(int value); + + //========================================================================================================= + /** + * Slot called when Class2 Button Group changes + * + * @param[in] value Integer for Color Class0. + */ + void onUpdateButtonGroupC2(int value); + + //========================================================================================================= + /** + * Slot called when Class3 Button Group changes + * + * @param[in] value Integer for Color Class0. + */ + void onUpdateButtonGroupC3(int value); + + //========================================================================================================= + /** + * Slot called when Class4 Button Group changes + * + * @param[in] value Integer for Color Class0. + */ + void onUpdateButtonGroupC4(int value); + + //========================================================================================================= + /** + * Slot is called when Load Button for Classification 0 is clicked + */ + void clickedLoadButton0(); + + //========================================================================================================= + /** + * Slot is called when Load Button for Classification 1 is clicked + */ + void clickedLoadButton1(); + + //========================================================================================================= + /** + * Slot is called when Load Button for Classification 2 is clicked + */ + void clickedLoadButton2(); + + //========================================================================================================= + /** + * Slot is called when Load Button for Classification 3 is clicked + */ + void clickedLoadButton3(); + + //========================================================================================================= + /** + * Slot is called when Load Button for Classification 4 is clicked + */ + void clickedLoadButton4(); + + //========================================================================================================= + /** + * Slot is called when Delete Button for Classification 0 is clicked + */ + void clickedDeleteButton0(); + + //========================================================================================================= + /** + * Slot is called when Delete Button for Classification 1 is clicked + */ + void clickedDeleteButton1(); + + //========================================================================================================= + /** + * Slot is called when Delete Button for Classification 2 is clicked + */ + void clickedDeleteButton2(); + + //========================================================================================================= + /** + * Slot is called when Delete Button for Classification 3 is clicked + */ + void clickedDeleteButton3(); + + //========================================================================================================= + /** + * Slot is called when Delete Button for Classification 4 is clicked + */ + void clickedDeleteButton4(); + + //========================================================================================================= + /** + * Slot is called when Reset Settings Button is clicked + */ + void clickedResetSettings(); + + //========================================================================================================= + /** + * Update all Settings on the NeurofeedbackCSettingsView Display. + */ + void updateDisplay(); + + //========================================================================================================= + /** + * Update the Image for Classification 0. + */ + void updateImgClass0(); + + //========================================================================================================= + /** + * Update the Image for Classification 1. + */ + void updateImgClass1(); + + //========================================================================================================= + /** + * Update the Image for Classification 2. + */ + void updateImgClass2(); + + //========================================================================================================= + /** + * Update the Image for Classification 3. + */ + void updateImgClass3(); + + //========================================================================================================= + /** + * Update the Image for Classification 4. + */ + void updateImgClass4(); + + + Ui::NeurofeedbackCSettingsViewWidget *m_pui; + + QString m_sSettingsPath; + QString m_sClass0; + QString m_sClass1; + QString m_sClass2; + QString m_sClass3; + QString m_sClass4; + QString m_sDirClass0; + QString m_sDirClass1; + QString m_sDirClass2; + QString m_sDirClass3; + QString m_sDirClass4; + QString m_sColClass0; + QString m_sColClass1; + QString m_sColClass2; + QString m_sColClass3; + QString m_sColClass4; + + int m_iClass0; + int m_iClass1; + int m_iClass2; + int m_iClass3; + int m_iClass4; + int m_iNumbofClass; + + bool m_bIsRunning; + + QPixmap m_imgClass0; + QPixmap m_imgClass1; + QPixmap m_imgClass2; + QPixmap m_imgClass3; + QPixmap m_imgClass4; + + QVector m_vintClass; + QVector m_vLineEditsClass; + QVector m_vLabelClass; + QVector m_vSpinboxClass; + QVector m_vLineEditsDirClass; + QVector m_vPushButtonsClass; + QVector m_vLabelStatusClass; + QVector m_vLabelImgClass; + QVector m_vRadioButtonClassg; + QVector m_vRadioButtonClassb; + QVector m_vDeleteButtonsClass; + + +signals: + //========================================================================================================= + /** + * Emitted whenever the settings changed and are ready to be retreived. + */ + + void changeNumbofClass(int value); + void changeClass0(const QString& sClass0); + void changeClass1(const QString& sClass1); + void changeClass2(const QString& sClass2); + void changeClass3(const QString& sClass3); + void changeClass4(const QString& sClass4); + void changeButtonGroupC0(const QString& sBGC0); + void changeButtonGroupC1(const QString& sBGC1); + void changeButtonGroupC2(const QString& sBGC2); + void changeButtonGroupC3(const QString& sBGC3); + void changeButtonGroupC4(const QString& sBGC4); + void changeiClass0(int value); + void changeiClass1(int value); + void changeiClass2(int value); + void changeiClass3(int value); + void changeiClass4(int value); + void changeImgClass0(QPixmap imgClass0); + void changeImgClass1(QPixmap imgClass1); + void changeImgClass2(QPixmap imgClass2); + void changeImgClass3(QPixmap imgClass3); + void changeImgClass4(QPixmap imgClass4); + +}; +} // NAMESPACE + +#endif // NEUROFEEDBACKCSETTINGSVIEW_H diff --git a/libraries/disp/viewers/neurofeedbackfsettingsview.cpp b/libraries/disp/viewers/neurofeedbackfsettingsview.cpp new file mode 100644 index 00000000000..39f65097973 --- /dev/null +++ b/libraries/disp/viewers/neurofeedbackfsettingsview.cpp @@ -0,0 +1,340 @@ +//============================================================================================================= +/** + * @file neurofeedbackfsettingsview.cpp + * @author Simon Marxgut + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the NeurofeedbackFSettingsView Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "neurofeedbackfsettingsview.h" +#include "ui_neurofeedbackfsettingsview.h" + +#include "neurofeedbackcsettingsview.h" +#include "ui_neurofeedbackcsettingsview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include +#include + +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +NeurofeedbackFSettingsView::NeurofeedbackFSettingsView(const QString& sSettingsPath, int iSliders, int iMin, int iMax, bool ballCh, bool bIsRunning, + QWidget *parent, Qt::WindowFlags f) +: QWidget(parent, f) +, m_pui(new Ui::NeurofeedbackFSettingsViewWidget) +, m_sSettingsPath(sSettingsPath) +, m_iSliders(iSliders) +, m_iMin(iMin) +, m_iMax(iMax) +, m_ballCh(ballCh) +, m_bIsRunning(bIsRunning) +{ + m_pui->setupUi(this); + + this->setWindowTitle("Neurofeedback Settings"); + this->setMinimumWidth(450); + this->setMaximumWidth(450); + + loadSettings(m_sSettingsPath); + + m_pui->spinBox_slider->setMinimum(1); + m_pui->spinBox_slider->setMaximum(5); + m_pui->spinBox_slider->setValue(m_iSliders); + onUpdateSpinBoxSlider(m_iSliders); + + if(m_bMaxAutoScale == true){ + m_pui->checkBox_maxautoscale->setChecked(true); + onUpdateCheckboxMaxAutoScale(2); + } + else{ + m_pui->checkBox_maxautoscale->setChecked(false); + onUpdateCheckboxMaxAutoScale(1); + } + + if(m_bMinAutoScale == true){ + m_pui->checkBox_minautoscale->setChecked(true); + onUpdateCheckboxMinAutoScale(2); + } + else{ + m_pui->checkBox_minautoscale->setChecked(false); + onUpdateCheckboxMinAutoScale(1); + } + + + connect(m_pui->spinBox_slider,static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackFSettingsView::onUpdateSpinBoxSlider); + connect(m_pui->checkBox_allCh, static_cast(&QCheckBox::stateChanged), this, &NeurofeedbackFSettingsView::onUpdateCheckboxallCh); + connect(m_pui->spinBox_Max,static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackFSettingsView::onUpdateSpinBoxMax); + connect(m_pui->spinBox_Min,static_cast(&QSpinBox::valueChanged), this, &NeurofeedbackFSettingsView::onUpdateSpinBoxMin); + connect(m_pui->pushButton_Max, &QPushButton::released, this, &NeurofeedbackFSettingsView::clickedStandardMax); + connect(m_pui->pushButton_Min, &QPushButton::released, this, &NeurofeedbackFSettingsView::clickedStandardMin); + connect(m_pui->pushButton_ResetSettings, &QPushButton::released, this, &NeurofeedbackFSettingsView::clickedResetSettings); + connect(m_pui->checkBox_minautoscale, static_cast(&QCheckBox::stateChanged), this, &NeurofeedbackFSettingsView::onUpdateCheckboxMinAutoScale); + connect(m_pui->checkBox_maxautoscale, static_cast(&QCheckBox::stateChanged), this, &NeurofeedbackFSettingsView::onUpdateCheckboxMaxAutoScale); + + updateDisplay(); + +} +//============================================================================================================= + +NeurofeedbackFSettingsView::~NeurofeedbackFSettingsView() +{ + saveSettings(m_sSettingsPath); + + delete m_pui; +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::saveSettings(const QString& settingsPath) +{ + if(settingsPath.isEmpty()) { + return; + } + + // Store Settings + QSettings settings; + + settings.setValue(settingsPath + QString("/allCh"), m_ballCh); + settings.setValue(settingsPath + QString("/iSliders"), m_iSliders); + settings.setValue(settingsPath + QString("/FMax"), m_iMax); + settings.setValue(settingsPath + QString("/FMin"), m_iMin); + settings.setValue(settingsPath + QString("/FMinAS"), m_bMinAutoScale); + settings.setValue(settingsPath + QString("/FMaxAS"), m_bMaxAutoScale); + + updateDisplay(); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::loadSettings(const QString& settingsPath) +{ + if(settingsPath.isEmpty()) { + return; + } + + // Load Settings + QSettings settings; + + m_ballCh = settings.value(settingsPath + QString("/allCh"), m_ballCh).toBool(); + m_iSliders = settings.value(settingsPath + QString("/iSliders"), m_iSliders).toInt(); + m_iMax = settings.value(settingsPath + QString("/FMax"), m_iMax).toInt(); + m_iMin = settings.value(settingsPath + QString("/FMin"), m_iMin).toInt(); + m_bMinAutoScale = settings.value(settingsPath + QString("/FMinAS"), m_bMinAutoScale).toBool(); + m_bMaxAutoScale = settings.value(settingsPath + QString("/FMaxAS"), m_bMaxAutoScale).toBool(); + + + updateDisplay(); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::emitSignals() +{ + emit changeSliders(m_iSliders); + emit changeballCh(m_ballCh); + emit changeMax(m_iMax); + emit changeMin(m_iMin); + emit changeMinAutoScale(m_bMinAutoScale); + emit changeMaxAutoScale(m_bMaxAutoScale); + emit changeResetAutoScale(true); +} + + +//============================================================================================================= + +void NeurofeedbackFSettingsView::clickedResetSettings() +{ + m_iMax = 25; + m_iMin = 0; + m_iSliders = 2; + m_ballCh = true; + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::updateDisplay() +{ + + + if(m_ballCh == true){ + m_pui->checkBox_allCh->setChecked(true); + m_pui->spinBox_slider->setEnabled(false); + } + else if(m_ballCh == false){ + m_pui->spinBox_slider->setValue(m_iSliders); + m_pui->checkBox_allCh->setChecked(false); + m_pui->spinBox_slider->setEnabled(true); + } + + +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::onUpdateCheckboxallCh(int value) +{ + if(value == 2){ + m_ballCh = true; + } + else { + m_ballCh = false; + } + + emit changeballCh(m_ballCh); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::onUpdateCheckboxMaxAutoScale(int value) +{ + if(value == 2){ + m_bMaxAutoScale = true; + m_pui->spinBox_Max->setDisabled(true); + m_pui->pushButton_Max->setDisabled(true); + emit changeResetAutoScale(true); + } + else { + m_bMaxAutoScale = false; + m_pui->spinBox_Max->setEnabled(true); + m_pui->pushButton_Max->setEnabled(true); + emit changeResetAutoScale(false); + } + + emit changeMaxAutoScale(m_bMaxAutoScale); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::onUpdateCheckboxMinAutoScale(int value) +{ + if(value == 2){ + m_bMinAutoScale = true; + m_pui->spinBox_Min->setDisabled(true); + m_pui->pushButton_Min->setDisabled(true); + emit changeResetAutoScale(true); + } + else { + m_bMinAutoScale = false; + m_pui->spinBox_Min->setEnabled(true); + m_pui->pushButton_Min->setEnabled(true); + emit changeResetAutoScale(false); + } + + emit changeMinAutoScale(m_bMinAutoScale); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::onUpdateSpinBoxSlider(int value) +{ + m_iSliders = value; + + emit changeSliders(m_iSliders); + + saveSettings(m_sSettingsPath); + onUpdateCheckboxallCh(0); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::onUpdateSpinBoxMax(int value) +{ + m_iMax = value; + + emit changeMax(m_iMax); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::onUpdateSpinBoxMin(int value) +{ + m_iMin = value; + + emit changeMax(m_iMin); + + saveSettings(m_sSettingsPath); +} + +//============================================================================================================= + +void NeurofeedbackFSettingsView::clickedStandardMax() +{ + onUpdateSpinBoxMax(25); + m_pui->spinBox_Max->setValue(25); + updateDisplay(); +} + + +//============================================================================================================= + +void NeurofeedbackFSettingsView::clickedStandardMin() +{ + onUpdateSpinBoxMin(0); + m_pui->spinBox_Min->setValue(0); + updateDisplay(); +} + +//============================================================================================================= + + + diff --git a/libraries/disp/viewers/neurofeedbackfsettingsview.h b/libraries/disp/viewers/neurofeedbackfsettingsview.h new file mode 100644 index 00000000000..e2985ecbc26 --- /dev/null +++ b/libraries/disp/viewers/neurofeedbackfsettingsview.h @@ -0,0 +1,235 @@ +//============================================================================================================= +/** + * @file neurofeedbackfsettingsview.h + * @author Simon Marxgut + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the NeurofeedbackFSettingsView Class. + * + */ + +#ifndef NEUROFEEDBACKFSETTINGSVIEW_H +#define NEUROFEEDBACKFSETTINGSVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class QSlider; +class QDoubleSpinBox; + +namespace Ui { +class NeurofeedbackFSettingsViewWidget; +} + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// DISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * DECLARE CLASS NeurofeedbackCSettingsView + */ +class DISPSHARED_EXPORT NeurofeedbackFSettingsView : public QWidget +{ + Q_OBJECT + +public: + typedef QSharedPointer SPtr; /**< Shared pointer type for NeurofeedbackCSettingsView. */ + typedef QSharedPointer ConstSPtr; /**< Const shared pointer type for NeurofeedbackCSettingsView. */ + + //========================================================================================================= + /** + * Constructs a NeurofeedbackCSettingsView which is a child of parent. + * + * @param [in] parent parent of widget + */ + NeurofeedbackFSettingsView(const QString& sSettingsPath = "", + int iSliders = 3, + int iMin = 0, + int iMax = 25, + bool ballCh = true, + bool bIsRunning = false, + QWidget *parent = 0, + Qt::WindowFlags f = Qt::Widget); + + //========================================================================================================= + + ~NeurofeedbackFSettingsView(); + + //========================================================================================================= + /** + * Emits all settings once. + * + */ + void emitSignals(); + +protected: + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + * + * @param[in] settingsPath the path to store the settings to. + */ + void saveSettings(const QString& settingsPath); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + * + * @param[in] settingsPath the path to load the settings from. + */ + void loadSettings(const QString& settingsPath); + + //========================================================================================================= + + /** + * Slot called when checkbox change + */ + void onUpdateCheckboxallCh(int value); + + //========================================================================================================= + + /** + * Slot called when checkbox change + */ + void onUpdateCheckboxMinAutoScale(int value); + + //========================================================================================================= + + /** + * Slot called when checkbox change + */ + void onUpdateCheckboxMaxAutoScale(int value); + + //========================================================================================================= + /** + * Slot called when number of slider spin box changes + * + * @param[in] value number of sliders. + */ + void onUpdateSpinBoxSlider(int value); + + + //========================================================================================================= + /** + * Slot is called when standard button for minimum is clicked + */ + void clickedStandardMin(); + + //========================================================================================================= + /** + * Slot is called when standard button for maximum is clicked + */ + void clickedStandardMax(); + + //========================================================================================================= + /** + * Slot is called when value in the Spinbox for maximum is changed + * + * @param[in] value minimum of frequency. + */ + void onUpdateSpinBoxMin(int value); + + //========================================================================================================= + /** + * Slot is called when value in the Spinbox for maximum is changed + * + * @param[in] value maximum of frequency. + */ + void onUpdateSpinBoxMax(int value); + + //========================================================================================================= + /** + * Update all Settings on the NeurofeedbackFSettingsView Display. + */ + void updateDisplay(); + + //========================================================================================================= + /** + * Slot is called when Reset Settings Button is clicket. + */ + void clickedResetSettings(); + + + Ui::NeurofeedbackFSettingsViewWidget *m_pui; + + QString m_sSettingsPath; + + + int m_iSliders; + int m_iMin; + int m_iMax; + + + bool m_ballCh; + bool m_bMinAutoScale; + bool m_bMaxAutoScale; + bool m_bIsRunning; + + +signals: + //========================================================================================================= + /** + * Emitted whenever the settings changed and are ready to be retreived. + */ + void changeSliders(int value); + void changeballCh(bool ballCh); + void changeMin(int value); + void changeMax(int value); + void changeMinAutoScale(bool MinAutoScale); + void changeMaxAutoScale(bool MaxAutoScale); + void changeResetAutoScale(bool ResetAutoscale); + + +}; +} // NAMESPACE + +#endif // NEUROFEEDBACKCSETTINGSVIEW_H diff --git a/libraries/disp/viewers/neurofeedbacksettingsview.cpp b/libraries/disp/viewers/neurofeedbacksettingsview.cpp new file mode 100644 index 00000000000..605e7bf6de1 --- /dev/null +++ b/libraries/disp/viewers/neurofeedbacksettingsview.cpp @@ -0,0 +1,297 @@ +//============================================================================================================= +/** + * @file neurofeedbacksettingsview.cpp + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the NeurofeedbackSettingsView Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "neurofeedbacksettingsview.h" + +#include "ui_neurofeedbacksettingsview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +NeurofeedbackSettingsView::NeurofeedbackSettingsView(const QString& sSettingsPath, + int iMin, + int iMax, + bool bMinAutoScale, + bool bMaxAutoScale, + QWidget *parent, + Qt::WindowFlags f) +: AbstractView(parent, f) +, m_pUi(new Ui::NeurofeedbackSettingsViewWidget) +, m_sSettingsPath(sSettingsPath) +, m_iMin(iMin) +, m_iMax(iMax) +, m_bMinAutoScale(bMinAutoScale) +, m_bMaxAutoScale(bMaxAutoScale) +{ + + m_pUi->setupUi(this); + + +// loadSettings(); + + connect(m_pUi->m_spinbox_min, static_cast(&QSpinBox::valueChanged), + this, &NeurofeedbackSettingsView::onMinChanged); + + connect(m_pUi->m_spinbox_max, static_cast(&QSpinBox::valueChanged), + this, &NeurofeedbackSettingsView::onMaxChanged); + + connect(m_pUi->checkBox_MaxAutoScale, static_cast(&QCheckBox::stateChanged), this, &NeurofeedbackSettingsView::onMaxAutoScaleChanged); + + connect(m_pUi->checkBox_MinAutoScale, static_cast(&QCheckBox::stateChanged), this, &NeurofeedbackSettingsView::onMinAutoScaleChanged); + + + connect(m_pUi->pushButton_ResetAutoScale, &QPushButton::released, this, &NeurofeedbackSettingsView::ResetAutoScaleClicked); + + + m_pUi->m_spinbox_min->setValue(m_iMin); + m_pUi->m_spinbox_max->setValue(m_iMax); + if(m_bMaxAutoScale == true){ + m_pUi->checkBox_MaxAutoScale->setChecked(true); + } + else{ + m_pUi->checkBox_MaxAutoScale->setChecked(false); + } + + if(m_bMinAutoScale == true){ + m_pUi->checkBox_MinAutoScale->setChecked(true); + } + else{ + m_pUi->checkBox_MinAutoScale->setChecked(false); + } + + this->setWindowTitle("Neurofeedback Settings"); + this->setMinimumWidth(330); + this->setMaximumWidth(330); +} + +//============================================================================================================= + +NeurofeedbackSettingsView::~NeurofeedbackSettingsView() +{ + saveSettings(); + + delete m_pUi; +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::saveSettings() +{ +// if(m_sSettingsPath.isEmpty()) { +// return; +// } + +// QSettings settings("MNECPP"); + + +// settings.setValue(m_sSettingsPath + QString("/iMax"), m_iMax); +// settings.setValue(m_sSettingsPath + QString("/iMin"), m_iMin); +// settings.setValue(m_sSettingsPath + QString("/bMaxAutoScale"), m_bMaxAutoScale); +// settings.setValue(m_sSettingsPath + QString("/bMinAutoScale"), m_bMinAutoScale); + + +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::loadSettings() +{ +// if(m_sSettingsPath.isEmpty()) { +// return; +// } + +// QSettings settings("MNECPP"); + +// m_iMax = settings.value(m_sSettingsPath + QString("/iMax"), m_iMax).toInt(); +// m_iMin = settings.value(m_sSettingsPath + QString("/iMin"), m_iMin).toInt(); +// m_bMaxAutoScale = settings.value(m_sSettingsPath + QString("/bMaxAutoScale"), m_bMaxAutoScale).toBool(); +// m_bMinAutoScale = settings.value(m_sSettingsPath + QString("/bMinAutoScale"), m_bMinAutoScale).toBool(); + + + +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::updateGuiMode(GuiMode mode) +{ + switch(mode) { + case GuiMode::Clinical: + break; + default: // default is research mode + break; + } +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::updateProcessingMode(ProcessingMode mode) +{ + switch(mode) { + case ProcessingMode::Offline: + break; + default: // default is realtime mode + break; + } +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::onMetricChanged(const QString& sMetric) +{ + emit NeurofeedbackMetricChanged(sMetric); + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::onWindowTypeChanged(const QString& sWindowType) +{ + emit windowTypeChanged(sWindowType); + saveSettings(); +} + + + +//============================================================================================================= + +void NeurofeedbackSettingsView::onTriggerTypeChanged(const QString& sTriggerType) +{ + emit triggerTypeChanged(sTriggerType); + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::onMaxChanged() +{ + m_iMax = m_pUi->m_spinbox_max->value(); + emit MaxChanged(m_iMax); + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::onMinChanged() +{ + m_iMin = m_pUi->m_spinbox_min->value(); + emit MinChanged(m_iMin); + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::ResetAutoScaleClicked() +{ + emit ResetAutoScaleChanged(true); + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::onMaxAutoScaleChanged(int value) +{ + if(value == 2){ + m_bMaxAutoScale = true; + emit MaxAutoScaleChanged(m_bMaxAutoScale); + emit ResetAutoScaleChanged(true); + } + else{ + m_bMaxAutoScale = false; + emit MaxAutoScaleChanged(m_bMaxAutoScale); + } + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::onMinAutoScaleChanged(int value) +{ + if(value == 2){ + m_bMinAutoScale = true; + emit MinAutoScaleChanged(m_bMinAutoScale); + emit ResetAutoScaleChanged(true); + } + else{ + m_bMinAutoScale = false; + emit MinAutoScaleChanged(m_bMinAutoScale); + } + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::changeMax(int value) +{ + m_iMax = value; + m_pUi->m_spinbox_max->setValue(m_iMax); + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::changeMin(int value) +{ + m_iMin = value; + m_pUi->m_spinbox_min->setValue(m_iMin); + saveSettings(); +} + +//============================================================================================================= + +void NeurofeedbackSettingsView::clearView() +{ + +} diff --git a/libraries/disp/viewers/neurofeedbacksettingsview.h b/libraries/disp/viewers/neurofeedbacksettingsview.h new file mode 100644 index 00000000000..459ed3c41ab --- /dev/null +++ b/libraries/disp/viewers/neurofeedbacksettingsview.h @@ -0,0 +1,375 @@ +//============================================================================================================= +/** + * @file neurofeedbacksettinsview.h + * @author Simon Marxgut + * @since 0.1.0 + * @date November, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Simon Marxgut. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the NeurofeedbackSettingsView Class. + * + */ + +#ifndef NEUROFEEDBACKSETTINGSVIEW_H +#define NEUROFEEDBACKSETTINGSVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace Ui { + class NeurofeedbackSettingsViewWidget; +} + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// DISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * DECLARE CLASS NeurofeedbackSettingsView + * + * @brief The NeurofeedbackSettingsView class provides a view to control settings for estiamting functional Neurofeedback + */ +class DISPSHARED_EXPORT NeurofeedbackSettingsView : public AbstractView +{ + Q_OBJECT + +public: + typedef QSharedPointer SPtr; /**< Shared pointer type for NeurofeedbackSettingsView. */ + typedef QSharedPointer ConstSPtr; /**< Const shared pointer type for NeurofeedbackSettingsView. */ + + //========================================================================================================= + /** + * Constructs a NeurofeedbackSettingsView which is a child of parent. + * + * @param [in] parent parent of widget. + */ + NeurofeedbackSettingsView(const QString& sSettingsPath = "", + int iMin = 0, + int iMax = 10, + bool bMinAutoScale = false, + bool bMaxAutoScale = false, + QWidget *parent = 0, + Qt::WindowFlags f = Qt::Widget); + + //========================================================================================================= + /** + * Destroys the NeurofeedbackSettingsView. + */ + ~NeurofeedbackSettingsView(); + + //========================================================================================================= + /** + * Destroys the NeurofeedbackSettingsView. + * + * @param [in] lTriggerTypes The new trigger types. + */ + void setTriggerTypes(const QStringList& lTriggerTypes); + + //========================================================================================================= + /** + * Sets the new number of trials. + * + * @param [in] iNumberTrials The new number of trials. + */ + void setNumberTrials(int iNumberTrials); + + //========================================================================================================= + /** + * Get the current Neurofeedback metric. + * + * @return The current Neurofeedback metric. + */ + QString getNeurofeedbackMetric(); + + //========================================================================================================= + /** + * Get the current window type. + * + * @return The current window type. + */ + QString getWindowType(); + + //========================================================================================================= + /** + * Get the current number of trials. + * + * @return The current number of trials. + */ + int getNumberTrials(); + + //========================================================================================================= + /** + * Get the current trigger type. + * + * @return The current trigger type. + */ + QString getTriggerType(); + + //========================================================================================================= + /** + * Get the current lower frequency range. + * + * @return The current lower frequency range. + */ + double getLowerFreq(); + + //========================================================================================================= + /** + * Get the current upper frequency range. + * + * @return The current upper frequency range. + */ + double getUpperFreq(); + + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + */ + void saveSettings(); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Clears the view + */ + void clearView(); + + void changeMax(int value); + + void changeMin(int value); + +protected: + //========================================================================================================= + /** + * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). + * + * @param mode The new mode (Clinical=0, Research=1). + */ + void updateGuiMode(GuiMode mode); + + //========================================================================================================= + /** + * Update the views GUI based on the set ProcessingMode (RealTime=0, Offline=1). + * + * @param mode The new mode (RealTime=0, Offline=1). + */ + void updateProcessingMode(ProcessingMode mode); + + //========================================================================================================= + /** + * Slot called when the metric changed. + * + * @param [in] sMetric The new metric. + */ + void onMetricChanged(const QString& sMetric); + + //========================================================================================================= + /** + * Slot called when the window type changed. + * + * @param [in] sWindowType The new window type. + */ + void onWindowTypeChanged(const QString& sWindowType); + + //========================================================================================================= + /** + * Slot called when the number of trials changed. + */ + void onNumberTrialsChanged(); + + //========================================================================================================= + /** + * Slot called when the trigger type changed. + * + * @param [in] sTriggerType The new trigger type. + */ + void onTriggerTypeChanged(const QString& sTriggerType); + + //========================================================================================================= + /** + * Slot called when the frequency band changed. + */ + void onFrequencyBandChanged(); + + //========================================================================================================= + /** + * Slot called when the minimum changed. + */ + void onMinChanged(); + + //========================================================================================================= + /** + * Slot called when the maximum changed. + */ + void onMaxChanged(); + + //========================================================================================================= + /** + * Slot called when the button Reset Autoscale is clicked. + */ + void ResetAutoScaleClicked(); + + //========================================================================================================= + /** + * Slot called when the checkbox for minimum autoscale changed. + */ + void onMinAutoScaleChanged(int value); + + //========================================================================================================= + /** + * Slot called when the checkbox for maximum autoscale changed. + */ + void onMaxAutoScaleChanged(int value); + + //========================================================================================================= + + + + + + Ui::NeurofeedbackSettingsViewWidget* m_pUi; + + QString m_sSettingsPath; /**< The settings path to store the GUI settings to. */ + int m_iNumberTrials; /**< The number of trials are stored to check whether the number of trials actually changed. */ + int m_iMin; + int m_iMax; + + bool m_bMinAutoScale; + bool m_bMaxAutoScale; + +signals: + //========================================================================================================= + /** + * Emit signal whenever the Neurofeedback metric changed. + * + * @param [in] sMetric The new metric. + */ + void NeurofeedbackMetricChanged(const QString& sMetric); + + //========================================================================================================= + /** + * Emit signal whenever the window type changed. + * + * @param [in] windowType The new window type. + */ + void windowTypeChanged(const QString& windowType); + + //========================================================================================================= + /** + * Emit signal whenever the number of trials changed. + * + * @param [in] iNumberTrials The new number of trials. + */ + void numberTrialsChanged(int iNumberTrials); + + //========================================================================================================= + /** + * Emit signal whenever the trigger type changed. + * + * @param [in] sTriggerType The new trigger type. + */ + void triggerTypeChanged(const QString& sTriggerType); + + //========================================================================================================= + /** + * Emit signal whenever the frequency band changed. + * + * @param [in] fFreqLow The new lower frequency band. + * @param [in] fFreqHigh The new higher frequency band. + */ + void freqBandChanged(float fFreqLow, float fFreqHigh); + + //========================================================================================================= + /** + * Emit signal whenever the minimum changed. + * + * @param [in] Min The new minimum. + */ + void MinChanged(int Min); + + //========================================================================================================= + /** + * Emit signal whenever the maximum changed. + * + * @param [in] Max The new maximum. + */ + void MaxChanged(int Max); + + //========================================================================================================= + /** + * Emit signal whenever the distribution changed. + * + * @param [in] Distribution The new type of distribution for the sliders. + */ + void ResetAutoScaleChanged(bool bResetAutoScale); + + //========================================================================================================= + /** + * Emit signal whenever the maximum autocale changed. + * + * @param [in] bMaxAutoScale The bool for maximum autoscale. + */ + void MaxAutoScaleChanged(bool bMaxAutoScale); + + //========================================================================================================= + /** + * Emit signal whenever the minimum autoscale changed. + * + * @param [in] bMinAutoScale The bool for minimum autoscale. + */ + void MinAutoScaleChanged(bool bMinAutoScale); +}; +} // NAMESPACE + +#endif // NEUROFEEDBACKSETTINGSVIEW_H