diff --git a/.gitsubprojects b/.gitsubprojects index 35f17644f8f44a0e49fbedef85267636e505ef92..d15b9a383eb2ce8d04e7617b1054515f0e025af9 100644 --- a/.gitsubprojects +++ b/.gitsubprojects @@ -5,6 +5,6 @@ #git_subproject( Brion https://github.com/BlueBrain/Brion.git 073f356 ) git_subproject( ReTo https://github.com/gmrvvis/ReTo.git 13f5747f ) git_subproject( prefr https://github.com/gmrvvis/prefr.git 5b4b874a ) -git_subproject( SimIL https://github.com/gmrvvis/SimIL.git 7a1eab6 ) +git_subproject( SimIL https://github.com/gmrvvis/SimIL.git e4edaa3c ) git_subproject( scoop https://github.com/gmrvvis/scoop.git b3326cd ) git_subproject( acuterecorder https://github.com/vg-lab/AcuteRecorder.git 3ae70efa ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a79bd57b7a3041fcd8c4a96db2f1ace248a371f..232bb5e7c045091c250db09d35ff9a50e60666c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ cmake_minimum_required( VERSION 3.1 FATAL_ERROR ) # visimpl project and version -project( visimpl VERSION 1.6.1 ) +project( visimpl VERSION 1.7.0 ) set( visimpl_VERSION_ABI 6 ) SET( VISIMPL_LICENSE "GPL") diff --git a/stackviz/CMakeLists.txt b/stackviz/CMakeLists.txt index b69845b6470de3d203912d824c5920dd0ed1c8ed..1889f5ee11f9f03c41d5c94b96e1f0ec54022d36 100644 --- a/stackviz/CMakeLists.txt +++ b/stackviz/CMakeLists.txt @@ -31,13 +31,11 @@ set(STACKVIZ_SOURCES resources.qrc stackviz.cpp MainWindow.cpp - DisplayManagerWidget.cpp ) set(STACKVIZ_HEADERS ${PROJECT_BINARY_DIR}/include/stackviz/version.h MainWindow.h - DisplayManagerWidget.h log.h ) diff --git a/stackviz/DisplayManagerWidget.cpp b/stackviz/DisplayManagerWidget.cpp deleted file mode 100644 index c4a68174bf0701be6c97109fd38d1d76a7fdb7b9..0000000000000000000000000000000000000000 --- a/stackviz/DisplayManagerWidget.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -// ViSimpl -#include "DisplayManagerWidget.h" - -// Qt -#include <QWidget> -#include <QTableWidget> -#include <QLabel> -#include <QPushButton> -#include <QGroupBox> -#include <QGridLayout> - -using namespace stackviz; - -DisplayManagerWidget::DisplayManagerWidget( ) -: _eventData( nullptr ) -, _histData( nullptr ) -, _eventsLayout( nullptr ) -, _histogramsLayout( nullptr ) -, _dirtyFlagEvents( true ) -, _dirtyFlagHistograms( true ) -{ -} - -void DisplayManagerWidget::init( const std::vector< visimpl::EventWidget* >* eventData, - const std::vector< visimpl::HistogramWidget* >* histData ) -{ - setMinimumWidth( 500 ); - - setWindowTitle( "Visibility manager" ); - setWindowIcon(QIcon(":/visimpl.png")); - - _eventData = eventData; - _histData = histData; - - const QStringList eventHeaders = { "Name", "Show", "Delete" }; - const QStringList histoHeaders = { "Name", "Size", "Show", "Delete" }; - - auto globalLayout = new QGridLayout( ); - - // Events - _eventsLayout = new QGridLayout( ); - _eventsLayout->setAlignment( Qt::AlignTop ); - - auto eventScrollContainer = new QWidget( ); - eventScrollContainer->setLayout( _eventsLayout ); - - auto eventScroll = new QScrollArea( ); - eventScroll->setWidget( eventScrollContainer ); - eventScroll->setWidgetResizable( true ); - eventScroll->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - - auto eventGroup = new QGroupBox( ); - eventGroup->setTitle( "Events" ); - eventGroup->setMinimumHeight( 300 ); - eventGroup->setMaximumHeight( 300 ); - eventGroup->setLayout( new QVBoxLayout( )); - - auto headerEventLayout = new QGridLayout( ); - headerEventLayout->addWidget( new QLabel( "Name" ), 0, 0, 1, 2); - headerEventLayout->addWidget( new QLabel( "Visible" ), 0, 2, 1, 1); - headerEventLayout->addWidget( new QLabel( "Delete" ), 0, 3, 1, 1); - - auto eventHeader = new QWidget( ); - eventHeader->setLayout( headerEventLayout ); - - eventGroup->layout( )->addWidget( eventHeader ); - eventGroup->layout( )->addWidget( eventScroll ); - - // Histograms - _histogramsLayout = new QGridLayout( ); - _histogramsLayout->setAlignment( Qt::AlignTop ); - - auto histoScrollContainer = new QWidget( ); - histoScrollContainer->setLayout( _histogramsLayout ); - - auto histoScroll = new QScrollArea( ); - histoScroll->setWidget( histoScrollContainer ); - histoScroll->setWidgetResizable( true ); - histoScroll->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - - auto histGroup = new QGroupBox( ); - histGroup->setTitle( "Histograms" ); - histGroup->setMinimumHeight( 300 ); - histGroup->setMaximumHeight( 300 ); - histGroup->setLayout( new QVBoxLayout( ) ); - - auto headerHistoLayout = new QGridLayout( ); - headerHistoLayout->addWidget( new QLabel( "Name" ), 0, 0, 1, 2); - headerHistoLayout->addWidget( new QLabel( "Size" ), 0, 2, 1, 1); - headerHistoLayout->addWidget( new QLabel( "Visible" ), 0, 3, 1, 1); - headerHistoLayout->addWidget( new QLabel( "Delete" ), 0, 4, 1, 1); - - auto histoHeader = new QWidget( ); - histoHeader->setLayout( headerHistoLayout ); - - histGroup->layout( )->addWidget( histoHeader ); - histGroup->layout( )->addWidget( histoScroll ); - - auto closeButton = new QPushButton( "Close", this ); - connect( closeButton, SIGNAL( clicked( )), this, SLOT( close( ))); - - globalLayout->addWidget( eventGroup, 0, 0, 5, 5 ); - globalLayout->addWidget( histGroup, 5, 0, 5, 5 ); - globalLayout->addWidget( closeButton, 10, 2, 1, 1 ); - - this->setLayout( globalLayout ); -} - -void DisplayManagerWidget::close( void ) -{ - hide( ); -} - -void DisplayManagerWidget::dirtyEvents(void) -{ - _dirtyFlagEvents = true; -} - -void DisplayManagerWidget::dirtyHistograms(void) -{ - _dirtyFlagHistograms = true; -} - -void DisplayManagerWidget::clearWidgets(void) -{ - clearEventWidgets(); - - clearHistogramWidgets(); -} - -void DisplayManagerWidget::clearEventWidgets(void) -{ - auto removeEventWidget = [this](TDisplayEventTuple &e) - { - auto container = std::get< TDM_E_CONTAINER >( e ); - _eventsLayout->removeWidget( container ); - - delete container; - }; - std::for_each(_events.begin(), _events.end(), removeEventWidget); - - QLayoutItem *item; - while ((item = _eventsLayout->takeAt(0)) != nullptr) - { - delete item->widget(); - delete item; - } - - _events.clear(); -} - -void DisplayManagerWidget::clearHistogramWidgets(void) -{ - auto removeHistogramWidget = [this](TDisplayHistogramTuple &e) - { - auto container = std::get< TDM_H_CONTAINER >( e ); - _histogramsLayout->removeWidget( container ); - - delete container; - }; - std::for_each(_histograms.begin(), _histograms.end(), removeHistogramWidget); - - QLayoutItem *item; - while ((item = _histogramsLayout->takeAt(0)) != nullptr) - { - delete item->widget(); - delete item; - } - - _histograms.clear(); -} - -void DisplayManagerWidget::refresh() -{ - if (_dirtyFlagEvents) refreshEvents(); - - if (_dirtyFlagHistograms) refreshHistograms(); -} - -void DisplayManagerWidget::refreshEvents(void) -{ - clearEventWidgets(); - - unsigned int row = 0; - for (const auto &ev : *_eventData) - { - QWidget *container = new QWidget(); - container->setMaximumHeight(50); - // Fill name - QGridLayout *contLayout = new QGridLayout(); - container->setLayout(contLayout); - - QLabel *nameLabel = new QLabel(tr(ev->name().c_str()), container); - QPushButton *hideButton = new QPushButton(container); - hideButton->setIcon(QIcon(QPixmap(":icons/show.svg"))); - hideButton->setCheckable(true); - hideButton->setChecked(true); - hideButton->setWhatsThis("Click to show/hide the row in main view."); - - QPushButton *deleteButton = new QPushButton(container); - deleteButton->setIcon(QIcon(QPixmap(":icons/trash.svg"))); - - contLayout->addWidget(nameLabel, row, 0, 1, 2); - contLayout->addWidget(hideButton, row, 2, 1, 1); - contLayout->addWidget(deleteButton, row, 3, 1, 1); - - _eventsLayout->addWidget(container); - - if (row < _eventData->size() - 1) - { - QFrame *line = new QFrame(container); - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - - _eventsLayout->addWidget(line); - } - - connect(hideButton, SIGNAL(clicked( )), - this, SLOT(hideEventClicked( ))); - - connect(deleteButton, SIGNAL(clicked( )), - this, SLOT(deleteEventClicked( ))); - - _events.push_back(std::make_tuple(container, nameLabel, hideButton, deleteButton)); - ++row; - } - - _dirtyFlagEvents = false; -} - -void DisplayManagerWidget::refreshHistograms(void) -{ - clearHistogramWidgets(); - - unsigned int row = 0; - for (const auto &hist : *_histData) - { - QWidget *container = new QWidget(); - container->setMaximumHeight(50); - - // Fill name - QGridLayout *contLayout = new QGridLayout(); - container->setLayout(contLayout); - - QLabel *nameLabel = new QLabel(tr(hist->name().c_str()), container); - - QLabel *numberLabel = new QLabel(QString::number(hist->gidsSize()), container); - - QPushButton *hideButton = new QPushButton(container); - hideButton->setIcon(QIcon(QPixmap(":icons/show.svg"))); - hideButton->setCheckable(true); - hideButton->setChecked(true); - hideButton->setWhatsThis("Click to show/hide the row in main view."); - - QPushButton *deleteButton = new QPushButton(container); - deleteButton->setIcon(QIcon(QPixmap(":icons/trash.svg"))); - - contLayout->addWidget(nameLabel, row, 0, 1, 2); - contLayout->addWidget(numberLabel, row, 2, 1, 1); - contLayout->addWidget(hideButton, row, 3, 1, 1); - contLayout->addWidget(deleteButton, row, 4, 1, 1); - - if (row == 0) deleteButton->setEnabled(false); - - _histogramsLayout->addWidget(container); - - if (row < _histData->size() - 1) - { - QFrame *line = new QFrame(container); - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - - _histogramsLayout->addWidget(line); - } - - connect(hideButton, SIGNAL(clicked( )), - this, SLOT(hideHistoClicked( ))); - - connect(deleteButton, SIGNAL(clicked( )), - this, SLOT(deleteHistoClicked( ))); - - _histograms.push_back(std::make_tuple(container, nameLabel, numberLabel, hideButton, deleteButton)); - ++row; - } - - _dirtyFlagHistograms = false; -} - -void DisplayManagerWidget::hideEventClicked() -{ - auto author = qobject_cast<QWidget*>(sender()); - if (!author) return; - - unsigned int counter = 0; - for (auto t : _events) - { - auto container = std::get<TDM_E_CONTAINER>(t); - - if (author->parent() == container) - { - auto button = std::get<TDM_E_SHOW>(t); - - bool hidden = button->isChecked(); - - button->setIcon(QIcon(hidden ? ":icons/show.svg" : ":icons/hide.svg")); - - emit(eventVisibilityChanged(counter, hidden)); - - break; - } - - ++counter; - } -} - -void DisplayManagerWidget::deleteEventClicked() -{ - auto author = qobject_cast<QWidget*>(sender()); - if (!author) return; - - unsigned int counter = 0; - for (auto t : _events) - { - auto container = std::get<TDM_E_CONTAINER>(t); - - if (author->parent() == container) - { - - emit(removeEvent(counter)); - _dirtyFlagEvents = true; - - refreshEvents(); - - break; - } - - ++counter; - } -} - -void DisplayManagerWidget::hideHistoClicked() -{ - auto author = qobject_cast<QWidget*>(sender()); - if (!author) return; - - unsigned int counter = 0; - for (auto t : _histograms) - { - auto container = std::get<TDM_H_CONTAINER>(t); - - if (author->parent() == container) - { - auto button = std::get<TDM_H_SHOW>(t); - - bool hidden = button->isChecked(); - - button->setIcon(QIcon(hidden ? ":icons/show.svg" : ":icons/hide.svg")); - - emit(subsetVisibilityChanged(counter, hidden)); - - break; - } - - ++counter; - } -} - -void DisplayManagerWidget::deleteHistoClicked() -{ - auto author = qobject_cast<QWidget*>(sender()); - if (!author) return; - - unsigned int counter = 0; - for (auto t : _histograms) - { - auto container = std::get<TDM_H_CONTAINER>(t); - - if (author->parent() == container) - { - - emit(removeHistogram(counter)); - _dirtyFlagHistograms = true; - - refreshHistograms(); - - break; - } - - ++counter; - } -} - - - diff --git a/stackviz/DisplayManagerWidget.h b/stackviz/DisplayManagerWidget.h deleted file mode 100644 index 3e34cc46370b71b8adbc47f67a91ca5fbe7bfad7..0000000000000000000000000000000000000000 --- a/stackviz/DisplayManagerWidget.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef DISPLAYMANAGERWIDGET_H_ -#define DISPLAYMANAGERWIDGET_H_ - -// Sumrice -#include <sumrice/sumrice.h> - -class QGridLayout; -class QWidget; -class QLabel; -class QPushButton; - -namespace stackviz -{ - - typedef enum - { - TDM_E_CONTAINER = 0, - TDM_E_NAME, - TDM_E_SHOW, - TDM_E_DELETE, -// TDM_E_LINE, - TDM_E_MAXCOLUMN - } TDispMngrEventName; - - typedef std::tuple< QWidget*, - QLabel*, - QPushButton*, - QPushButton* -// QFrame* - > TDisplayEventTuple; - - typedef enum - { - TDM_H_CONTAINER = 0, - TDM_H_NAME, - TDM_H_NUMBER, - TDM_H_SHOW, - TDM_H_DELETE, - TDM_H_MAXCOLUMN - } TDispMngrHistoName; - - typedef std::tuple< QWidget*, - QLabel*, - QLabel*, - QPushButton*, - QPushButton* - > TDisplayHistogramTuple; - - - class DisplayManagerWidget : public QWidget - { - Q_OBJECT; - - public: - - DisplayManagerWidget( ); - - void init( const std::vector< visimpl::EventWidget* >* eventData, - const std::vector< visimpl::HistogramWidget* >* histData ); - - void refresh( ); - - void dirtyEvents( void ); - void dirtyHistograms( void ); - - void clearWidgets( void ); - - signals: - - void eventVisibilityChanged( unsigned int, bool ); - void removeEvent( unsigned int ); - - void subsetVisibilityChanged( unsigned int, bool ); - void removeHistogram( unsigned int ); - - protected slots: - - void hideEventClicked( ); - void deleteEventClicked( ); - - void close( void ); - - void hideHistoClicked( ); - void deleteHistoClicked( ); - - protected: - - void clearEventWidgets( void ); - void clearHistogramWidgets( void ); - - void refreshEvents( void ); - void refreshHistograms( void ); - -// QTableWidget* _eventTable; -// QTableWidget* _histoTable; - - const std::vector< visimpl::EventWidget* >* _eventData; - const std::vector< visimpl::HistogramWidget* >* _histData; - -// std::vector< visimpl::EventWidget* > _availableEvents; -// std::vector< visimpl::HistogramWidget* > _availableHistograms; - - std::vector< TDisplayEventTuple > _events; - std::vector< TDisplayHistogramTuple > _histograms; - - QGridLayout* _eventsLayout; - QGridLayout* _histogramsLayout; - - bool _dirtyFlagEvents; - bool _dirtyFlagHistograms; - }; - - -} - -#endif /* DISPLAYMANAGERWIDGET_H_ */ diff --git a/stackviz/MainWindow.cpp b/stackviz/MainWindow.cpp index 6d2e98e6ea288733973ce3255cf060be45b354c3..543a04ef5f4fad810320bb9b0bc4b02b22c12abe 100644 --- a/stackviz/MainWindow.cpp +++ b/stackviz/MainWindow.cpp @@ -111,6 +111,10 @@ MainWindow::MainWindow( QWidget* parent_ ) connect( _ui->actionAbout, SIGNAL( triggered( void )), this, SLOT( aboutDialog( void ))); +#ifdef SIMIL_WITH_REST_API + _ui->actionConnectRESTserver->setEnabled(true); +#endif + m_dataInspector = new DataInspector(""); m_dataInspector->hide(); } @@ -146,6 +150,9 @@ void MainWindow::init( const std::string &session ) connect( _ui->actionOpenSubsetEventsFile, SIGNAL( triggered( void )), this, SLOT( openSubsetEventsFileThroughDialog( void ))); + connect( _ui->actionCloseData, SIGNAL(triggered(bool)), + this, SLOT(closeData())); + _ui->actionOpenSubsetEventsFile->setEnabled(false); initPlaybackDock( ); @@ -174,6 +181,7 @@ void MainWindow::init( const std::string &session ) _ui->menubar->setContextMenuPolicy(Qt::PreventContextMenu); _ui->actionShowDataManager->setEnabled(false); + _ui->actionCloseData->setEnabled(false); } MainWindow::~MainWindow( void ) @@ -495,6 +503,8 @@ void MainWindow::initPlaybackDock( ) _dockSimulation->setWidget( content ); this->addDockWidget( Qt::BottomDockWidgetArea, _dockSimulation ); + + _dockSimulation->setEnabled(false); } void MainWindow::initSummaryWidget( ) @@ -509,6 +519,12 @@ void MainWindow::initSummaryWidget( ) _summary->simulationPlayer( _player ); } + if(centralWidget()) + { + auto toRemove = centralWidget(); + layout()->removeWidget(toRemove); + delete toRemove; + } this->setCentralWidget( _summary ); connect( _ui->actionAutoNamingSelections, SIGNAL( triggered( )), @@ -751,7 +767,7 @@ void MainWindow::UpdateSimulationSlider(float position) const auto tBegin = _player->startTime(); const auto tEnd = _player->endTime(); const auto newPosition = std::min(tEnd, std::max(tBegin, position)); - const auto isOverflow = newPosition != position; + const auto isOverflow = (newPosition != position); PlayAtTime( newPosition, isOverflow ); @@ -889,6 +905,8 @@ void MainWindow::addCorrelation(const std::string &subset) void MainWindow::calculateCorrelations(void) { + if(!_subsetEventManager) return; + visimpl::CorrelationComputer cc(dynamic_cast<simil::SpikeData*>(_player->data())); const auto eventNames = _subsetEventManager->eventNames(); @@ -1017,6 +1035,9 @@ void MainWindow::updateUIonOpen(const std::string &eventsFile) _ui->actionShowDataManager->setEnabled(true); _ui->actionOpenSubsetEventsFile->setEnabled(true); + _ui->actionCloseData->setEnabled(true); + + _dockSimulation->setEnabled(true); } void stackviz::MainWindow::loadData(const simil::TDataType type, @@ -1025,6 +1046,11 @@ void stackviz::MainWindow::loadData(const simil::TDataType type, { updateGeometry(); + Q_ASSERT(type != simil::TDataType::TREST); + m_dataInspector->setUpdatesEnabled(false); + _ui->actionConfigureRESTconnection->setEnabled(false); + _ui->actionConnectRESTserver->setEnabled(false); + _simulationType = simType; m_subsetEventFile = subsetEventFile; @@ -1134,6 +1160,7 @@ void stackviz::MainWindow::onLoadFinished() break; case simil::TREST: { +#ifdef SIMIL_WITH_REST_API const auto netData = m_loader->network(); const auto simData = m_loader->simulationData(); @@ -1141,12 +1168,10 @@ void stackviz::MainWindow::onLoadFinished() _player->LoadData(netData, simData); // NOTE: loader doesn't get destroyed. -#ifdef SIMIL_WITH_REST_API - auto timer = new QTimer( this ); - connect( timer, SIGNAL( timeout()), - m_dataInspector, SLOT( updateInfo()) ); - - timer->start( 4000 ); + const auto waitTime = m_loader->RESTLoader()->getConfiguration().waitTime; + m_dataInspector->setCheckTimer(waitTime); + m_dataInspector->setUpdatesEnabled(true); + _ui->actionConfigureRESTconnection->setEnabled(true); #endif } break; @@ -1243,6 +1268,107 @@ void stackviz::MainWindow::closeEvent(QCloseEvent *e) QMainWindow::closeEvent(e); } +void stackviz::MainWindow::openRESTThroughDialog() +{ +#ifdef SIMIL_WITH_REST_API + ConnectRESTDialog dialog(this); + ConnectRESTDialog::Connection connection; + dialog.setRESTConnection(connection); + + if (QDialog::Accepted == dialog.exec()) + { + connection = dialog.getRESTConnection(); + const auto restOpt = dialog.getRESTOptions(); + + simil::LoaderRestData::Configuration config; + config.api = connection.protocol.compare("NEST", Qt::CaseInsensitive) == 0 ? + simil::LoaderRestData::Rest_API::NEST : + simil::LoaderRestData::Rest_API::ARBOR; + config.port = connection.port; + config.url = connection.url.toStdString(); + config.waitTime = restOpt.waitTime; + config.failTime = restOpt.failTime; + config.spikesSize = restOpt.spikesSize; + + loadRESTData(config); + } +#else + const auto title = tr("Connect REST API"); + const auto message = tr("REST data loading is unsupported."); + QMessageBox::critical(this, title, message, QMessageBox::Ok); +#endif +} + +void stackviz::MainWindow::configureREST() +{ +#ifdef SIMIL_WITH_REST_API + if (!m_loader) + { + const QString message = tr("There is no REST connection!"); + QMessageBox::warning(this, tr("REST API Options"), message, QMessageBox::Ok); + return; + } + + auto loader = m_loader->RESTLoader(); + auto options = loader->getConfiguration(); + + RESTConfigurationWidget::Options dialogOptions; + dialogOptions.waitTime = options.waitTime; + dialogOptions.failTime = options.failTime; + dialogOptions.spikesSize = options.spikesSize; + + ConfigureRESTDialog dialog(this, Qt::WindowFlags(), dialogOptions); + if (QDialog::Accepted == dialog.exec()) + { + dialogOptions = dialog.getRESTOptions(); + + simil::LoaderRestData::Configuration config; + config.waitTime = dialogOptions.waitTime; + config.failTime = dialogOptions.failTime; + config.spikesSize = dialogOptions.spikesSize; + + loader->setConfiguration(config); + } +#else + const auto title = tr("Configure REST API"); + const auto message = tr("REST data loading is unsupported."); + QMessageBox::critical(this, title, message, QMessageBox::Ok); +#endif +} + +void stackviz::MainWindow::closeData() +{ + QApplication::setOverrideCursor(Qt::WaitCursor); + _player->Clear(); + _subsetEventManager = nullptr; + + // remove histograms + if(_summary) + { + layout()->removeWidget(_summary); + _summary->deleteLater(); + _summary = nullptr; + setCentralWidget(new QWidget()); + } + + if(_displayManager) + { + if(_displayManager->isVisible()) _displayManager->hide(); + _displayManager->deleteLater(); + _displayManager = nullptr; + } + + _correlations.clear(); + + _ui->actionCloseData->setEnabled(false); + _dockSimulation->setEnabled(false); + + m_dataInspector->setUpdatesEnabled(false); + m_dataInspector->setSimPlayer(nullptr); + + QApplication::restoreOverrideCursor(); +} + void stackviz::MainWindow::closeLoadingDialog() { if(m_loaderDialog) @@ -1252,3 +1378,33 @@ void stackviz::MainWindow::closeLoadingDialog() m_loaderDialog = nullptr; } } + +#ifdef SIMIL_WITH_REST_API +void stackviz::MainWindow::loadRESTData(const simil::LoaderRestData::Configuration &config) +{ + closeLoadingDialog(); + + QApplication::setOverrideCursor(Qt::WaitCursor); + + m_dataInspector->setCheckUpdates(false); + + m_loaderDialog = new LoadingDialog( this ); + m_loaderDialog->show( ); + + QApplication::processEvents( ); + + m_loader = std::make_shared< LoaderThread >( ); + m_loader->setRESTConfiguration(config); + + connect( m_loader.get( ) , SIGNAL( finished( )), + this, SLOT( onDataLoaded( )) ); + connect( m_loader.get( ) , SIGNAL( progress( int )), + m_loaderDialog , SLOT( setProgress( int )) ); + connect( m_loader.get( ) , SIGNAL( network( unsigned int )) , + m_loaderDialog , SLOT( setNetwork( unsigned int )) ); + connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) , + m_loaderDialog , SLOT( setSpikesValue( unsigned int )) ); + + m_loader->start( ); +} +#endif diff --git a/stackviz/MainWindow.h b/stackviz/MainWindow.h index 56806255fbefa89c1b18cdc41d366f10c1491d8b..68c92774b470b545c101fc7f115e83c711df0eec 100644 --- a/stackviz/MainWindow.h +++ b/stackviz/MainWindow.h @@ -46,10 +46,10 @@ #endif #include "ui_stackviz.h" -#include "DisplayManagerWidget.h" class Recorder; class QCloseEvent; +class DisplayManagerWidget; namespace Ui { @@ -76,6 +76,14 @@ namespace stackviz const simil::TSimulationType simType = simil::TSimulationType::TSimSpikes, const std::string &subsetEventFile = ""); +#ifdef SIMIL_WITH_REST_API + /** \brief Connects and loads data using the given REST connection. + * \param[in] config REST connection configuration. + * + */ + void loadRESTData(const simil::LoaderRestData::Configuration &config); +#endif + void openSubsetEventFile( const std::string& fileName, bool append = false ); @@ -85,6 +93,7 @@ namespace stackviz void openCSVFilesThroughDialog( void ); void openH5FilesThroughDialog( void ); void openSubsetEventsFileThroughDialog( void ); + void openRESTThroughDialog(); void aboutDialog( void ); void togglePlaybackDock( void ); @@ -108,6 +117,11 @@ namespace stackviz void calculateCorrelations( void ); + /** \brief Closes the current dataset and resets the UI. + * + */ + void closeData(); + protected slots: #ifdef VISIMPL_USE_GMRVLEX @@ -130,6 +144,11 @@ namespace stackviz void finishRecording(); + /** \brief Shows a dialog with REST API options and applies them. + * + */ + void configureREST(); + protected: void configurePlayer( void ); diff --git a/stackviz/icons/close.svg b/stackviz/icons/close.svg index 0e92788ba0fa8bfbf267436dfc87aba8a785c642..c1b09d11230814a5bebb4dcef5b3fe974e9ee2fb 100644 --- a/stackviz/icons/close.svg +++ b/stackviz/icons/close.svg @@ -1,2 +1,158 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 48 48"><title>Gnome window close</title><desc>http://svn.gnome.org/viewvc/gnome-icon-theme/</desc><radialGradient id="SVGID_1_" cx="-66.1006" cy="-1047.4805" r="1.6055" gradientTransform="matrix(13.7819 0 0 -2.4587 934.9918 -2541.4377)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#000"/><stop offset="1" style="stop-color:#000;stop-opacity:0"/></radialGradient><path style="opacity:.092;fill:url(#SVGID_1_)" d="M46.127,33.979c0,2.182-9.906,3.947-22.127,3.947c-12.22,0-22.126-1.768-22.126-3.947c0-2.179,9.906-3.946,22.126-3.946C36.222,30.032,46.127,31.8,46.127,33.979z"/><radialGradient id="SVGID_2_" cx="148.2012" cy="-1029.5996" r="1.6036" gradientTransform="matrix(5.3381 0 0 -2.4944 -778.1038 -2532.8325)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#000"/><stop offset="1" style="stop-color:#000;stop-opacity:0"/></radialGradient><path style="opacity:.2031;fill:url(#SVGID_2_)" d="M22,35.392c0,2.322-4.029,4.205-9,4.205s-9-1.883-9-4.205s4.029-4.205,9-4.205S22,33.069,22,35.392z"/><radialGradient id="SVGID_3_" cx="127.0596" cy="-1016.3906" r="1.6066" gradientTransform="matrix(5.4059 0 0 -2.5259 -652.8704 -2531.8577)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#000"/><stop offset="1" style="stop-color:#000;stop-opacity:0"/></radialGradient><path style="opacity:.2031;fill:url(#SVGID_3_)" d="M43,35.392c0,2.322-4.028,4.205-9,4.205c-4.971,0-9-1.883-9-4.205s4.029-4.205,9-4.205C38.972,31.187,43,33.069,43,35.392z"/><radialGradient id="SVGID_4_" cx="-18.3965" cy="-229.4829" r="1.4931" gradientTransform="matrix(10.1125 0 0 -10.104 209.6891 -2299.3503)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#9C9E99"/><stop offset="1" style="stop-color:#868883"/></radialGradient><path style="fill:url(#SVGID_4_);stroke:#555753;stroke-width:.8125;stroke-linecap:round;stroke-linejoin:round" d="M13.102,8.405c-1.456-0.01-2.788,0.879-3.339,2.227c-0.551,1.348-0.212,2.883,0.834,3.896l8.013,8.013l-8.013,8.013c-1.398,1.398-1.398,3.666,0,5.064c1.398,1.398,3.666,1.398,5.064,0l8.014-8.014l8.013,8.014c0.898,0.924,2.204,1.277,3.45,0.945c1.245-0.332,2.241-1.313,2.561-2.561c0.318-1.249-0.067-2.563-1.002-3.45l-8.014-8.014l8.014-8.013c1.056-1.021,1.4-2.6,0.834-3.951c-0.563-1.354-1.928-2.205-3.396-2.17c-0.93,0.037-1.809,0.437-2.447,1.111l-8.013,8.014l-8.014-8.014C14.995,8.815,14.069,8.413,13.102,8.405z"/><path xlink:href="#path4262" style="opacity:.3621;fill:none;stroke:#FFFFFF;stroke-width:.8125;stroke-linecap:round;stroke-linejoin:round" d="M13.126,9.405c-1.037-0.008-2.03,0.654-2.423,1.615s-0.147,2.03,0.615,2.771c0.013,0,0.025,0,0.039,0l8,8.038c0.199,0.191,0.311,0.455,0.311,0.73s-0.112,0.541-0.311,0.731l-8,8c-1.009,1.009-1.009,2.605,0,3.615c1.008,1.009,2.606,1.009,3.615,0l8-8.039c0.191-0.198,0.455-0.313,0.731-0.313c0.275,0,0.539,0.112,0.73,0.313l8,8.039c0,0.013,0,0.023,0,0.037c0.637,0.656,1.55,0.896,2.461,0.654c0.904-0.242,1.581-0.957,1.809-1.847c0.228-0.896-0.021-1.823-0.693-2.462c-0.012,0-0.024,0-0.037,0l-8-8c-0.198-0.191-0.313-0.455-0.313-0.73s0.113-0.541,0.313-0.73l8-8.038c0.013,0,0.025,0,0.037,0c0.76-0.733,1.015-1.896,0.615-2.847c-0.399-0.959-1.354-1.563-2.422-1.539c-0.664,0.025-1.315,0.328-1.77,0.809c0,0.014,0,0.025,0,0.039l-8,8.001c-0.191,0.198-0.455,0.312-0.73,0.312c-0.276,0-0.54-0.112-0.731-0.312l-8-8.001c0-0.014,0-0.025,0-0.039C14.501,9.715,13.819,9.411,13.126,9.405z"/><radialGradient id="SVGID_5_" cx="46.3672" cy="-666" r="1.8958" gradientTransform="matrix(7.5973 0 0 -3.8245 -329.7393 -2524.8076)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#555753"/><stop offset="1" style="stop-color:#555753;stop-opacity:0"/></radialGradient><path style="opacity:.3;fill:url(#SVGID_5_)" d="M19.454,22.559c5.222-1.522,3.882,0.164,8.507,0.164l8.506,8.506l-4.704,3.64l-8-8.068l-8,7.798L11.58,30.5L19.454,22.559z"/></svg> \ No newline at end of file +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="100%" + height="100%" + viewBox="0 0 48 48" + version="1.1" + id="svg43" + sodipodi:docname="close.svg" + inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"> + <metadata + id="metadata49"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs47" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1528" + inkscape:window-height="836" + id="namedview45" + showgrid="false" + inkscape:zoom="13.906433" + inkscape:cx="24" + inkscape:cy="24" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="svg43" /> + <title + id="title2">Gnome window close</title> + <desc + id="desc4">http://svn.gnome.org/viewvc/gnome-icon-theme/</desc> + <radialGradient + id="SVGID_1_" + cx="-66.1006" + cy="-1047.4805" + r="1.6055" + gradientTransform="matrix(13.7819 0 0 -2.4587 934.9918 -2541.4377)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#000" + id="stop6" /> + <stop + offset="1" + style="stop-color:#000;stop-opacity:0" + id="stop8" /> + </radialGradient> + <path + style="opacity:.092;fill:url(#SVGID_1_)" + d="M46.127,33.979c0,2.182-9.906,3.947-22.127,3.947c-12.22,0-22.126-1.768-22.126-3.947c0-2.179,9.906-3.946,22.126-3.946C36.222,30.032,46.127,31.8,46.127,33.979z" + id="path11" /> + <radialGradient + id="SVGID_2_" + cx="148.2012" + cy="-1029.5996" + r="1.6036" + gradientTransform="matrix(5.3381 0 0 -2.4944 -778.1038 -2532.8325)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#000" + id="stop13" /> + <stop + offset="1" + style="stop-color:#000;stop-opacity:0" + id="stop15" /> + </radialGradient> + <path + style="opacity:.2031;fill:url(#SVGID_2_)" + d="M22,35.392c0,2.322-4.029,4.205-9,4.205s-9-1.883-9-4.205s4.029-4.205,9-4.205S22,33.069,22,35.392z" + id="path18" /> + <radialGradient + id="SVGID_3_" + cx="127.0596" + cy="-1016.3906" + r="1.6066" + gradientTransform="matrix(5.4059 0 0 -2.5259 -652.8704 -2531.8577)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#000" + id="stop20" /> + <stop + offset="1" + style="stop-color:#000;stop-opacity:0" + id="stop22" /> + </radialGradient> + <path + style="opacity:.2031;fill:url(#SVGID_3_)" + d="M43,35.392c0,2.322-4.028,4.205-9,4.205c-4.971,0-9-1.883-9-4.205s4.029-4.205,9-4.205C38.972,31.187,43,33.069,43,35.392z" + id="path25" /> + <radialGradient + id="SVGID_4_" + cx="-18.3965" + cy="-229.4829" + r="1.4931" + gradientTransform="matrix(10.1125 0 0 -10.104 209.6891 -2299.3503)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#9C9E99" + id="stop27" /> + <stop + offset="1" + style="stop-color:#868883" + id="stop29" /> + </radialGradient> + <path + style="fill:#aa0000;stroke:#555753;stroke-width:0.8125;stroke-linecap:round;stroke-linejoin:round" + d="M13.102,8.405c-1.456-0.01-2.788,0.879-3.339,2.227c-0.551,1.348-0.212,2.883,0.834,3.896l8.013,8.013l-8.013,8.013c-1.398,1.398-1.398,3.666,0,5.064c1.398,1.398,3.666,1.398,5.064,0l8.014-8.014l8.013,8.014c0.898,0.924,2.204,1.277,3.45,0.945c1.245-0.332,2.241-1.313,2.561-2.561c0.318-1.249-0.067-2.563-1.002-3.45l-8.014-8.014l8.014-8.013c1.056-1.021,1.4-2.6,0.834-3.951c-0.563-1.354-1.928-2.205-3.396-2.17c-0.93,0.037-1.809,0.437-2.447,1.111l-8.013,8.014l-8.014-8.014C14.995,8.815,14.069,8.413,13.102,8.405z" + id="path32" /> + <path + style="opacity:0.3621;fill:#ff0000;stroke:#FFFFFF;stroke-width:0.8125;stroke-linecap:round;stroke-linejoin:round" + d="M 34.203125 9.4023438 C 33.539125 9.4273437 32.888594 9.7318902 32.433594 10.212891 L 32.433594 10.251953 L 24.433594 18.251953 C 24.242594 18.449953 23.978125 18.564453 23.703125 18.564453 C 23.427125 18.564453 23.163656 18.451953 22.972656 18.251953 L 14.972656 10.251953 L 14.972656 10.212891 C 14.501656 9.7158902 13.819953 9.4102969 13.126953 9.4042969 C 12.089953 9.3962969 11.096125 10.058531 10.703125 11.019531 C 10.310125 11.980531 10.556359 13.050016 11.318359 13.791016 L 11.357422 13.791016 L 19.357422 21.828125 C 19.556422 22.019125 19.667969 22.283594 19.667969 22.558594 C 19.667969 22.833594 19.556422 23.099063 19.357422 23.289062 L 11.357422 31.289062 C 10.348422 32.298063 10.348422 33.894297 11.357422 34.904297 C 12.365422 35.913297 13.963656 35.913297 14.972656 34.904297 L 22.972656 26.865234 C 23.163656 26.667234 23.427125 26.552734 23.703125 26.552734 C 23.978125 26.552734 24.242594 26.664234 24.433594 26.865234 L 32.433594 34.904297 L 32.433594 34.941406 C 33.070594 35.597406 33.983531 35.837703 34.894531 35.595703 C 35.798531 35.353703 36.475125 34.638047 36.703125 33.748047 C 36.931125 32.852047 36.681766 31.926109 36.009766 31.287109 L 35.972656 31.287109 L 27.972656 23.287109 C 27.774656 23.096109 27.660156 22.831641 27.660156 22.556641 C 27.660156 22.281641 27.772656 22.015172 27.972656 21.826172 L 35.972656 13.789062 L 36.009766 13.789062 C 36.769766 13.056063 37.025 11.892406 36.625 10.941406 C 36.226 9.9824065 35.271125 9.3783437 34.203125 9.4023438 z " + id="path34" /> + <radialGradient + id="SVGID_5_" + cx="46.3672" + cy="-666" + r="1.8958" + gradientTransform="matrix(7.5973 0 0 -3.8245 -329.7393 -2524.8076)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#555753" + id="stop36" /> + <stop + offset="1" + style="stop-color:#555753;stop-opacity:0" + id="stop38" /> + </radialGradient> + <path + style="opacity:.3;fill:url(#SVGID_5_)" + d="M19.454,22.559c5.222-1.522,3.882,0.164,8.507,0.164l8.506,8.506l-4.704,3.64l-8-8.068l-8,7.798L11.58,30.5L19.454,22.559z" + id="path41" /> +</svg> diff --git a/stackviz/icons/folder-rest.svg b/stackviz/icons/folder-rest.svg new file mode 100644 index 0000000000000000000000000000000000000000..d32071f7cff28c1adcdc6932f10e9f771008ee3d --- /dev/null +++ b/stackviz/icons/folder-rest.svg @@ -0,0 +1,358 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + id="svg97" + height="48" + width="48" + version="1.0" + sodipodi:docname="folder-rest.svg" + inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"> + <metadata + id="metadata57"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1528" + inkscape:window-height="836" + id="namedview55" + showgrid="false" + inkscape:zoom="8.8541665" + inkscape:cx="36.481212" + inkscape:cy="17.761916" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="svg97" + inkscape:document-rotation="0" /> + <defs + id="defs3"> + <rect + x="6.2682353" + y="11.350588" + width="41.392941" + height="33.825882" + id="rect890" /> + <radialGradient + id="radialGradient6719" + xlink:href="#linearGradient5060" + gradientUnits="userSpaceOnUse" + cy="486.65" + cx="605.71" + gradientTransform="matrix(-2.7744 0 0 1.9697 112.76 -872.89)" + r="117.14" /> + <linearGradient + id="linearGradient5060"> + <stop + id="stop5062" + offset="0" /> + <stop + id="stop5064" + stop-opacity="0" + offset="1" /> + </linearGradient> + <radialGradient + id="radialGradient6717" + xlink:href="#linearGradient5060" + gradientUnits="userSpaceOnUse" + cy="486.65" + cx="605.71" + gradientTransform="matrix(2.7744 0 0 1.9697 -1891.6 -872.89)" + r="117.14" /> + <linearGradient + id="linearGradient6715" + y2="609.51" + gradientUnits="userSpaceOnUse" + x2="302.86" + gradientTransform="matrix(2.7744 0 0 1.9697 -1892.2 -872.89)" + y1="366.65" + x1="302.86"> + <stop + id="stop5050" + stop-opacity="0" + offset="0" /> + <stop + id="stop5056" + offset=".5" /> + <stop + id="stop5052" + stop-opacity="0" + offset="1" /> + </linearGradient> + <radialGradient + id="radialGradient238" + gradientUnits="userSpaceOnUse" + cy="37.518" + cx="20.706" + gradientTransform="matrix(1.055 -.027345 .17770 1.1909 -3.5722 -7.1253)" + r="30.905"> + <stop + id="stop1790" + stop-color="#202020" + offset="0" /> + <stop + id="stop1791" + stop-color="#b9b9b9" + offset="1" /> + </radialGradient> + <linearGradient + id="linearGradient491" + y2="66.834" + gradientUnits="userSpaceOnUse" + x2="9.8981" + gradientTransform="matrix(1.5168 0 0 .70898 -.87957 -1.3182)" + y1="13.773" + x1="6.2298"> + <stop + id="stop3984" + stop-color="#fff" + stop-opacity=".87629" + offset="0" /> + <stop + id="stop3985" + stop-color="#fffffe" + stop-opacity="0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient322" + y2="46.689" + gradientUnits="userSpaceOnUse" + x2="12.854" + gradientTransform="matrix(1.3175 0 0 .81626 -.87957 -1.3182)" + y1="32.567" + x1="13.036"> + <stop + id="stop320" + stop-color="#fff" + offset="0" /> + <stop + id="stop321" + stop-color="#fff" + stop-opacity="0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3104" + y2="6.1803" + gradientUnits="userSpaceOnUse" + x2="15.515" + y1="31.368" + x1="18.113"> + <stop + id="stop3098" + stop-color="#424242" + offset="0" /> + <stop + id="stop3100" + stop-color="#777" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient9772" + y2="32.05" + gradientUnits="userSpaceOnUse" + x2="22.065" + y1="36.988" + x1="22.176"> + <stop + id="stop9768" + stop-color="#6194cb" + offset="0" /> + <stop + id="stop9770" + stop-color="#729fcf" + offset="1" /> + </linearGradient> + </defs> + <g + id="layer1"> + <g + id="g6707" + transform="matrix(0.022624,0,0,0.020868,43.383,36.37)"> + <rect + id="rect6709" + height="478.35999" + width="1339.6" + y="-150.7" + x="-1559.3" + style="opacity:0.40206;fill:url(#linearGradient6715)" /> + <path + id="path6711" + d="m -219.62,-150.68 v 478.33 c 142.88,0.9 345.4,-107.17 345.4,-239.2 0,-132.02 -159.44,-239.13 -345.4,-239.13 z" + inkscape:connector-curvature="0" + style="opacity:0.40206;fill:url(#radialGradient6717)" /> + <path + id="path6713" + d="m -1559.3,-150.68 v 478.33 c -142.8,0.9 -345.4,-107.17 -345.4,-239.2 0,-132.02 159.5,-239.13 345.4,-239.13 z" + inkscape:connector-curvature="0" + style="opacity:0.40206;fill:url(#radialGradient6719)" /> + </g> + <path + id="path216" + d="m 4.5218,38.687 c 0.0218,0.417 0.4599,0.833 0.8762,0.833 h 31.327 c 0.416,0 0.811,-0.416 0.789,-0.833 L 36.578,11.461 c -0.022,-0.417 -0.46,-0.833 -0.877,-0.833 h -13.27 c -0.486,0 -1.235,-0.316 -1.402,-1.1066 L 20.417,6.6284 C 20.262,5.8927 19.535,5.5905 19.119,5.5905 H 4.34 c -0.4162,0 -0.8107,0.4163 -0.7889,0.8326 l 0.9707,32.264 z" + inkscape:connector-curvature="0" + style="fill:url(#radialGradient238);stroke:url(#linearGradient3104);stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9788" + d="m 5.2266,22.562 h 30.265" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9784" + d="m 5.0422,18.562 h 30.447" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9778" + d="m 4.9807,12.562 h 30.507" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9798" + d="m 5.3862,32.562 h 30.109" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9800" + d="m 5.5091,34.562 h 29.988" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9782" + d="m 5.0422,16.562 h 30.447" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9780" + d="m 5.0114,14.562 h 30.478" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9776" + d="m 4.9221,10.562 h 15.281" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9774" + d="m 4.8738,8.5625 h 14.783" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9794" + d="m 5.3247,28.562 h 30.169" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9792" + d="m 5.2881,26.562 h 30.205" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9790" + d="m 5.2266,24.562 h 30.265" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9786" + d="m 5.1959,20.562 h 30.296" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9796" + d="m 5.3247,30.562 h 30.169" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9802" + d="m 5.5091,36.562 h 29.988" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path219" + d="M 6.0683,38.864 C 6.0847,39.176 5.8874,39.384 5.5698,39.28 5.2521,39.176 5.033,38.968 5.0167,38.656 L 4.069,6.591 C 4.0526,6.2792 4.2341,6.0906 4.5464,6.0906 l 14.422,-0.0477 c 0.313,0 0.932,0.3005 1.133,1.3222 l 0.574,2.8159 c -0.427,-0.4656 -0.419,-0.48 -0.638,-1.1571 l -0.406,-1.2592 c -0.219,-0.7276 -0.698,-0.8319 -1.01,-0.8319 H 5.7334 c -0.3122,0 -0.5095,0.2082 -0.4931,0.5204 l 0.938,31.515 -0.1096,-0.104 z" + display="block" + inkscape:connector-curvature="0" + style="display:block;opacity:0.45143002;fill:url(#linearGradient491)" /> + <g + id="g220" + transform="matrix(1.0408,0,0.054493,1.0408,-8.6702,2.6706)" + style="fill:#ffffff;fill-opacity:0.75705997"> + <path + id="path221" + d="M 42.417,8.5152 C 42.422,8.4181 42.289,8.2682 42.182,8.2682 L 29.151,8.2661 c 0,0 0.911,0.5879 2.201,0.5962 l 11.054,0.071 c 0.011,-0.2117 0.003,-0.256 0.011,-0.4181 z" + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:0.50847" /> + </g> + <path + id="path233" + d="M 39.784,39.511 C 40.927,39.467 41.747,38.414 41.831,37.19 42.622,25.641 43.49,15.958 43.49,15.958 43.562,15.71 43.322,15.463 43.01,15.463 H 8.639 c -4e-4,0 -1.8507,21.867 -1.8507,21.867 -0.1145,0.982 -0.466,1.804 -1.5498,2.183 l 34.546,-0.002 z" + display="block" + inkscape:connector-curvature="0" + style="display:block;fill:url(#linearGradient9772);stroke:#3465a4;stroke-linejoin:round" /> + <path + id="path304" + d="m 9.6202,16.464 32.791,0.065 -1.574,20.002 c -0.084,1.071 -0.45,1.428 -1.872,1.428 -1.872,0 -28.678,-0.032 -31.395,-0.032 0.2335,-0.321 0.3337,-0.989 0.335,-1.005 L 9.6204,16.464 Z" + inkscape:connector-curvature="0" + style="opacity:0.46591001;fill:none;stroke:url(#linearGradient322);stroke-width:1px;stroke-linecap:round" /> + <path + id="path323" + d="M 9.6202,16.223 8.4536,31.866 c 0,0 8.2964,-4.148 18.666,-4.148 10.3696,0 15.555,-11.495 15.555,-11.495 H 9.6196 Z" + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:0.089286;fill-rule:evenodd" /> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="4.9807" + y="12.562" + id="text872"><tspan + sodipodi:role="line" + id="tspan870" + x="4.9807" + y="47.952625" /></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="12.084706" + y="-1.9200009" + id="text876"><tspan + sodipodi:role="line" + id="tspan874" + x="12.084706" + y="33.470623" /></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:43.91484451px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.09787118" + x="1.1159539" + y="28.247671" + id="text880" + transform="scale(0.91085367,1.0978712)"><tspan + sodipodi:role="line" + id="tspan878" + x="1.1159539" + y="28.247671" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.56593895px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:1.09787118">REST</tspan></text> +</svg> diff --git a/stackviz/resources.qrc b/stackviz/resources.qrc index 66b2cd2e6d643fcccc1a7dd09023aa367c7632e2..06d4035131398e215b943b32a3e542b52f76edd7 100644 --- a/stackviz/resources.qrc +++ b/stackviz/resources.qrc @@ -4,6 +4,7 @@ <file>icons/folder-bc.svg</file> <file>icons/folder-csv.svg</file> <file>icons/folder-h5.svg</file> + <file>icons/folder-rest.svg</file> <file>icons/autofocus.svg</file> <file>icons/focus.svg</file> <file>icons/logoVGLab.png</file> diff --git a/stackviz/stackviz.cpp b/stackviz/stackviz.cpp index 39b9e9e875348bcffeabdaf03d3d24362a2f258b..5cc8dc53c7faf0bcfeaa6cdf3bf5037a9c5cddaa 100644 --- a/stackviz/stackviz.cpp +++ b/stackviz/stackviz.cpp @@ -268,7 +268,28 @@ int main( int argc, char** argv ) if (dataType != simil::TDataType::TDataUndefined) { - mainWindow.loadData(dataType, networkFile, activityFile, simType); + switch(dataType) + { + case simil::TDataType::TREST: + { +#ifdef SIMIL_WITH_REST_API + simil::LoaderRestData::Configuration config; + config.url = networkFile; + config.port = stoi(activityFile); + config.api = simil::LoaderRestData::Rest_API::NEST; + + mainWindow.loadRESTData(config); +#else + std::cerr << "REST API not supported." << std::endl; + return -1; +#endif + + } + break; + default: + mainWindow.loadData(dataType, networkFile, activityFile, simType); + break; + } if (dataType == simil::TDataType::THDF5) { diff --git a/stackviz/stackviz.ui b/stackviz/stackviz.ui index b16ef1c456c55b4496768de386d56c504c4e446d..d88a43f25429b712cf82f9ff77752b1f516f2701 100644 --- a/stackviz/stackviz.ui +++ b/stackviz/stackviz.ui @@ -33,11 +33,13 @@ </property> <addaction name="actionOpenBlueConfig"/> <addaction name="actionOpenCSVFiles"/> - <addaction name="actionCloseData"/> <addaction name="actionOpenH5Files"/> + <addaction name="actionConnectRESTserver"/> <addaction name="separator"/> <addaction name="actionOpenSubsetEventsFile"/> <addaction name="separator"/> + <addaction name="actionCloseData"/> + <addaction name="separator"/> <addaction name="actionQuit"/> </widget> <widget class="QMenu" name="menuHelp"> @@ -56,6 +58,8 @@ <addaction name="actionFill_Plots"/> <addaction name="actionShowPanels"/> <addaction name="actionAddZeroEQhistograms"/> + <addaction name="separator"/> + <addaction name="actionConfigureRESTconnection"/> </widget> <widget class="QMenu" name="menuPlayback"> <property name="title"> @@ -90,11 +94,11 @@ <addaction name="actionOpenBlueConfig"/> <addaction name="actionOpenCSVFiles"/> <addaction name="actionOpenH5Files"/> + <addaction name="actionConnectRESTserver"/> <addaction name="separator"/> <addaction name="actionOpenSubsetEventsFile"/> <addaction name="separator"/> <addaction name="actionTogglePlaybackDock"/> - <addaction name="actionCloseData"/> <addaction name="actionShowDataManager"/> <addaction name="actionShowPanels"/> <addaction name="separator"/> @@ -104,20 +108,15 @@ <addaction name="actionFill_Plots"/> <addaction name="separator"/> </widget> - <action name="actionQuit"> - <property name="text"> - <string>Quit</string> - </property> - <property name="shortcut"> - <string>Ctrl+Q</string> - </property> - </action> <action name="actionAbout"> <property name="text"> <string>About ...</string> </property> </action> <action name="actionOpenBlueConfig"> + <property name="enabled"> + <bool>false</bool> + </property> <property name="icon"> <iconset resource="resources.qrc"> <normaloff>:/icons/folder-bc.svg</normaloff>:/icons/folder-bc.svg</iconset> @@ -141,7 +140,7 @@ <normaloff>:/icons/close.svg</normaloff>:/icons/close.svg</iconset> </property> <property name="text"> - <string>Close Data</string> + <string>Close Dataset</string> </property> <property name="toolTip"> <string>Close Data</string> @@ -150,7 +149,7 @@ <string>Ctrl+Shift+C</string> </property> <property name="visible"> - <bool>false</bool> + <bool>true</bool> </property> <property name="iconVisibleInMenu"> <bool>true</bool> @@ -310,6 +309,37 @@ <string>Advanced recorder options</string> </property> </action> + <action name="actionConfigureRESTconnection"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Configure REST connection...</string> + </property> + <property name="toolTip"> + <string>Configure REST connection options.</string> + </property> + </action> + <action name="actionConnectRESTserver"> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/icons/folder-rest.svg</normaloff>:/icons/folder-rest.svg</iconset> + </property> + <property name="text"> + <string>Connect to REST server...</string> + </property> + <property name="toolTip"> + <string>Connect to a REST API server.</string> + </property> + </action> + <action name="actionQuit"> + <property name="text"> + <string>Quit</string> + </property> + <property name="shortcut"> + <string>Ctrl+Q</string> + </property> + </action> </widget> <resources> <include location="resources.qrc"/> diff --git a/sumrice/CMakeLists.txt b/sumrice/CMakeLists.txt index 84384c7a548079192b555cc4b9632586c521cf04..655d7702ec91038564d338142a41b3deddf1b89e 100644 --- a/sumrice/CMakeLists.txt +++ b/sumrice/CMakeLists.txt @@ -25,6 +25,8 @@ set(SUMRICE_PUBLIC_HEADERS DataInspector.h DisplayManagerWidget.h StackViz.h + ConfigureRESTDialog.h + ConnectRESTDialog.h ) set(SUMRICE_HEADERS @@ -46,6 +48,8 @@ set(SUMRICE_SOURCES DataInspector.cpp DisplayManagerWidget.cpp StackViz.cpp + ConfigureRESTDialog.cpp + ConnectRESTDialog.cpp ) set(SUMRICE_LINK_LIBRARIES diff --git a/sumrice/ConfigureRESTDialog.cpp b/sumrice/ConfigureRESTDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2165c6e76bec7efd1edd4c60c8f6ca8fcbababd --- /dev/null +++ b/sumrice/ConfigureRESTDialog.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2022-2022 VG-Lab/URJC. + * + * Authors: Félix de las Pozas Ãlvarez <felix.delaspozas@urjc.es> + * + * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +// Sumrice +#include <sumrice/ConfigureRESTDialog.h> + +// Qt +#include <QSpinBox> +#include <QVBoxLayout> +#include <QGridLayout> +#include <QLabel> +#include <QDialogButtonBox> + +//----------------------------------------------------------------------------- +RESTConfigurationWidget::RESTConfigurationWidget(QWidget *p, Qt::WindowFlags f) +: QWidget(p,f) +{ + m_waitTime = new QSpinBox(); + m_waitTime->setMinimum(1000); + m_waitTime->setMaximum(10000); + m_waitTime->setValue(5000); + m_waitTime->setSuffix(" ms"); + + m_spikesSize = new QSpinBox(); + m_spikesSize->setMinimum(100); + m_spikesSize->setMaximum(10000); + m_spikesSize->setValue(1000); + m_spikesSize->setSuffix(" spikes"); + + auto layout = new QGridLayout(); + layout->addWidget(new QLabel("Time between requests:"), 0, 0); + layout->addWidget(m_waitTime, 0, 1); + layout->addWidget(new QLabel("Request size:"), 2, 0); + layout->addWidget(m_spikesSize, 2, 1); + + setLayout(layout); + layout->setColumnStretch(0,0); + layout->setColumnStretch(1,1); +} + +//----------------------------------------------------------------------------- +void RESTConfigurationWidget::setOptions(const Options &o) +{ + m_waitTime->setValue(o.waitTime); + m_spikesSize->setValue(o.spikesSize); +} + +//----------------------------------------------------------------------------- +RESTConfigurationWidget::Options RESTConfigurationWidget::getOptions() const +{ + Options result; + result.waitTime = m_waitTime->value(); + result.spikesSize = m_spikesSize->value(); + + return result; +} + +//----------------------------------------------------------------------------- +ConfigureRESTDialog::ConfigureRESTDialog(QWidget *p, Qt::WindowFlags f, const RESTConfigurationWidget::Options &o) +: QDialog(p,f) +{ + auto layout = new QVBoxLayout(); + setLayout(layout); + + m_options = new RESTConfigurationWidget(this); + m_options->setOptions(o); + + auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + + layout->addWidget(m_options, 1); + layout->addWidget(buttons,0); + + setSizeGripEnabled(false); + setModal(true); + setFixedWidth(440); +} + +//----------------------------------------------------------------------------- +RESTConfigurationWidget::Options ConfigureRESTDialog::getRESTOptions() const +{ + return m_options->getOptions(); +} + +//----------------------------------------------------------------------------- +void ConfigureRESTDialog::setRESTOptions(const RESTConfigurationWidget::Options &o) +{ + m_options->setOptions(o); +} diff --git a/sumrice/ConfigureRESTDialog.h b/sumrice/ConfigureRESTDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..7f765441ebf4c627b3609e7c04c5e8d7cbe7c722 --- /dev/null +++ b/sumrice/ConfigureRESTDialog.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2022-2022 VG-Lab/URJC. + * + * Authors: Félix de las Pozas Ãlvarez <felix.delaspozas@urjc.es> + * + * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef SUMRICE_CONFIGURERESTDIALOG_H_ +#define SUMRICE_CONFIGURERESTDIALOG_H_ + +#include <QDialog> +#include <QWidget> + +class QSpinBox; + +/** \class RESTConfigurationWidget + * \brief Implements a widget with the REST configuration options. + * + */ +class RESTConfigurationWidget +: public QWidget +{ + Q_OBJECT + public: + /** \brief RESTConfigurationWidget class constructor. + * \param[in] parent Raw pointer of the QWidget parent of this one. + * \param[in] f Qt widget flags. + * + */ + explicit RESTConfigurationWidget(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + + /** \brief RESTConfigurationWidget class virtual destructor. + * + */ + virtual ~RESTConfigurationWidget() + {}; + + /** \struct Options + * \brief Contains the REST options. + * + */ + struct Options + { + unsigned int waitTime; /** time to wait in ms after a successful call. */ + unsigned int failTime; /** time to wait in ms after a failed call. */ + unsigned int spikesSize; /** size of spikes to ask in a call. */ + + Options(): waitTime(5000), failTime(1000), spikesSize(1000) {}; + }; + + /** \brief Sets the widget options values. + * \param[in] o Options struct reference. + * + */ + void setOptions(const Options &o); + + /** \brief Returns the widget values as a Options struct. + * + */ + Options getOptions() const; + + private: + QSpinBox *m_waitTime; /** wait time value spinbox. */ + QSpinBox *m_spikesSize; /** spikes size value spinbox. */ +}; + +/** \class ConfigureRESTDialog + * \brief Implements a dialog to configure REST connection options. + * + */ +class ConfigureRESTDialog +: public QDialog +{ + Q_OBJECT + public: + /** \brief ConfigureRESTDialog class constructor. + * \param[in] parent Raw pointer of the widget parent of this one. + * \param[in] f Qt dialog flags. + * \param[in] o REST configuration options initial values. + * + */ + explicit ConfigureRESTDialog(QWidget *parent = nullptr, + Qt::WindowFlags f = Qt::WindowFlags(), + const RESTConfigurationWidget::Options &o = RESTConfigurationWidget::Options()); + + /** \brief ConfigureRESTDialog class virtual destructor. + * + */ + virtual ~ConfigureRESTDialog() + {} + + /** \brief Returns the configured options. + * + */ + RESTConfigurationWidget::Options getRESTOptions() const; + + /** \brief Sets the options values. + * + */ + void setRESTOptions(const RESTConfigurationWidget::Options &o); + + private: + RESTConfigurationWidget *m_options; /** options widget */ +}; + +#endif /* SUMRICE_CONFIGURERESTDIALOG_H_ */ diff --git a/sumrice/ConnectRESTDialog.cpp b/sumrice/ConnectRESTDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3c64c001bd9e7518db29044814ad0502f18ce94 --- /dev/null +++ b/sumrice/ConnectRESTDialog.cpp @@ -0,0 +1,102 @@ +/* + * ConnectRESTDialog.cpp + * + * Created on: May 5, 2022 + * Author: felix + */ + +// Sumrice +#include <sumrice/ConnectRESTDialog.h> + +// Qt +#include <QComboBox> +#include <QVBoxLayout> +#include <QGridLayout> +#include <QLineEdit> +#include <QLabel> +#include <QGroupBox> +#include <QDialogButtonBox> + +const QStringList PROTOCOLS = { "NEST", "ARBOR" }; + +//----------------------------------------------------------------------------- +ConnectRESTDialog::ConnectRESTDialog(QWidget *p, Qt::WindowFlags f) +: QDialog(p,f) +{ + auto layout = new QVBoxLayout(); + setLayout(layout); + + Connection connection; + + m_protocol = new QComboBox(); + m_protocol->addItems(PROTOCOLS); + m_protocol->setCurrentIndex(connection.protocol.compare("NEST", Qt::CaseInsensitive) == 0 ? 0 : 1); + + // @felix Enable when ARBOR plugin has been tested. + m_protocol->setEnabled(false); + + m_url = new QLineEdit(); + m_url->setText(connection.url); + + m_port = new QLineEdit(); + m_port->setText(QString::number(connection.port)); + + auto glo = new QGridLayout(); + glo->addWidget(new QLabel("Protocol: "), 0, 0); + glo->addWidget(m_protocol, 0, 1); + glo->addWidget(new QLabel("IP address: "), 1, 0); + glo->addWidget(m_url, 1, 1); + glo->addWidget(new QLabel("Port: "), 2, 0); + glo->addWidget(m_port, 2, 1); + + layout->addLayout(glo,1); + + m_options = new RESTConfigurationWidget(this); + + auto group = new QGroupBox("REST Options"); + group->setLayout(new QVBoxLayout()); + group->layout()->addWidget(m_options); + + layout->addWidget(group, 1); + + auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + + layout->addWidget(buttons,0); + + setSizeGripEnabled(false); + setModal(true); + setFixedWidth(440); +} + +//----------------------------------------------------------------------------- +void ConnectRESTDialog::setRESTConnection(const Connection &r) +{ + m_protocol->setCurrentIndex(r.protocol == "NEST" ? 0 : 1); + m_url->setText(r.url); + m_port->setText(QString::number(r.port)); +} + +//----------------------------------------------------------------------------- +ConnectRESTDialog::Connection ConnectRESTDialog::getRESTConnection() const +{ + Connection result; + result.protocol = m_protocol->currentIndex() == 0 ? "NEST" : "ARBOR"; + result.url = m_url->text(); + result.port = m_port->text().toInt(); + + return result; +} + +//----------------------------------------------------------------------------- +void ConnectRESTDialog::setRESTOptions(const RESTConfigurationWidget::Options &o) +{ + m_options->setOptions(o); +} + +//----------------------------------------------------------------------------- +RESTConfigurationWidget::Options ConnectRESTDialog::getRESTOptions() const +{ + return m_options->getOptions(); +} diff --git a/sumrice/ConnectRESTDialog.h b/sumrice/ConnectRESTDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..48353f2a2241337b63cb9439b88545427a9457c2 --- /dev/null +++ b/sumrice/ConnectRESTDialog.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022-2022 VG-Lab/URJC. + * + * Authors: Félix de las Pozas Ãlvarez <felix.delaspozas@urjc.es> + * + * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef SUMRICE_CONNECTRESTDIALOG_H_ +#define SUMRICE_CONNECTRESTDIALOG_H_ + +// Sumrice +#include <sumrice/ConfigureRESTDialog.h> + +// Qt +#include <QDialog> + +class QComboBox; +class QLineEdit; + +/** \class ConnectRESTDialog + * \brief Implements a dialog for a REST connection configuration. + * + */ +class ConnectRESTDialog +: public QDialog +{ + Q_OBJECT + public: + /** \brief ConnectRESTDialog class constructor. + * \param[in] parent Raw pointer of the widget parent of this one. + * \param[in] f Qt dialog flags. + * + */ + explicit ConnectRESTDialog(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + + /** \brief ConnectRESTDialog class virtual destructor. + * + */ + virtual ~ConnectRESTDialog() + {}; + + struct Connection + { + QString protocol; + QString url; + unsigned int port; + + Connection(): protocol("NEST"), url("localhost"), port(28080) {}; + }; + + /** \brief Sets the connection values. + * \param[in] r RESTConnection struct reference. + * + */ + void setRESTConnection(const Connection &r); + + /** \brief Returns the REST connection options. + * + */ + Connection getRESTConnection() const; + + /** \brief Sets the REST configuration values. + * \param[in] o RESTConfigurationWidget options struct reference. + * + */ + void setRESTOptions(const RESTConfigurationWidget::Options &o); + + /** \brief Returns the REST configuration options values. + * + */ + RESTConfigurationWidget::Options getRESTOptions() const; + + private: + QComboBox *m_protocol; /** REST protocol, NEST or ARBOR. */ + QLineEdit *m_url; /** url of server. */ + QLineEdit *m_port; /** port of server. */ + RESTConfigurationWidget *m_options; /** REST configuration options widget. */ +}; + +#endif /* SUMRICE_CONNECTRESTDIALOG_H_ */ diff --git a/sumrice/DataInspector.cpp b/sumrice/DataInspector.cpp index 643df99b8956582200823fb4aed1f335d8142309..321b29cbc03263ccbab7d749dfd28b5bad18e147 100644 --- a/sumrice/DataInspector.cpp +++ b/sumrice/DataInspector.cpp @@ -30,6 +30,8 @@ #include <QGridLayout> #include <QLabel> +constexpr int DEFAULT_CKECK_INTERVAL = 5000; + DataInspector::DataInspector( const QString& title, QWidget* parent ) : QGroupBox( title, parent ) , _gidsize( 0 ) @@ -39,22 +41,26 @@ DataInspector::DataInspector( const QString& title, QWidget* parent ) , _labelStartTime( nullptr ) , _labelEndTime( nullptr ) , _simPlayer( nullptr ) + , m_check{false} { _labelGIDs = new QLabel( QString::number( _gidsize ) ); _labelSpikes = new QLabel( QString::number( _spikesize ) ); _labelStartTime = new QLabel( "0" ); _labelEndTime = new QLabel( "0" ); - QGridLayout* oiLayout = new QGridLayout( ); - oiLayout->setAlignment( Qt::AlignTop ); - oiLayout->addWidget( new QLabel( "Network Information:" ), 0, 0, 1, 1 ); - oiLayout->addWidget( _labelGIDs, 0, 1, 1, 3 ); - oiLayout->addWidget( new QLabel( "Simulation Spikes: " ), 1, 0, 1, 1 ); - oiLayout->addWidget( _labelSpikes, 1, 1, 1, 3 ); - oiLayout->addWidget( new QLabel( "Start Time: " ), 4, 0, 1, 1 ); - oiLayout->addWidget( _labelStartTime, 4, 1, 1, 3 ); - oiLayout->addWidget( new QLabel( "End Time: " ), 5, 0, 1, 1 ); - oiLayout->addWidget( _labelEndTime, 5, 1, 1, 3 ); - setLayout( oiLayout ); + QGridLayout* gLayout = new QGridLayout( ); + gLayout->setAlignment( Qt::AlignTop ); + gLayout->addWidget( new QLabel( "Network Information:" ), 0, 0, 1, 1 ); + gLayout->addWidget( _labelGIDs, 0, 1, 1, 3 ); + gLayout->addWidget( new QLabel( "Simulation Spikes: " ), 1, 0, 1, 1 ); + gLayout->addWidget( _labelSpikes, 1, 1, 1, 3 ); + gLayout->addWidget( new QLabel( "Start Time: " ), 4, 0, 1, 1 ); + gLayout->addWidget( _labelStartTime, 4, 1, 1, 3 ); + gLayout->addWidget( new QLabel( "End Time: " ), 5, 0, 1, 1 ); + gLayout->addWidget( _labelEndTime, 5, 1, 1, 3 ); + setLayout( gLayout ); + + m_timer.setInterval(DEFAULT_CKECK_INTERVAL); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(updateInfo())); } void DataInspector::addWidget( QWidget* widget, int row, int column, @@ -67,7 +73,31 @@ void DataInspector::addWidget( QWidget* widget, int row, int column, void DataInspector::setSimPlayer( simil::SimulationPlayer* simPlayer_ ) { + const auto timerActive = m_timer.isActive(); + if(timerActive) m_timer.stop(); + _simPlayer = simPlayer_; + _gidsize = 0; + _spikesize = 0; + + if(timerActive) m_timer.start(); +} + +void DataInspector::setCheckUpdates(const bool value) +{ + if(value != m_check) + { + m_check = value; + + if(m_check) + { + m_timer.start(); + } + else + { + m_timer.stop(); + } + } } void DataInspector::paintEvent( QPaintEvent* event ) @@ -103,4 +133,27 @@ void DataInspector::updateInfo( ) if ( updated ) emit simDataChanged( ); } + else + { + _labelGIDs = new QLabel( "0" ); + _labelSpikes = new QLabel( "0" ); + _labelStartTime = new QLabel( "0" ); + _labelEndTime = new QLabel( "0" ); + } +} + +void DataInspector::setCheckTimer(const int ms) +{ + if(m_timer.interval() == ms) return; + + if(m_timer.isActive()) + { + m_timer.stop(); + m_timer.setInterval(ms); + m_timer.start(); + } + else + { + m_timer.setInterval(ms); + } } diff --git a/sumrice/DataInspector.h b/sumrice/DataInspector.h index 75c39b4e4c82b0a280d3a457d48e643bf2edeefa..02de720370a9bbb272f4144eb7575f3aa3f59626 100644 --- a/sumrice/DataInspector.h +++ b/sumrice/DataInspector.h @@ -25,6 +25,7 @@ // Qt #include <QGroupBox> +#include <QTimer> // Simil #include <simil/simil.h> @@ -37,21 +38,37 @@ class DataInspector : public QGroupBox Q_OBJECT public: DataInspector(const QString &title, QWidget *parent = nullptr); + virtual ~DataInspector() {}; void addWidget(QWidget *widget, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment()); + /** \brief Sets the simulation player to check for updates. + * \param[in] simPlayer_ Simulation player raw pointer. + * + */ void setSimPlayer(simil::SimulationPlayer * simPlayer_); -public slots: - void updateInfo( void ); + /** \brief Enables/disables the player update checks. + * \param[in] value True to enable false otherwise. + * + */ + void setCheckUpdates(const bool value); + + /** \brief Check for player updates interval, default 5000 milliseconds. + * + */ + void setCheckTimer(const int ms); signals: void simDataChanged( void ); +protected slots: + void updateInfo( void ); + protected: - virtual void paintEvent(QPaintEvent *event); + virtual void paintEvent(QPaintEvent *e); unsigned int _gidsize; unsigned int _spikesize; @@ -60,6 +77,8 @@ protected: QLabel *_labelStartTime; QLabel *_labelEndTime; simil::SimulationPlayer * _simPlayer; + bool m_check; + QTimer m_timer; }; #endif // DATAINSPECTOR_H diff --git a/sumrice/DisplayManagerWidget.h b/sumrice/DisplayManagerWidget.h index 0637205c7083b78cf6dce60368456b1c95014986..b66c0b9c641eb1d30ac3ac712031e17ec8267515 100644 --- a/sumrice/DisplayManagerWidget.h +++ b/sumrice/DisplayManagerWidget.h @@ -32,14 +32,12 @@ class QPushButton; namespace visimpl { - typedef enum { TDM_E_CONTAINER = 0, TDM_E_NAME, TDM_E_SHOW, TDM_E_DELETE, -// TDM_E_LINE, TDM_E_MAXCOLUMN } TDispMngrEventName; @@ -47,7 +45,6 @@ namespace visimpl QLabel*, QPushButton*, QPushButton* -// QFrame* > TDisplayEventTuple; typedef enum @@ -112,15 +109,9 @@ namespace visimpl void refreshEvents( void ); void refreshHistograms( void ); -// QTableWidget* _eventTable; -// QTableWidget* _histoTable; - const std::vector< visimpl::EventWidget* >* _eventData; const std::vector< visimpl::HistogramWidget* >* _histData; -// std::vector< visimpl::EventWidget* > _availableEvents; -// std::vector< visimpl::HistogramWidget* > _availableHistograms; - std::vector< TDisplayEventTuple > _events; std::vector< TDisplayHistogramTuple > _histograms; @@ -130,8 +121,6 @@ namespace visimpl bool _dirtyFlagEvents; bool _dirtyFlagHistograms; }; - - } #endif /* DISPLAYMANAGERWIDGET_H_ */ diff --git a/sumrice/LoaderThread.cpp b/sumrice/LoaderThread.cpp index 77cc7c31ebf6f64eeb737db2ab0868d1977bd372..2f1c863e43b59e1d4ff93f3c518d43fa4d48f922 100644 --- a/sumrice/LoaderThread.cpp +++ b/sumrice/LoaderThread.cpp @@ -54,6 +54,8 @@ void LoaderThread::setData(const simil::TDataType type, const std::string &arg1, const std::string &arg2) { + assert(type != simil::TDataType::TREST); + m_type = type; m_arg1 = arg1; m_arg2 = arg2; @@ -106,15 +108,31 @@ void LoaderThread::run() #ifdef SIMIL_WITH_REST_API m_rest = new simil::LoaderRestData(); m_rest->deltaTime(REST_DELTATIME); - m_network = m_rest->loadNetwork(m_arg1, m_arg2); - m_data = m_rest->loadSimulationData(m_arg1, m_arg2); + m_rest->setConfiguration(m_restConfig); + + const auto url = m_restConfig.url; + const auto port = std::to_string(m_restConfig.port); + const auto version = m_rest->getVersion(url, m_restConfig.port); + + std::cout << "REST api version " << version.api << " - insite pipeline version " << version.insite << std::endl; + + if(version.api.empty() || version.insite.empty()) + { + m_errors = std::string("Unknown protocol connecting to ") + + m_restConfig.url + ":" + std::to_string(m_restConfig.port); + break; + } + + m_network = m_rest->loadNetwork(url, port); + m_data = m_rest->loadSimulationData(url, port); unsigned int oldSpikes = 0, oldNetwork = 0; - for(int i = 0; i < 5; ++i) + unsigned int count = 0; + while(count < 5 || oldNetwork < 2) { QThread::sleep(1); const auto newNetwork = m_network->gidsSize(); - if(newNetwork != oldNetwork) + if(newNetwork != oldNetwork && newNetwork > 2) { oldNetwork = newNetwork; emit network(newNetwork); @@ -126,7 +144,17 @@ void LoaderThread::run() oldSpikes = newSpikes; emit spikes(newSpikes); } + + ++count; + + if(count > 60) + { + m_errors = std::string("Unable to connect to ") + + m_restConfig.url + ":" + std::to_string(m_restConfig.port); + break; + } } + emit progress(50); #else m_errors = "REST data loading is unsupported."; @@ -142,16 +170,16 @@ void LoaderThread::run() } catch(const std::exception &ex) { - m_errors = std::string("simil::LoaderThread::run() -> ") + std::string(ex.what()); + m_errors = std::string("sumrice::LoaderThread::run() -> ") + std::string(ex.what()); } catch(...) { - m_errors = std::string("simil::LoaderThread::run() -> Unhandled exception when loading data. "); + m_errors = std::string("sumrice::LoaderThread::run() -> Un-handled exception when loading data. "); } emit progress(75); - if(!m_errors.empty()) + if(!m_errors.empty() && m_type != simil::TDataType::TREST) { m_errors += std::string("\ndata type: ") + std::to_string(static_cast<int>(m_type)); m_errors += std::string(" argument 1: ") + m_arg1; @@ -160,3 +188,26 @@ void LoaderThread::run() emit progress(100); } + +#ifdef SIMIL_WITH_REST_API +simil::LoaderRestData *LoaderThread::RESTLoader() +{ + if(m_type != simil::TDataType::TREST) + { + throw std::logic_error("No REST data loader!"); + } + + return m_rest; +} + +void LoaderThread::setRESTConfiguration(const simil::LoaderRestData::Configuration &config) +{ + m_type = simil::TDataType::TREST; + m_restConfig = config; + + if(m_rest) + { + m_rest->setConfiguration(m_restConfig); + } +} +#endif diff --git a/sumrice/LoaderThread.h b/sumrice/LoaderThread.h index accf1a2ecc5410e2bdac418c890da3acae017aee..daf5fce86be61dc9c2d6ca5a9a43d8100902fc99 100644 --- a/sumrice/LoaderThread.h +++ b/sumrice/LoaderThread.h @@ -29,6 +29,9 @@ // Simil #include <simil/types.h> #include <simil/api.h> +#ifdef SIMIL_WITH_REST_API +#include <simil/loaders/LoaderRestData.h> +#endif // Qt #include <QThread> @@ -41,11 +44,6 @@ namespace simil { class Network; class SimulationData; - class LoaderRestData; - -#ifdef SIMIL_WITH_REST_API - class LoaderRestData; -#endif } @@ -68,7 +66,8 @@ class SUMRICE_API LoaderThread */ virtual ~LoaderThread(); - /** \brief Set the information for the data to load. + /** \brief Set the information for the data to load. If data + * is REST use setRESTConfiguration(). * \param[in] type Data origin type. * \param[in] arg1 Load argument 1. * \param[in] arg1 Load argument 1. @@ -99,6 +98,19 @@ class SUMRICE_API LoaderThread */ simil::TDataType type() const; +#ifdef SIMIL_WITH_REST_API + /** \brief Sets the REST loader protocol configuration. + * \param[in] o REST protocol configuration. + * + */ + void setRESTConfiguration(const simil::LoaderRestData::Configuration &o); + + /** \brief Returns the REST loader. + * + */ + simil::LoaderRestData *RESTLoader(); +#endif + protected: virtual void run(); @@ -108,15 +120,18 @@ class SUMRICE_API LoaderThread void network(unsigned int); private: - simil::TDataType m_type; /** data origin type. */ - std::string m_arg1; /** argument 1, meaning depends on type. */ - std::string m_arg2; /** argument 2, meaning depends on type. */ - simil::Network* m_network; /** loaded network. */ - simil::SimulationData* m_data; /** loaded data. */ + simil::TDataType m_type; /** data origin type. */ + std::string m_arg1; /** argument 1, meaning depends on type. */ + std::string m_arg2; /** argument 2, meaning depends on type. */ + simil::Network* m_network; /** loaded network. */ + simil::SimulationData* m_data; /** loaded data. */ #ifdef SIMIL_WITH_REST_API - simil::LoaderRestData* m_rest; /** rest data importer. */ + using Loader = simil::LoaderRestData; + + Loader* m_rest; /** rest data importer. */ + Loader::Configuration m_restConfig; /** rest connnection configuration. */ #endif - std::string m_errors; /** error messages or empty if success. */ + std::string m_errors; /** error messages or empty if success. */ }; #endif /* SUMRICE_LOADERTHREAD_H_ */ diff --git a/sumrice/StackViz.cpp b/sumrice/StackViz.cpp index d647a4321e53b1ae0d99785d1a4f5e273b4ddddb..deb9d2d1b2103f0b5afb6bf8e90e209eeec6e0cf 100644 --- a/sumrice/StackViz.cpp +++ b/sumrice/StackViz.cpp @@ -66,26 +66,23 @@ void StackViz::init( simil::SimulationPlayer* player ) QApplication::restoreOverrideCursor( ); } -StackViz::~StackViz( void ) -{ -} - void StackViz::openSubsetEventsFile( bool fromH5 ) { + if(_summary) + { _summary->clearEvents(); - _summary->generateEventsRep( ); - //_summary->importSubsetsFromSubsetMngr( ); + _summary->generateEventsRep(); _autoCalculateCorrelations = fromH5; + } - if( _displayManager ) - _displayManager->refresh( ); + if (_displayManager) _displayManager->refresh(); } void StackViz::showDisplayManagerWidget( ) { if(!_summary) return; - if( !_displayManager) + if(!_displayManager) { _displayManager = new DisplayManagerWidget( ); _displayManager->init( _summary->eventWidgets(), @@ -112,6 +109,8 @@ void StackViz::showDisplayManagerWidget( ) void StackViz::initSummaryWidget( ) { + if(!_player) return; + const bool hasSummary = _summary != nullptr; if(!hasSummary) @@ -198,6 +197,8 @@ void StackViz::removeSubset(const unsigned int i) void StackViz::calculateCorrelations(void) { + if(!_player || !_subsetEventManager) return; + visimpl::CorrelationComputer cc(dynamic_cast<simil::SpikeData*>(_player->data())); const auto eventNames = _subsetEventManager->eventNames(); @@ -280,3 +281,29 @@ void visimpl::StackViz::repaintHistograms() _summary->repaintHistograms(); } } + +void visimpl::StackViz::closeData() +{ + _player = nullptr; + _subsetEventManager = nullptr; + + // remove histograms + if(_summary) + { + while(_summary->histogramsNumber() > 1) + _summary->removeSubset(1); + + layout()->removeWidget(_summary); + _summary->deleteLater(); + _summary = nullptr; + } + + if(_displayManager) + { + if(_displayManager->isVisible()) _displayManager->hide(); + _displayManager->deleteLater(); + _displayManager = nullptr; + } + + _correlations.clear(); +} diff --git a/sumrice/StackViz.h b/sumrice/StackViz.h index eaf5d703ed2a0989f18277254b9a3f57d00ee27c..b4da70661cbda4ad1495d3d1be79559c0f186c98 100644 --- a/sumrice/StackViz.h +++ b/sumrice/StackViz.h @@ -48,7 +48,8 @@ namespace visimpl public: explicit StackViz( QWidget* parent = nullptr ); - virtual ~StackViz( void ); + virtual ~StackViz() + {}; void init( simil::SimulationPlayer* p ); @@ -77,6 +78,11 @@ namespace visimpl */ void setHistogramVisible(const unsigned idx, const bool state); + /** \brief Removes histograms and resets interface. + * + */ + void closeData(); + signals: void changedBins(const unsigned int); diff --git a/sumrice/Summary.cpp b/sumrice/Summary.cpp index 8faa1d183efe0c2b7918764aa6fbc4c6530743b9..95daa57d3c8a8e8a62876fdf95f661cf38581454 100644 --- a/sumrice/Summary.cpp +++ b/sumrice/Summary.cpp @@ -161,20 +161,23 @@ namespace visimpl { _simData = data_; - switch( data_->simulationType()) + if(_simData) { - case simil::TSimSpikes: + switch( data_->simulationType()) { - auto *spikeData = dynamic_cast< simil::SpikeData * >( _simData ); - _spikeReport = spikeData; + case simil::TSimSpikes: + { + auto *spikeData = dynamic_cast< simil::SpikeData * >( _simData ); + _spikeReport = spikeData; - break; + break; + } + default: + break; } - default: - break; - } - _gids = GIDUSet( data_->gids().begin(), data_->gids().end()); + _gids = GIDUSet( data_->gids().begin(), data_->gids().end()); + } Init(); } @@ -361,8 +364,8 @@ namespace visimpl layoutNorm->addWidget( _globalColorWidget , 1 , 1 , 1 , 1 ); layoutNorm->addWidget( globalComboBox , 1 , 2 , 1 , 1 ); - localComboBox->setCurrentIndex(( int ) _colorScaleLocal ); - globalComboBox->setCurrentIndex(( int ) _colorScaleGlobal ); + localComboBox->setCurrentIndex(static_cast<int>(_colorScaleLocal )); + globalComboBox->setCurrentIndex(static_cast<int>( _colorScaleGlobal )); connect( localComboBox , SIGNAL( currentIndexChanged( int )) , @@ -506,9 +509,9 @@ namespace visimpl void Summary::Init() { - if( !_spikeReport ) return; + clear(); - if(_mainHistogram) clear(); + if( !_spikeReport ) return; _mainHistogram = new visimpl::HistogramWidget( *_spikeReport ); _mainHistogram->setMinimumHeight( _heightPerRow ); @@ -663,8 +666,7 @@ namespace visimpl void Summary::importSubsetsFromSubsetMngr( void ) { - simil::SubsetMapRange subsets = - _spikeReport->subsetsEvents()->subsets(); + auto subsets = _spikeReport->subsetsEvents()->subsets(); for( auto it = subsets.first; it != subsets.second; ++it ) { @@ -734,7 +736,6 @@ namespace visimpl insertSubset( selection ); } - } #endif @@ -748,6 +749,8 @@ namespace visimpl h->update(); }; std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), updateHistogram); + + update(); } void Summary::insertSubset( const Selection& selection ) @@ -1136,7 +1139,7 @@ namespace visimpl void Summary::zoomFactor( double zoom ) { - if(_zoomFactor == zoom) return; + if(std::abs(_zoomFactor - zoom) < std::numeric_limits<float>::epsilon()) return; _zoomFactor = zoom; @@ -1317,8 +1320,8 @@ namespace visimpl updateEventWidgets(); - _eventLabelsScroll->setVisible( false ); - _scrollEvent->setVisible( false ); + if(_eventLabelsScroll) _eventLabelsScroll->setVisible( false ); + if(_scrollEvent) _scrollEvent->setVisible( false ); update(); } @@ -1369,7 +1372,6 @@ namespace visimpl delete summaryRow.histogram; _histogramWidgets.erase( _histogramWidgets.begin() + i ); - _histogramRows.erase( _histogramRows.begin() + i ); updateHistogramWidgets(); @@ -1814,18 +1816,41 @@ namespace visimpl { clearEvents(); - auto row = _histogramRows.front(); + switch(_stackType) + { + case TStackType::T_STACK_FIXED: + { + if(_mainHistogram) + { + _histogramWidgets.clear(); + _mainHistogram->hide(); + _layoutHistograms->removeWidget( _mainHistogram); + delete _mainHistogram; + _mainHistogram = nullptr; + } + } + break; + case TStackType::T_STACK_EXPANDABLE: + while(_layoutHistograms->count() > 0 && !_histogramRows.empty()) + { + auto row = _histogramRows.front(); + + if(_layoutHistoLabels && row.label) _layoutHistoLabels->removeWidget( row.label ); + _layoutHistograms->removeWidget( row.histogram ); - _layoutHistoLabels->removeWidget( row.label ); - _layoutHistograms->removeWidget( row.histogram ); + if(row.label) delete row.label; + delete row.histogram; - delete row.label; - delete row.histogram; + _histogramRows.erase( _histogramRows.begin()); + _histogramWidgets.erase( _histogramWidgets.begin()); + } + break; + } - _histogramWidgets.erase( _histogramWidgets.begin()); - _histogramRows.erase( _histogramRows.begin()); + _gids.clear(); + _mainHistogram = nullptr; + _focusedHistogram = nullptr; - while(!_histogramRows.empty()) removeSubset(0); + layout()->activate(); } - } diff --git a/sumrice/Summary.h b/sumrice/Summary.h index 05d3318e8b0c892f8af1d777b918093e22cea8ef..fa1e177487f0af5bc01953b15c27ac0c4b0cd09b 100644 --- a/sumrice/Summary.h +++ b/sumrice/Summary.h @@ -176,6 +176,11 @@ namespace visimpl */ void showConfigPanels(bool value); + /** \brief Removes all widgets. + * + */ + void clear(); + protected slots: void childHistogramPressed( const QPoint&, float ); @@ -206,11 +211,6 @@ namespace visimpl virtual void showEvent(QShowEvent *); - /** \brief Removes all widgets. - * - */ - void clear(); - struct HistogramRow { public: diff --git a/sumrice/TransferFunctionWidget.cpp b/sumrice/TransferFunctionWidget.cpp index 9798809b9b4019dc96f09d0b672e2c9c1e7c1a72..e7c96d314c02927b51fb7c135dd3ed40e6e9b401 100644 --- a/sumrice/TransferFunctionWidget.cpp +++ b/sumrice/TransferFunctionWidget.cpp @@ -78,46 +78,46 @@ void TransferFunctionWidget::InitDialog( void ) _presetsComboBox = new QComboBox( _dialog ); { - QGradientStops stops; - - stops.clear( ); - stops << qMakePair( 0.0, QColor::fromRgbF( 0.0, 1.0, 0.0, 0.2 )) - << qMakePair( 0.35, QColor::fromRgbF( 1.0, 0.0, 0.0, 0.5 )) - << qMakePair( 0.7, QColor::fromRgbF( 1.0, 1.0, 0.0, 0.5 )) - << qMakePair( 1.0, QColor::fromRgbF( 0.0, 0.0, 1.0, 0.5 )); - _presets.push_back( Preset( "Default [ multi-hue]", stops )); - - stops.clear( ); - stops << qMakePair( 0.0, QColor( 255, 0, 0, 127 )) - << qMakePair( 1.0, QColor( 0, 0, 255, 127 )); - _presets.push_back( Preset( "Red-blue [ multi-hue]", stops )); - - stops.clear( ); - stops << qMakePair( 0.0, QColor( 255, 0, 0, 127 )) - << qMakePair( 1.0, QColor( 0, 255, 0, 127 )); - _presets.push_back( Preset( "Red-green [ multi-hue]", stops )); - - stops.clear( ); - stops << qMakePair( 0.0, QColor( 255, 0, 0, 100 )) - << qMakePair( 0.1, QColor( 255, 0, 0, 200 )) - << qMakePair( 1.0, QColor( 0, 0, 0, 20 )); - _presets.push_back( Preset( "Red [ mono-hue]", stops )); - - stops.clear( ); - stops << qMakePair( 0.0, QColor( 0, 255, 0, 100 )) - << qMakePair( 1.0, QColor( 0, 0, 0, 0 )); - _presets.push_back( Preset( "Green [ mono-hue]", stops )); - - stops.clear( ); - stops << qMakePair( 0.0, QColor( 0, 0, 255, 100 )) - << qMakePair( 1.0, QColor( 0, 0, 0, 0 )); - _presets.push_back( Preset( "Blue [ mono-hue]", stops )); - - stops.clear( ); - stops << qMakePair( 0.0, QColor::fromHsv( 60, 255, 255, 100 )) - << qMakePair( 1.0, QColor::fromHsv( 60, 128, 128, 0 )) - << qMakePair( 1.0, QColor::fromHsv( 60, 0, 0, 0 )); - _presets.push_back( Preset( "Yellow [ mono-hue]", stops )); + QGradientStops _stops; + + _stops.clear( ); + _stops << qMakePair( 0.0, QColor::fromRgbF( 0.0, 1.0, 0.0, 0.2 )) + << qMakePair( 0.35, QColor::fromRgbF( 1.0, 0.0, 0.0, 0.5 )) + << qMakePair( 0.7, QColor::fromRgbF( 1.0, 1.0, 0.0, 0.5 )) + << qMakePair( 1.0, QColor::fromRgbF( 0.0, 0.0, 1.0, 0.5 )); + _presets.push_back( Preset( "Default [ multi-hue]", _stops )); + + _stops.clear( ); + _stops << qMakePair( 0.0, QColor( 255, 0, 0, 127 )) + << qMakePair( 1.0, QColor( 0, 0, 255, 127 )); + _presets.push_back( Preset( "Red-blue [ multi-hue]", _stops )); + + _stops.clear( ); + _stops << qMakePair( 0.0, QColor( 255, 0, 0, 127 )) + << qMakePair( 1.0, QColor( 0, 255, 0, 127 )); + _presets.push_back( Preset( "Red-green [ multi-hue]", _stops )); + + _stops.clear( ); + _stops << qMakePair( 0.0, QColor( 255, 0, 0, 100 )) + << qMakePair( 0.1, QColor( 255, 0, 0, 200 )) + << qMakePair( 1.0, QColor( 0, 0, 0, 20 )); + _presets.push_back( Preset( "Red [ mono-hue]", _stops )); + + _stops.clear( ); + _stops << qMakePair( 0.0, QColor( 0, 255, 0, 100 )) + << qMakePair( 1.0, QColor( 0, 0, 0, 0 )); + _presets.push_back( Preset( "Green [ mono-hue]", _stops )); + + _stops.clear( ); + _stops << qMakePair( 0.0, QColor( 0, 0, 255, 100 )) + << qMakePair( 1.0, QColor( 0, 0, 0, 0 )); + _presets.push_back( Preset( "Blue [ mono-hue]", _stops )); + + _stops.clear( ); + _stops << qMakePair( 0.0, QColor::fromHsv( 60, 255, 255, 100 )) + << qMakePair( 1.0, QColor::fromHsv( 60, 128, 128, 0 )) + << qMakePair( 1.0, QColor::fromHsv( 60, 0, 0, 0 )); + _presets.push_back( Preset( "Yellow [ mono-hue]", _stops )); for ( const auto& preset : _presets ) _presetsComboBox->addItem( preset.name( )); diff --git a/visimpl/MainWindow.cpp b/visimpl/MainWindow.cpp index 774c800c991c5635b566ad77995652b810c13150..93b7b7c48a645eb9f3e5df24e82dabfccacae9e4 100644 --- a/visimpl/MainWindow.cpp +++ b/visimpl/MainWindow.cpp @@ -61,7 +61,6 @@ #include <QDockWidget> #include <QPushButton> #include <QSlider> -#include <QTimer> #include <QRadioButton> #include <QGroupBox> #include <QPushButton> @@ -150,8 +149,9 @@ namespace visimpl , _spinBoxClippingDist( nullptr ) , _frameClippingColor( nullptr ) , _buttonSelectionFromClippingPlanes( nullptr ) - , m_type{simil::TDataType::TDataUndefined} , _recorder( nullptr ) + , m_loader{nullptr} + , m_loaderDialog{nullptr} { _ui->setupUi( this ); @@ -181,7 +181,6 @@ namespace visimpl void MainWindow::init( const std::string& zeqUri ) { _openGLWidget = new OpenGLWidget( this, Qt::WindowFlags(), zeqUri ); - connect(_openGLWidget, SIGNAL(dataLoaded()), this, SLOT(onDataLoaded())); this->setCentralWidget( _openGLWidget ); @@ -227,11 +226,21 @@ namespace visimpl connect( _ui->actionOpenH5Files , SIGNAL( triggered( void )) , this , SLOT( openHDF5ThroughDialog( void )) ); + connect( _ui->actionConnectREST , SIGNAL( triggered( void )) , this , + SLOT( openRESTThroughDialog())); + + connect( _ui->actionConfigureREST, SIGNAL(triggered()), this, + SLOT(configureREST())); + connect( _ui->actionOpenSubsetEventsFile , SIGNAL( triggered( void )) , this , SLOT( openSubsetEventsFileThroughDialog( void )) ); _ui->actionOpenSubsetEventsFile->setEnabled(false); +#ifdef SIMIL_WITH_REST_API + _ui->actionConnectREST->setEnabled(true); +#endif + connect( _ui->actionCloseData , SIGNAL( triggered( void )) , this , SLOT( closeData( void )) ); @@ -335,6 +344,8 @@ namespace visimpl #endif delete _ui; + m_loader = nullptr; + closeLoadingDialog( ); } void MainWindow::showStatusBarMessage( const QString& message ) @@ -352,6 +363,7 @@ namespace visimpl _ui->actionToggleStackVizDock->setEnabled(true); _ui->actionOpenSubsetEventsFile->setEnabled(true); + _ui->actionCloseData->setEnabled(true); if(_openGLWidget) { @@ -369,6 +381,8 @@ namespace visimpl UpdateSimulationSlider(percentage); } } + + _simulationDock->setEnabled(true); } void MainWindow::openBlueConfigThroughDialog( void ) @@ -422,8 +436,8 @@ namespace visimpl { _lastOpenedNetworkFileName = QFileInfo( pathNetwork ).path( ); _lastOpenedActivityFileName = QFileInfo( pathActivity ).path( ); - std::string networkFile = pathNetwork.toStdString( ); - std::string activityFile = pathActivity.toStdString( ); + const auto networkFile = pathNetwork.toStdString( ); + const auto activityFile = pathActivity.toStdString( ); loadData(simil::TCSV, networkFile, activityFile, simil::TSimSpikes); } @@ -577,7 +591,29 @@ namespace visimpl void MainWindow::closeData( void ) { - // TODO + QApplication::setOverrideCursor(Qt::WaitCursor); + + Stop(); + + clearGroups(); + clearSelection(); + _openGLWidget->setPlayer(nullptr, simil::TDataType::TDataUndefined); + _stackViz->closeData(); + _ui->actionToggleStackVizDock->setChecked(false); + _ui->actionToggleStackVizDock->setEnabled(false); + _ui->actionCloseData->setEnabled(false); + + _objectInspectorGB->setCheckUpdates(false); + _objectInspectorGB->setSimPlayer(nullptr); + + _simSlider->setSliderPosition(0); + _summary->clear(); + _simulationDock->setEnabled(false); + + _tfWidget->setColorPoints( visimpl::TTransferFunction() ); + _tfWidget->setSizeFunction( visimpl::TSizeFunction()); + + QApplication::restoreOverrideCursor(); } void MainWindow::dialogAbout( void ) @@ -741,6 +777,7 @@ namespace visimpl void MainWindow::_initStackVizDock( void ) { _stackVizDock = new QDockWidget( ); + _stackVizDock->setObjectName("stackvizDock"); _stackVizDock->setMinimumHeight( 100 ); _stackVizDock->setSizePolicy( QSizePolicy::MinimumExpanding , QSizePolicy::MinimumExpanding ); @@ -866,6 +903,8 @@ namespace visimpl connect( _summary, SIGNAL( histogramClicked( float ) ), this, SLOT( PlayAtPercentage( float ) ) ); + + _simulationDock->setEnabled(false); } void MainWindow::_initSimControlDock( void ) @@ -1215,8 +1254,6 @@ namespace visimpl _toolBoxOptions->addItem( tSpeedGB, tr( "Playback Configuration" ) ); _toolBoxOptions->addItem( vcContainer, tr( "Visual Configuration" ) ); _toolBoxOptions->addItem( containerSelectionTools, tr( "Selection" ) ); - - _toolBoxOptions->addItem( _objectInspectorGB, tr( "Inspector" )); connect( _objectInspectorGB, SIGNAL( simDataChanged()), @@ -1344,6 +1381,7 @@ namespace visimpl _summary->Init( spikesPlayer->data( ) ); _summary->simulationPlayer( _openGLWidget->player( ) ); + _summary->show(); } } @@ -1566,7 +1604,7 @@ namespace visimpl _labelPosition->setText( posText ); - _toolBoxOptions->setCurrentIndex( ( unsigned int )T_TOOL_Inpector ); + _toolBoxOptions->setCurrentIndex( static_cast<unsigned int>( T_TOOL_Inpector )); } void MainWindow::clippingPlanesReset( void ) @@ -1623,18 +1661,18 @@ namespace visimpl return; bool ok; + auto player = _openGLWidget->player(); double result = QInputDialog::getDouble( this, tr( "Set simulation time to play:" ), tr( "Simulation time" ), - ( double )_openGLWidget->currentTime( ), - ( double )_openGLWidget->player( )->data( )->startTime( ), - ( double )_openGLWidget->player( )->data( )->endTime( ), 3, &ok, + static_cast<double>(_openGLWidget->currentTime( )), + static_cast<double>(player->data( )->startTime( )), + static_cast<double>(player->data( )->endTime( )), 3, &ok, Qt::Popup ); if ( ok ) { - float percentage = ( result - _openGLWidget->player( )->startTime( ) ) / - ( _openGLWidget->player( )->endTime( ) - - _openGLWidget->player( )->startTime( ) ); + float percentage = ( result - player->startTime( ) ) / + ( player->endTime( ) - player->startTime( ) ); percentage = std::max( 0.0f, std::min( 1.0f, percentage ) ); @@ -1736,7 +1774,7 @@ namespace visimpl void MainWindow::ApplyPlaybackOperation( unsigned int playbackOp ) { zeroeq::gmrv::PlaybackOperation operation = - ( zeroeq::gmrv::PlaybackOperation )playbackOp; + static_cast<zeroeq::gmrv::PlaybackOperation>(playbackOp); switch ( operation ) { @@ -2090,10 +2128,11 @@ void MainWindow::clearGroups( void ) if ( !_openGLWidget || !_openGLWidget->player( ) ) return; - const auto tBegin = _openGLWidget->player()->startTime(); - const auto tEnd = _openGLWidget->player()->endTime(); + auto player = _openGLWidget->player(); + const auto tBegin = player->startTime(); + const auto tEnd = player->endTime(); const auto newPosition = std::min(tEnd, std::max(tBegin, timePos)); - const auto isOverflow = timePos != newPosition; + const auto isOverflow = std::abs(timePos-newPosition) > std::numeric_limits<float>::epsilon(); PlayAtTime( newPosition, isOverflow ); @@ -2126,8 +2165,9 @@ void MainWindow::clearGroups( void ) if ( !_openGLWidget || !_openGLWidget->player( ) ) return; - const auto tBegin = _openGLWidget->player()->startTime(); - const auto tEnd = _openGLWidget->player()->endTime(); + auto player = _openGLWidget->player(); + const auto tBegin = player->startTime(); + const auto tEnd = player->endTime(); const auto timePos = (percentage * (tEnd - tBegin)) + tBegin; PlayAtTime(timePos, notify); @@ -2138,8 +2178,9 @@ void MainWindow::clearGroups( void ) if(!_openGLWidget || !_openGLWidget->player()) return; - const auto tBegin = _openGLWidget->player()->startTime(); - const auto tEnd = _openGLWidget->player()->endTime(); + auto player = _openGLWidget->player(); + const auto tBegin = player->startTime(); + const auto tEnd = player->endTime(); const auto newPosition = std::max(tBegin, std::min(tEnd, timePos)); const auto percentage = (newPosition - tBegin) / (tEnd - tBegin); @@ -2153,8 +2194,7 @@ void MainWindow::clearGroups( void ) _openGLWidget->PlayAt( newPosition ); _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS ); - _startTimeLabel->setText( - QString::number(_openGLWidget->player()->currentTime(), 'f',3)); + _startTimeLabel->setText(QString::number(player->currentTime(), 'f',3)); if ( notify ) { @@ -2162,7 +2202,6 @@ void MainWindow::clearGroups( void ) try { // Send event - auto player = _openGLWidget->player(); auto eventMgr = player->zeqEvents( ); if(eventMgr) { @@ -2251,26 +2290,132 @@ void MainWindow::clearGroups( void ) const std::string arg_1, const std::string arg_2, const simil::TSimulationType simType, const std::string &subsetEventFile) { + closeLoadingDialog(); + + Q_ASSERT(type != simil::TDataType::TREST); + QApplication::setOverrideCursor(Qt::WaitCursor); - try + _objectInspectorGB->setCheckUpdates(false); + _ui->actionConfigureREST->setEnabled(false); + + Q_ASSERT(simType == simil::TSimulationType::TSimSpikes); + + m_loaderDialog = new LoadingDialog( this ); + m_loaderDialog->show( ); + + QApplication::processEvents( ); + + m_loader = std::make_shared< LoaderThread >( ); + m_loader->setData( type , arg_1 , arg_2 ); + + connect( m_loader.get( ) , SIGNAL( finished( )), + this, SLOT( onDataLoaded( )) ); + connect( m_loader.get( ) , SIGNAL( progress( int )), + m_loaderDialog , SLOT( setProgress( int )) ); + connect( m_loader.get( ) , SIGNAL( network( unsigned int )) , + m_loaderDialog , SLOT( setNetwork( unsigned int )) ); + connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) , + m_loaderDialog , SLOT( setSpikesValue( unsigned int )) ); + + _lastOpenedNetworkFileName = QString::fromStdString(arg_1); + _lastOpenedSubsetsFileName = QString::fromStdString(subsetEventFile); + + m_loader->start( ); + } + + void MainWindow::closeLoadingDialog( ) + { + if ( m_loaderDialog ) { - m_type = type; - m_subsetEventFile = subsetEventFile; - _openGLWidget->loadData( arg_1, type, simType, arg_2 ); - _lastOpenedNetworkFileName = QString::fromStdString(arg_1); + m_loaderDialog->close( ); + delete m_loaderDialog; + m_loaderDialog = nullptr; } - catch(const std::exception &e) + } + + void MainWindow::onDataLoaded() + { + if(!m_loader) return; + + const auto error = m_loader->errors(); + if (!error.empty()) { + closeLoadingDialog(); QApplication::restoreOverrideCursor(); - const auto errorText = QString::fromLocal8Bit(e.what()); - QMessageBox::critical(this, tr("Error loading data"), errorText, QMessageBox::Ok); + + const auto message = QString::fromStdString(error); + QMessageBox::critical(this, tr("Error loading data"), message, + QMessageBox::Ok); + + m_loader = nullptr; return; } - } - void MainWindow::onDataLoaded() - { + simil::SpikesPlayer *player = nullptr; + const auto dataType = m_loader->type(); + + switch ( dataType ) + { + case simil::TBlueConfig: + case simil::TCSV: + case simil::THDF5: + { + const auto spikeData = m_loader->simulationData( ); + + player = new simil::SpikesPlayer( ); + player->LoadData( spikeData ); + + m_loader = nullptr; + } + break; + case simil::TREST: + { + const auto netData = m_loader->network( ); + const auto simData = m_loader->simulationData( ); + + player = new simil::SpikesPlayer( ); + player->LoadData( netData , simData ); + + // NOTE: loader doesn't get destroyed because has a loop for getting data. + } + break; + case simil::TDataUndefined: + default: + { + m_loader = nullptr; + closeLoadingDialog( ); + QMessageBox::critical( this , tr( "Error loading data" ) , + tr( "Data type is undefined after loading" ) , + QMessageBox::Ok ); + + return; + } + break; + } + + if(!player) + { + closeLoadingDialog( ); + QApplication::restoreOverrideCursor( ); + + const auto message = tr("Unable to load data."); + QMessageBox::critical( this , tr( "Error loading data" ) , message , + QMessageBox::Ok ); + + m_loader = nullptr; + return; + } + + if ( m_loaderDialog ) + { + m_loaderDialog->setNetwork( player->gidsSize( )); + m_loaderDialog->setSpikesValue( player->spikesSize( )); + m_loaderDialog->repaint( ); + } + + _openGLWidget->setPlayer(player, dataType); + configureComponents( ); openSubsetEventFile( m_subsetEventFile, false ); @@ -2279,9 +2424,9 @@ void MainWindow::clearGroups( void ) _comboAttribSelection->clear(); - _stackViz->init( _openGLWidget->player( )); + _stackViz->init( player ); - switch(m_type) + switch(dataType) { case simil::TDataType::TBlueConfig: { @@ -2292,11 +2437,10 @@ void MainWindow::clearGroups( void ) case simil::TDataType::TREST: { #ifdef SIMIL_WITH_REST_API - auto timer = new QTimer( this ); - connect( timer, SIGNAL( timeout()), - _objectInspectorGB, SLOT( updateInfo()) ); - - timer->start( 4000 ); + const auto waitTime = m_loader->RESTLoader()->getConfiguration().waitTime; + _objectInspectorGB->setCheckTimer(waitTime); + _objectInspectorGB->setCheckUpdates(true); + _ui->actionConfigureREST->setEnabled(true); #endif } break; @@ -2307,7 +2451,12 @@ void MainWindow::clearGroups( void ) break; } - _openGLWidget->closeLoadingDialog(); + closeLoadingDialog(); + + if(!_lastOpenedSubsetsFileName.isEmpty()) + { + openSubsetEventFile( _lastOpenedSubsetsFileName.toStdString() , false ); + } QApplication::restoreOverrideCursor(); } @@ -3044,6 +3193,104 @@ void MainWindow::clearGroups( void ) } } + void MainWindow::openRESTThroughDialog() + { +#ifdef SIMIL_WITH_REST_API + ConnectRESTDialog dialog(this); + ConnectRESTDialog::Connection connection; + dialog.setRESTConnection(connection); + + if(QDialog::Accepted == dialog.exec()) + { + connection = dialog.getRESTConnection(); + const auto restOpt = dialog.getRESTOptions(); + + simil::LoaderRestData::Configuration config; + config.api = connection.protocol.compare("NEST", Qt::CaseInsensitive) == 0 ? + simil::LoaderRestData::Rest_API::NEST : + simil::LoaderRestData::Rest_API::ARBOR; + config.port = connection.port; + config.url = connection.url.toStdString(); + config.waitTime = restOpt.waitTime; + config.failTime = restOpt.failTime; + config.spikesSize = restOpt.spikesSize; + + loadRESTData(config); + } +#else + const auto title = tr("Connect REST API"); + const auto message = tr("REST data loading is unsupported."); + QMessageBox::critical(this, title, message, QMessageBox::Ok); +#endif + } + + void MainWindow::configureREST() + { +#ifdef SIMIL_WITH_REST_API + if(!m_loader) + { + const QString message = tr("There is no REST connection!"); + QMessageBox::warning(this, tr("REST API Options"), message, QMessageBox::Ok); + return; + } + + auto loader = m_loader->RESTLoader(); + auto options = loader->getConfiguration(); + + RESTConfigurationWidget::Options dialogOptions; + dialogOptions.waitTime = options.waitTime; + dialogOptions.failTime = options.failTime; + dialogOptions.spikesSize = options.spikesSize; + + ConfigureRESTDialog dialog(this, Qt::WindowFlags(), dialogOptions); + if(QDialog::Accepted == dialog.exec()) + { + dialogOptions = dialog.getRESTOptions(); + + simil::LoaderRestData::Configuration config; + config.waitTime = dialogOptions.waitTime; + config.failTime = dialogOptions.failTime; + config.spikesSize = dialogOptions.spikesSize; + + loader->setConfiguration(config); + } +#else + const auto title = tr("Configure REST API"); + const auto message = tr("REST data loading is unsupported."); + QMessageBox::critical(this, title, message, QMessageBox::Ok); +#endif + } + +#ifdef SIMIL_WITH_REST_API + void MainWindow::loadRESTData(const simil::LoaderRestData::Configuration &o) + { + closeLoadingDialog(); + + QApplication::setOverrideCursor(Qt::WaitCursor); + + _objectInspectorGB->setCheckUpdates(false); + + m_loaderDialog = new LoadingDialog( this ); + m_loaderDialog->show( ); + + QApplication::processEvents( ); + + m_loader = std::make_shared< LoaderThread >( ); + m_loader->setRESTConfiguration(o); + + connect( m_loader.get( ) , SIGNAL( finished( )), + this, SLOT( onDataLoaded( )) ); + connect( m_loader.get( ) , SIGNAL( progress( int )), + m_loaderDialog , SLOT( setProgress( int )) ); + connect( m_loader.get( ) , SIGNAL( network( unsigned int )) , + m_loaderDialog , SLOT( setNetwork( unsigned int )) ); + connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) , + m_loaderDialog , SLOT( setSpikesValue( unsigned int )) ); + + m_loader->start( ); + } +#endif + void MainWindow::sendZeroEQPlaybackOperation(const unsigned int op) { #ifdef SIMIL_USE_ZEROEQ diff --git a/visimpl/MainWindow.h b/visimpl/MainWindow.h index f15caaefe88f5acf6abfeb35188d7fdba13a1c96..cf9c9adb12538ff668d5edce8d58d439a68c75f2 100644 --- a/visimpl/MainWindow.h +++ b/visimpl/MainWindow.h @@ -51,6 +51,9 @@ class QPushButton; class QToolBox; class QCloseEvent; +class LoadingDialog; +class LoaderThread; + namespace Ui { class MainWindow; @@ -87,11 +90,20 @@ namespace visimpl const simil::TSimulationType simType = simil::TSimulationType::TSimSpikes, const std::string &subsetEventFile = std::string()); +#ifdef SIMIL_WITH_REST_API + /** \brief Connects and loads data using the given REST connection. + * \param[in] config REST connection configuration. + * + */ + void loadRESTData(const simil::LoaderRestData::Configuration &config); +#endif + public slots: void openBlueConfigThroughDialog( void ); void openCSVFilesThroughDialog( void ); void openHDF5ThroughDialog( void ); + void openRESTThroughDialog(); void openSubsetEventsFileThroughDialog( void ); void openSubsetEventFile( const std::string& fileName, @@ -262,6 +274,11 @@ namespace visimpl */ void applyCameraPosition(); + /** \brief Shows a dialog with REST API options and applies them. + * + */ + void configureREST(); + protected: void _initSimControlDock( void ); void _initPlaybackDock( void ); @@ -285,6 +302,11 @@ namespace visimpl virtual void closeEvent(QCloseEvent *e) override; + /** \brief Closes the data loading dialog. + * + */ + void closeLoadingDialog(); + #ifdef VISIMPL_USE_ZEROEQ #ifdef VISIMPL_USE_GMRVLEX @@ -389,10 +411,11 @@ namespace visimpl QPushButton* _frameClippingColor; QPushButton* _buttonSelectionFromClippingPlanes; - simil::TDataType m_type; std::string m_subsetEventFile; - // Recorder - Recorder* _recorder; + Recorder* _recorder; /** Recorder */ + + std::shared_ptr<LoaderThread> m_loader; /** data loader thread. */ + LoadingDialog *m_loaderDialog; /** data loader dialog. */ }; } // namespace visimpl diff --git a/visimpl/OpenGLWidget.cpp b/visimpl/OpenGLWidget.cpp index ec033811bac9d7569a7f9cb84eaa4cda35e6011a..6ac4ce5cdefd8cefbfbf5cd52fa771d81dac7156 100644 --- a/visimpl/OpenGLWidget.cpp +++ b/visimpl/OpenGLWidget.cpp @@ -67,6 +67,8 @@ constexpr float TRANSLATION_FACTOR = 0.001f; constexpr float ROTATION_FACTOR = 0.01f; constexpr int FRAMEBUFFER_SCALE_FACTOR = 2; constexpr int SAMPLES = 4; +constexpr float DEFAULT_DELTA_TIME = 0.5f; +const QString INITIAL_CAMERA_POSITION = "0,0,0;1;1,0,0,0,1,0,0,0,1"; namespace visimpl { @@ -151,10 +153,7 @@ void main() , _shaderClippingPlanes( nullptr ) , _particleSystem( nullptr ) , _pickRenderer( nullptr ) - , _simulationType( simil::TSimulationType::TSimNetwork ) , _player( nullptr ) - , m_loader{ nullptr } - , m_loaderDialog{ nullptr } , _clippingPlaneLeft( nullptr ) , _clippingPlaneRight( nullptr ) , _planeHeight( 1 ) @@ -325,180 +324,6 @@ void main() if ( _player ) delete _player; - - m_loader = nullptr; - closeLoadingDialog( ); - } - - void OpenGLWidget::loadData( const std::string& fileName , - const simil::TDataType fileType , - simil::TSimulationType simulationType , - const std::string& report ) - { - m_loader = nullptr; - closeLoadingDialog( ); - - _simulationType = simulationType; - - m_loaderDialog = new LoadingDialog( this ); - m_loaderDialog->show( ); - - QApplication::processEvents( ); - - m_loader = std::make_shared< LoaderThread >( ); - m_loader->setData( fileType , fileName , report ); - - connect( m_loader.get( ) , SIGNAL( finished( )) , this , - SLOT( onLoaderFinished( )) ); - connect( m_loader.get( ) , SIGNAL( progress( int )) , m_loaderDialog , - SLOT( setProgress( int )) ); - connect( m_loader.get( ) , SIGNAL( network( unsigned int )) , - m_loaderDialog , SLOT( setNetwork( unsigned int )) ); - connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) , - m_loaderDialog , SLOT( setSpikesValue( unsigned int )) ); - - m_loader->start( ); - } - - void OpenGLWidget::onLoaderFinished( ) - { - makeCurrent( ); - - _deltaTime = 0.5f; - - if ( m_loader ) - { - const auto error = m_loader->errors( ); - if ( !error.empty( )) - { - closeLoadingDialog( ); - QApplication::restoreOverrideCursor( ); - - const auto message = QString::fromStdString( error ); - QMessageBox::critical( this , tr( "Error loading data" ) , message , - QMessageBox::Ok ); - - m_loader = nullptr; - return; - } - } - - const auto dataType = m_loader->type( ); - - switch ( dataType ) - { - case simil::TBlueConfig: - case simil::TCSV: - case simil::THDF5: - { - const auto spikeData = m_loader->simulationData( ); - - _player = new simil::SpikesPlayer( ); - _player->LoadData( spikeData ); - - m_loader = nullptr; - } - break; - case simil::TREST: - { - const auto netData = m_loader->network( ); - const auto simData = m_loader->simulationData( ); - - _player = new simil::SpikesPlayer( ); - _player->LoadData( netData , simData ); - - // NOTE: loader doesn't get destroyed because has a loop for getting data. - } - break; - case simil::TDataUndefined: - default: - { - m_loader = nullptr; - closeLoadingDialog( ); - QMessageBox::critical( this , tr( "Error loading data" ) , - tr( "Data type is undefined after loading" ) , - QMessageBox::Ok ); - - return; - } - break; - } - - if ( m_loaderDialog ) - { - m_loaderDialog->setNetwork( _player->gidsSize( )); - m_loaderDialog->setSpikesValue( _player->spikesSize( )); - m_loaderDialog->repaint( ); - } - - InitialConfig config; - switch ( dataType ) - { - case simil::TBlueConfig: - config = _initialConfigSimBlueConfig; - break; - case simil::THDF5: - config = _initialConfigSimH5; - break; - case simil::TCSV: - config = _initialConfigSimCSV; - break; - case simil::TREST: - config = _initialConfigSimREST; - break; - default: - break; - } - - if ( !_scaleFactorExternal ) - { - const auto scale = std::get< T_SCALE >( config ); - _scaleFactor = vec3( scale , scale , scale ); - } - - std::cout << "Using scale factor of " << _scaleFactor.x - << ", " << _scaleFactor.y - << ", " << _scaleFactor.z - << std::endl; - - createParticleSystem( ); - _initRenderToTexture( ); - - simulationDeltaTime( std::get< T_DELTATIME >( config )); - simulationStepsPerSecond( std::get< T_STEPS_PER_SEC >( config )); - changeSimulationDecayValue( std::get< T_DECAY >( config )); - -#ifdef VISIMPL_USE_ZEROEQ - if ( !_zeqUri.empty( )) - { - try - { - auto& instance = ZeroEQConfig::instance( ); - if ( !instance.isConnected( )) - { - instance.connect( _zeqUri ); - } - - _player->connectZeq( instance.subscriber( ) , instance.publisher( )); - instance.startReceiveLoop( ); - } - catch ( std::exception& e ) - { - std::cerr << "Exception when initializing ZeroEQ. "; - std::cerr << e.what( ) << __FILE__ << ":" << __LINE__ << std::endl; - } - catch ( ... ) - { - std::cerr << "Unknown exception when initializing ZeroEQ. " << __FILE__ - << ":" << __LINE__ << std::endl; - } - } -#endif - - this->_paint = true; - update( ); - - emit dataLoaded( ); } void OpenGLWidget::initializeGL( void ) @@ -727,8 +552,10 @@ void main() void OpenGLWidget::_backtraceSimulation( void ) { - float endTime = _player->currentTime( ); - float startTime = std::max( 0.0f , endTime - _domainManager->decay( )); + if(!_player) return; + + const float endTime = _player->currentTime( ); + const float startTime = std::max( 0.0f , endTime - _domainManager->decay( )); if ( startTime < endTime ) { const auto context = _player->spikesBetween( startTime , endTime ); @@ -770,7 +597,7 @@ void main() auto render = _particleSystem->renderer( ); auto glRender = dynamic_cast<prefr::GLAbstractRenderer*>(render); - if ( glRender != nullptr ) + if ( glRender ) { glRender->setRenderProgram( _shaderParticlesCurrent ); } @@ -912,21 +739,30 @@ void main() std::cout << "Loaded default shaders." << std::endl; } + unsigned int currentParticles = _player ? static_cast<unsigned int>( _player->gids( ).size( )) : 0u; const unsigned int maxParticles = - std::max( 100000u , static_cast<unsigned int>( _player->gids( ).size( ))); + std::max( 100000u , currentParticles); _updateData( ); _particleSystem = new prefr::ParticleSystem( maxParticles , _camera ); _flagResetParticles = true; - _domainManager = new DomainManager( _particleSystem , _player->gids( )); + if(!_player) + { + if(_domainManager) delete _domainManager; + _domainManager = nullptr; + } + else + { + _domainManager = new DomainManager( _particleSystem , _player->gids( )); #ifdef SIMIL_USE_BRION - _domainManager->init( _gidPositions , _player->data( )->blueConfig( )); + _domainManager->init( _gidPositions , _player->data( )->blueConfig( )); #else - _domainManager->init( _gidPositions ); + _domainManager->init( _gidPositions ); #endif - _domainManager->initializeParticleSystem( _shaderParticlesDefault ); - _domainManager->updateData( _player->gids( ) , _gidPositions ); + _domainManager->initializeParticleSystem( _shaderParticlesDefault ); + _domainManager->updateData( _player->gids( ) , _gidPositions ); + } _pickRenderer = dynamic_cast< prefr::GLPickRenderer* >( _particleSystem->renderer( )); @@ -937,7 +773,8 @@ void main() _pickRenderer->setDefaultFBO( defaultFramebufferObject( )); } - _domainManager->mode( TMODE_SELECTION ); + if(_domainManager) + _domainManager->mode( TMODE_SELECTION ); updateCameraBoundingBox( true ); @@ -1271,18 +1108,17 @@ void main() void OpenGLWidget::_updateSelection( void ) { - if ( _particleSystem /*&& _pendingSelection*/ ) - { - _particleSystem->run( false ); + if(!_particleSystem || !_player) return; - updateCameraBoundingBox( ); + _particleSystem->run(false); - _particleSystem->run( true ); - _particleSystem->update( 0.0f ); + updateCameraBoundingBox(); - _flagUpdateSelection = false; - _flagUpdateRender = true; - } + _particleSystem->run(true); + _particleSystem->update(0.0f); + + _flagUpdateSelection = false; + _flagUpdateRender = true; } void OpenGLWidget::setGroupVisibility( unsigned int i , bool state ) @@ -1348,6 +1184,13 @@ void main() bool OpenGLWidget::_updateData( bool force ) { + if(!_player) + { + _gidPositions.clear( ); + _boundingBoxHome = tBoundingBox{ vec3{0,0,0}, vec3{0,0,0} }; + return false; + } + const auto& positions = _player->positions( ); // assumed positions doesn't change so if equal the network didn't change. @@ -1429,7 +1272,7 @@ void main() void OpenGLWidget::updateCameraBoundingBox( bool setBoundingBox ) { - if ( _gidPositions.empty( )) return; + if ( _gidPositions.empty( ) || !_domainManager) return; const auto boundingBox = _domainManager->boundingBox( ); @@ -1536,7 +1379,7 @@ void main() void OpenGLWidget::_updateParticles( float renderDelta ) { - if ( _player->isPlaying( ) || _firstFrame ) + if ( _player && (_player->isPlaying( ) || _firstFrame )) { _particleSystem->update( renderDelta ); _firstFrame = false; @@ -1545,6 +1388,8 @@ void main() void OpenGLWidget::_updateEventLabelsVisibility( void ) { + if(!_player) return; + std::vector< bool > visibility = _activeEventsAt( _player->currentTime( )); unsigned int counter = 0; @@ -1564,16 +1409,19 @@ void main() { std::vector< bool > result( _eventLabels.size( ) , false ); - const float totalTime = _player->endTime( ) - _player->startTime( ); - const double perc = time / totalTime; - - unsigned int counter = 0; - for ( auto event: _eventsActivation ) + if(_player) { - unsigned int position = perc * event.size( ); - result[ counter ] = event[ position ]; + const float totalTime = _player->endTime( ) - _player->startTime( ); + const double perc = time / totalTime; - ++counter; + unsigned int counter = 0; + for ( auto event: _eventsActivation ) + { + unsigned int position = perc * event.size( ); + result[ counter ] = event[ position ]; + + ++counter; + } } return result; @@ -1639,6 +1487,8 @@ void main() void OpenGLWidget::_genPlanesFromBoundingBox( void ) { + if(!_domainManager) return; + auto currentBoundingBox = _domainManager->boundingBox( ); _planesCenter = @@ -2000,6 +1850,88 @@ void main() update( ); } + void OpenGLWidget::setPlayer(simil::SpikesPlayer *p, const simil::TDataType type) + { + // Resets camera position + setCameraPosition(CameraPosition(INITIAL_CAMERA_POSITION)); + + if(_player) + { + // TODO: clear data? + } + + _deltaTime = DEFAULT_DELTA_TIME; + _player = p; + + InitialConfig config; + switch ( type ) + { + case simil::TBlueConfig: + config = _initialConfigSimBlueConfig; + break; + case simil::THDF5: + config = _initialConfigSimH5; + break; + case simil::TCSV: + config = _initialConfigSimCSV; + break; + case simil::TREST: + config = _initialConfigSimREST; + break; + default: + break; + } + + if ( !_scaleFactorExternal ) + { + const auto scale = std::get< T_SCALE >( config ); + _scaleFactor = vec3( scale , scale , scale ); + } + + std::cout << "Using scale factor of " << _scaleFactor.x + << ", " << _scaleFactor.y + << ", " << _scaleFactor.z + << std::endl; + + createParticleSystem( ); + _initRenderToTexture( ); + + simulationDeltaTime( std::get< T_DELTATIME >( config )); + simulationStepsPerSecond( std::get< T_STEPS_PER_SEC >( config )); + changeSimulationDecayValue( std::get< T_DECAY >( config )); + +#ifdef VISIMPL_USE_ZEROEQ + if ( !_zeqUri.empty( )) + { + try + { + auto& instance = ZeroEQConfig::instance( ); + if ( !instance.isConnected( )) + { + instance.connect( _zeqUri ); + } + + _player->connectZeq( instance.subscriber( ) , instance.publisher( )); + instance.startReceiveLoop( ); + _zeqUri = std::string(); // clear to avoid re-connect. + } + catch ( std::exception& e ) + { + std::cerr << "Exception when initializing ZeroEQ. "; + std::cerr << e.what( ) << __FILE__ << ":" << __LINE__ << std::endl; + } + catch ( ... ) + { + std::cerr << "Unknown exception when initializing ZeroEQ. " << __FILE__ + << ":" << __LINE__ << std::endl; + } + } +#endif + + this->_paint = (_player != nullptr); + update( ); + } + void OpenGLWidget::keyPressEvent( QKeyEvent* event_ ) { switch ( event_->key( )) @@ -2099,6 +2031,8 @@ void main() float OpenGLWidget::currentTime( void ) { + if(!_player) return 0.; + switch ( _playbackMode ) { case TPlaybackMode::STEP_BY_STEP: @@ -2117,7 +2051,7 @@ void main() { _subsetEvents = manager; - _createEventLabels( ); + if(manager) _createEventLabels( ); update( ); } @@ -2395,7 +2329,7 @@ void main() void OpenGLWidget::simulationDeltaTime( float value ) { - _player->deltaTime( value ); + if(_player) _player->deltaTime( value ); _simDeltaTime = value; @@ -2445,16 +2379,6 @@ void main() return _domainManager->decay( ); } - void OpenGLWidget::closeLoadingDialog( ) - { - if ( m_loaderDialog ) - { - m_loaderDialog->close( ); - delete m_loaderDialog; - m_loaderDialog = nullptr; - } - } - CameraPosition OpenGLWidget::cameraPosition() const { CameraPosition pos; diff --git a/visimpl/OpenGLWidget.h b/visimpl/OpenGLWidget.h index 482f1382ed6534862a3b18fa28c04cd785288234..7d7ee58100dbcabfed994c971d90f9279b40927a 100644 --- a/visimpl/OpenGLWidget.h +++ b/visimpl/OpenGLWidget.h @@ -64,8 +64,6 @@ #include <sstream> class QLabel; -class LoadingDialog; -class LoaderThread; struct streamDotSeparator: std::numpunct<char> { @@ -189,10 +187,12 @@ namespace visimpl virtual ~OpenGLWidget(); void createParticleSystem( ); - void loadData( const std::string& fileName, - const simil::TDataType = simil::TDataType::TBlueConfig, - simil::TSimulationType simulationType = simil::TSimulationType::TSimSpikes, - const std::string& report = std::string( "" )); + + /** \brief Sets a new spikes player and initializes. + * \param[in] p SpikesPlayer pointer. + * + */ + void setPlayer(simil::SpikesPlayer *p, const simil::TDataType type); void idleUpdate( bool idleUpdate_ = true ); @@ -221,8 +221,6 @@ namespace visimpl const scoop::ColorPalette& colorPalette( void ); - void closeLoadingDialog(); - /** \brief Returns the current camera position. * */ @@ -244,8 +242,6 @@ namespace visimpl void pickedSingle( unsigned int ); - void dataLoaded(); - public slots: void updateData( void ); @@ -318,8 +314,6 @@ namespace visimpl GIDVec getPlanesContainedElements( void ) const; - void onLoaderFinished(); - protected: void _resolveFlagsOperations( void ); @@ -435,12 +429,8 @@ namespace visimpl prefr::ParticleSystem* _particleSystem; prefr::GLPickRenderer* _pickRenderer; - simil::TSimulationType _simulationType; simil::SpikesPlayer* _player; - std::shared_ptr<LoaderThread> m_loader; - LoadingDialog *m_loaderDialog; - reto::ClippingPlane* _clippingPlaneLeft; reto::ClippingPlane* _clippingPlaneRight; evec3 _planesCenter; diff --git a/visimpl/icons/close.svg b/visimpl/icons/close.svg index 0e92788ba0fa8bfbf267436dfc87aba8a785c642..c1b09d11230814a5bebb4dcef5b3fe974e9ee2fb 100644 --- a/visimpl/icons/close.svg +++ b/visimpl/icons/close.svg @@ -1,2 +1,158 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 48 48"><title>Gnome window close</title><desc>http://svn.gnome.org/viewvc/gnome-icon-theme/</desc><radialGradient id="SVGID_1_" cx="-66.1006" cy="-1047.4805" r="1.6055" gradientTransform="matrix(13.7819 0 0 -2.4587 934.9918 -2541.4377)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#000"/><stop offset="1" style="stop-color:#000;stop-opacity:0"/></radialGradient><path style="opacity:.092;fill:url(#SVGID_1_)" d="M46.127,33.979c0,2.182-9.906,3.947-22.127,3.947c-12.22,0-22.126-1.768-22.126-3.947c0-2.179,9.906-3.946,22.126-3.946C36.222,30.032,46.127,31.8,46.127,33.979z"/><radialGradient id="SVGID_2_" cx="148.2012" cy="-1029.5996" r="1.6036" gradientTransform="matrix(5.3381 0 0 -2.4944 -778.1038 -2532.8325)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#000"/><stop offset="1" style="stop-color:#000;stop-opacity:0"/></radialGradient><path style="opacity:.2031;fill:url(#SVGID_2_)" d="M22,35.392c0,2.322-4.029,4.205-9,4.205s-9-1.883-9-4.205s4.029-4.205,9-4.205S22,33.069,22,35.392z"/><radialGradient id="SVGID_3_" cx="127.0596" cy="-1016.3906" r="1.6066" gradientTransform="matrix(5.4059 0 0 -2.5259 -652.8704 -2531.8577)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#000"/><stop offset="1" style="stop-color:#000;stop-opacity:0"/></radialGradient><path style="opacity:.2031;fill:url(#SVGID_3_)" d="M43,35.392c0,2.322-4.028,4.205-9,4.205c-4.971,0-9-1.883-9-4.205s4.029-4.205,9-4.205C38.972,31.187,43,33.069,43,35.392z"/><radialGradient id="SVGID_4_" cx="-18.3965" cy="-229.4829" r="1.4931" gradientTransform="matrix(10.1125 0 0 -10.104 209.6891 -2299.3503)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#9C9E99"/><stop offset="1" style="stop-color:#868883"/></radialGradient><path style="fill:url(#SVGID_4_);stroke:#555753;stroke-width:.8125;stroke-linecap:round;stroke-linejoin:round" d="M13.102,8.405c-1.456-0.01-2.788,0.879-3.339,2.227c-0.551,1.348-0.212,2.883,0.834,3.896l8.013,8.013l-8.013,8.013c-1.398,1.398-1.398,3.666,0,5.064c1.398,1.398,3.666,1.398,5.064,0l8.014-8.014l8.013,8.014c0.898,0.924,2.204,1.277,3.45,0.945c1.245-0.332,2.241-1.313,2.561-2.561c0.318-1.249-0.067-2.563-1.002-3.45l-8.014-8.014l8.014-8.013c1.056-1.021,1.4-2.6,0.834-3.951c-0.563-1.354-1.928-2.205-3.396-2.17c-0.93,0.037-1.809,0.437-2.447,1.111l-8.013,8.014l-8.014-8.014C14.995,8.815,14.069,8.413,13.102,8.405z"/><path xlink:href="#path4262" style="opacity:.3621;fill:none;stroke:#FFFFFF;stroke-width:.8125;stroke-linecap:round;stroke-linejoin:round" d="M13.126,9.405c-1.037-0.008-2.03,0.654-2.423,1.615s-0.147,2.03,0.615,2.771c0.013,0,0.025,0,0.039,0l8,8.038c0.199,0.191,0.311,0.455,0.311,0.73s-0.112,0.541-0.311,0.731l-8,8c-1.009,1.009-1.009,2.605,0,3.615c1.008,1.009,2.606,1.009,3.615,0l8-8.039c0.191-0.198,0.455-0.313,0.731-0.313c0.275,0,0.539,0.112,0.73,0.313l8,8.039c0,0.013,0,0.023,0,0.037c0.637,0.656,1.55,0.896,2.461,0.654c0.904-0.242,1.581-0.957,1.809-1.847c0.228-0.896-0.021-1.823-0.693-2.462c-0.012,0-0.024,0-0.037,0l-8-8c-0.198-0.191-0.313-0.455-0.313-0.73s0.113-0.541,0.313-0.73l8-8.038c0.013,0,0.025,0,0.037,0c0.76-0.733,1.015-1.896,0.615-2.847c-0.399-0.959-1.354-1.563-2.422-1.539c-0.664,0.025-1.315,0.328-1.77,0.809c0,0.014,0,0.025,0,0.039l-8,8.001c-0.191,0.198-0.455,0.312-0.73,0.312c-0.276,0-0.54-0.112-0.731-0.312l-8-8.001c0-0.014,0-0.025,0-0.039C14.501,9.715,13.819,9.411,13.126,9.405z"/><radialGradient id="SVGID_5_" cx="46.3672" cy="-666" r="1.8958" gradientTransform="matrix(7.5973 0 0 -3.8245 -329.7393 -2524.8076)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#555753"/><stop offset="1" style="stop-color:#555753;stop-opacity:0"/></radialGradient><path style="opacity:.3;fill:url(#SVGID_5_)" d="M19.454,22.559c5.222-1.522,3.882,0.164,8.507,0.164l8.506,8.506l-4.704,3.64l-8-8.068l-8,7.798L11.58,30.5L19.454,22.559z"/></svg> \ No newline at end of file +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="100%" + height="100%" + viewBox="0 0 48 48" + version="1.1" + id="svg43" + sodipodi:docname="close.svg" + inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"> + <metadata + id="metadata49"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs47" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1528" + inkscape:window-height="836" + id="namedview45" + showgrid="false" + inkscape:zoom="13.906433" + inkscape:cx="24" + inkscape:cy="24" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="svg43" /> + <title + id="title2">Gnome window close</title> + <desc + id="desc4">http://svn.gnome.org/viewvc/gnome-icon-theme/</desc> + <radialGradient + id="SVGID_1_" + cx="-66.1006" + cy="-1047.4805" + r="1.6055" + gradientTransform="matrix(13.7819 0 0 -2.4587 934.9918 -2541.4377)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#000" + id="stop6" /> + <stop + offset="1" + style="stop-color:#000;stop-opacity:0" + id="stop8" /> + </radialGradient> + <path + style="opacity:.092;fill:url(#SVGID_1_)" + d="M46.127,33.979c0,2.182-9.906,3.947-22.127,3.947c-12.22,0-22.126-1.768-22.126-3.947c0-2.179,9.906-3.946,22.126-3.946C36.222,30.032,46.127,31.8,46.127,33.979z" + id="path11" /> + <radialGradient + id="SVGID_2_" + cx="148.2012" + cy="-1029.5996" + r="1.6036" + gradientTransform="matrix(5.3381 0 0 -2.4944 -778.1038 -2532.8325)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#000" + id="stop13" /> + <stop + offset="1" + style="stop-color:#000;stop-opacity:0" + id="stop15" /> + </radialGradient> + <path + style="opacity:.2031;fill:url(#SVGID_2_)" + d="M22,35.392c0,2.322-4.029,4.205-9,4.205s-9-1.883-9-4.205s4.029-4.205,9-4.205S22,33.069,22,35.392z" + id="path18" /> + <radialGradient + id="SVGID_3_" + cx="127.0596" + cy="-1016.3906" + r="1.6066" + gradientTransform="matrix(5.4059 0 0 -2.5259 -652.8704 -2531.8577)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#000" + id="stop20" /> + <stop + offset="1" + style="stop-color:#000;stop-opacity:0" + id="stop22" /> + </radialGradient> + <path + style="opacity:.2031;fill:url(#SVGID_3_)" + d="M43,35.392c0,2.322-4.028,4.205-9,4.205c-4.971,0-9-1.883-9-4.205s4.029-4.205,9-4.205C38.972,31.187,43,33.069,43,35.392z" + id="path25" /> + <radialGradient + id="SVGID_4_" + cx="-18.3965" + cy="-229.4829" + r="1.4931" + gradientTransform="matrix(10.1125 0 0 -10.104 209.6891 -2299.3503)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#9C9E99" + id="stop27" /> + <stop + offset="1" + style="stop-color:#868883" + id="stop29" /> + </radialGradient> + <path + style="fill:#aa0000;stroke:#555753;stroke-width:0.8125;stroke-linecap:round;stroke-linejoin:round" + d="M13.102,8.405c-1.456-0.01-2.788,0.879-3.339,2.227c-0.551,1.348-0.212,2.883,0.834,3.896l8.013,8.013l-8.013,8.013c-1.398,1.398-1.398,3.666,0,5.064c1.398,1.398,3.666,1.398,5.064,0l8.014-8.014l8.013,8.014c0.898,0.924,2.204,1.277,3.45,0.945c1.245-0.332,2.241-1.313,2.561-2.561c0.318-1.249-0.067-2.563-1.002-3.45l-8.014-8.014l8.014-8.013c1.056-1.021,1.4-2.6,0.834-3.951c-0.563-1.354-1.928-2.205-3.396-2.17c-0.93,0.037-1.809,0.437-2.447,1.111l-8.013,8.014l-8.014-8.014C14.995,8.815,14.069,8.413,13.102,8.405z" + id="path32" /> + <path + style="opacity:0.3621;fill:#ff0000;stroke:#FFFFFF;stroke-width:0.8125;stroke-linecap:round;stroke-linejoin:round" + d="M 34.203125 9.4023438 C 33.539125 9.4273437 32.888594 9.7318902 32.433594 10.212891 L 32.433594 10.251953 L 24.433594 18.251953 C 24.242594 18.449953 23.978125 18.564453 23.703125 18.564453 C 23.427125 18.564453 23.163656 18.451953 22.972656 18.251953 L 14.972656 10.251953 L 14.972656 10.212891 C 14.501656 9.7158902 13.819953 9.4102969 13.126953 9.4042969 C 12.089953 9.3962969 11.096125 10.058531 10.703125 11.019531 C 10.310125 11.980531 10.556359 13.050016 11.318359 13.791016 L 11.357422 13.791016 L 19.357422 21.828125 C 19.556422 22.019125 19.667969 22.283594 19.667969 22.558594 C 19.667969 22.833594 19.556422 23.099063 19.357422 23.289062 L 11.357422 31.289062 C 10.348422 32.298063 10.348422 33.894297 11.357422 34.904297 C 12.365422 35.913297 13.963656 35.913297 14.972656 34.904297 L 22.972656 26.865234 C 23.163656 26.667234 23.427125 26.552734 23.703125 26.552734 C 23.978125 26.552734 24.242594 26.664234 24.433594 26.865234 L 32.433594 34.904297 L 32.433594 34.941406 C 33.070594 35.597406 33.983531 35.837703 34.894531 35.595703 C 35.798531 35.353703 36.475125 34.638047 36.703125 33.748047 C 36.931125 32.852047 36.681766 31.926109 36.009766 31.287109 L 35.972656 31.287109 L 27.972656 23.287109 C 27.774656 23.096109 27.660156 22.831641 27.660156 22.556641 C 27.660156 22.281641 27.772656 22.015172 27.972656 21.826172 L 35.972656 13.789062 L 36.009766 13.789062 C 36.769766 13.056063 37.025 11.892406 36.625 10.941406 C 36.226 9.9824065 35.271125 9.3783437 34.203125 9.4023438 z " + id="path34" /> + <radialGradient + id="SVGID_5_" + cx="46.3672" + cy="-666" + r="1.8958" + gradientTransform="matrix(7.5973 0 0 -3.8245 -329.7393 -2524.8076)" + gradientUnits="userSpaceOnUse"> + <stop + offset="0" + style="stop-color:#555753" + id="stop36" /> + <stop + offset="1" + style="stop-color:#555753;stop-opacity:0" + id="stop38" /> + </radialGradient> + <path + style="opacity:.3;fill:url(#SVGID_5_)" + d="M19.454,22.559c5.222-1.522,3.882,0.164,8.507,0.164l8.506,8.506l-4.704,3.64l-8-8.068l-8,7.798L11.58,30.5L19.454,22.559z" + id="path41" /> +</svg> diff --git a/visimpl/icons/folder-rest.svg b/visimpl/icons/folder-rest.svg new file mode 100644 index 0000000000000000000000000000000000000000..d32071f7cff28c1adcdc6932f10e9f771008ee3d --- /dev/null +++ b/visimpl/icons/folder-rest.svg @@ -0,0 +1,358 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + id="svg97" + height="48" + width="48" + version="1.0" + sodipodi:docname="folder-rest.svg" + inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"> + <metadata + id="metadata57"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1528" + inkscape:window-height="836" + id="namedview55" + showgrid="false" + inkscape:zoom="8.8541665" + inkscape:cx="36.481212" + inkscape:cy="17.761916" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="svg97" + inkscape:document-rotation="0" /> + <defs + id="defs3"> + <rect + x="6.2682353" + y="11.350588" + width="41.392941" + height="33.825882" + id="rect890" /> + <radialGradient + id="radialGradient6719" + xlink:href="#linearGradient5060" + gradientUnits="userSpaceOnUse" + cy="486.65" + cx="605.71" + gradientTransform="matrix(-2.7744 0 0 1.9697 112.76 -872.89)" + r="117.14" /> + <linearGradient + id="linearGradient5060"> + <stop + id="stop5062" + offset="0" /> + <stop + id="stop5064" + stop-opacity="0" + offset="1" /> + </linearGradient> + <radialGradient + id="radialGradient6717" + xlink:href="#linearGradient5060" + gradientUnits="userSpaceOnUse" + cy="486.65" + cx="605.71" + gradientTransform="matrix(2.7744 0 0 1.9697 -1891.6 -872.89)" + r="117.14" /> + <linearGradient + id="linearGradient6715" + y2="609.51" + gradientUnits="userSpaceOnUse" + x2="302.86" + gradientTransform="matrix(2.7744 0 0 1.9697 -1892.2 -872.89)" + y1="366.65" + x1="302.86"> + <stop + id="stop5050" + stop-opacity="0" + offset="0" /> + <stop + id="stop5056" + offset=".5" /> + <stop + id="stop5052" + stop-opacity="0" + offset="1" /> + </linearGradient> + <radialGradient + id="radialGradient238" + gradientUnits="userSpaceOnUse" + cy="37.518" + cx="20.706" + gradientTransform="matrix(1.055 -.027345 .17770 1.1909 -3.5722 -7.1253)" + r="30.905"> + <stop + id="stop1790" + stop-color="#202020" + offset="0" /> + <stop + id="stop1791" + stop-color="#b9b9b9" + offset="1" /> + </radialGradient> + <linearGradient + id="linearGradient491" + y2="66.834" + gradientUnits="userSpaceOnUse" + x2="9.8981" + gradientTransform="matrix(1.5168 0 0 .70898 -.87957 -1.3182)" + y1="13.773" + x1="6.2298"> + <stop + id="stop3984" + stop-color="#fff" + stop-opacity=".87629" + offset="0" /> + <stop + id="stop3985" + stop-color="#fffffe" + stop-opacity="0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient322" + y2="46.689" + gradientUnits="userSpaceOnUse" + x2="12.854" + gradientTransform="matrix(1.3175 0 0 .81626 -.87957 -1.3182)" + y1="32.567" + x1="13.036"> + <stop + id="stop320" + stop-color="#fff" + offset="0" /> + <stop + id="stop321" + stop-color="#fff" + stop-opacity="0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3104" + y2="6.1803" + gradientUnits="userSpaceOnUse" + x2="15.515" + y1="31.368" + x1="18.113"> + <stop + id="stop3098" + stop-color="#424242" + offset="0" /> + <stop + id="stop3100" + stop-color="#777" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient9772" + y2="32.05" + gradientUnits="userSpaceOnUse" + x2="22.065" + y1="36.988" + x1="22.176"> + <stop + id="stop9768" + stop-color="#6194cb" + offset="0" /> + <stop + id="stop9770" + stop-color="#729fcf" + offset="1" /> + </linearGradient> + </defs> + <g + id="layer1"> + <g + id="g6707" + transform="matrix(0.022624,0,0,0.020868,43.383,36.37)"> + <rect + id="rect6709" + height="478.35999" + width="1339.6" + y="-150.7" + x="-1559.3" + style="opacity:0.40206;fill:url(#linearGradient6715)" /> + <path + id="path6711" + d="m -219.62,-150.68 v 478.33 c 142.88,0.9 345.4,-107.17 345.4,-239.2 0,-132.02 -159.44,-239.13 -345.4,-239.13 z" + inkscape:connector-curvature="0" + style="opacity:0.40206;fill:url(#radialGradient6717)" /> + <path + id="path6713" + d="m -1559.3,-150.68 v 478.33 c -142.8,0.9 -345.4,-107.17 -345.4,-239.2 0,-132.02 159.5,-239.13 345.4,-239.13 z" + inkscape:connector-curvature="0" + style="opacity:0.40206;fill:url(#radialGradient6719)" /> + </g> + <path + id="path216" + d="m 4.5218,38.687 c 0.0218,0.417 0.4599,0.833 0.8762,0.833 h 31.327 c 0.416,0 0.811,-0.416 0.789,-0.833 L 36.578,11.461 c -0.022,-0.417 -0.46,-0.833 -0.877,-0.833 h -13.27 c -0.486,0 -1.235,-0.316 -1.402,-1.1066 L 20.417,6.6284 C 20.262,5.8927 19.535,5.5905 19.119,5.5905 H 4.34 c -0.4162,0 -0.8107,0.4163 -0.7889,0.8326 l 0.9707,32.264 z" + inkscape:connector-curvature="0" + style="fill:url(#radialGradient238);stroke:url(#linearGradient3104);stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9788" + d="m 5.2266,22.562 h 30.265" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9784" + d="m 5.0422,18.562 h 30.447" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9778" + d="m 4.9807,12.562 h 30.507" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9798" + d="m 5.3862,32.562 h 30.109" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9800" + d="m 5.5091,34.562 h 29.988" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9782" + d="m 5.0422,16.562 h 30.447" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9780" + d="m 5.0114,14.562 h 30.478" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9776" + d="m 4.9221,10.562 h 15.281" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9774" + d="m 4.8738,8.5625 h 14.783" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9794" + d="m 5.3247,28.562 h 30.169" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9792" + d="m 5.2881,26.562 h 30.205" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9790" + d="m 5.2266,24.562 h 30.265" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9786" + d="m 5.1959,20.562 h 30.296" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9796" + d="m 5.3247,30.562 h 30.169" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path9802" + d="m 5.5091,36.562 h 29.988" + inkscape:connector-curvature="0" + style="opacity:0.11363998;fill:#729fcf;stroke:#000000;stroke-linecap:round;stroke-linejoin:round" /> + <path + id="path219" + d="M 6.0683,38.864 C 6.0847,39.176 5.8874,39.384 5.5698,39.28 5.2521,39.176 5.033,38.968 5.0167,38.656 L 4.069,6.591 C 4.0526,6.2792 4.2341,6.0906 4.5464,6.0906 l 14.422,-0.0477 c 0.313,0 0.932,0.3005 1.133,1.3222 l 0.574,2.8159 c -0.427,-0.4656 -0.419,-0.48 -0.638,-1.1571 l -0.406,-1.2592 c -0.219,-0.7276 -0.698,-0.8319 -1.01,-0.8319 H 5.7334 c -0.3122,0 -0.5095,0.2082 -0.4931,0.5204 l 0.938,31.515 -0.1096,-0.104 z" + display="block" + inkscape:connector-curvature="0" + style="display:block;opacity:0.45143002;fill:url(#linearGradient491)" /> + <g + id="g220" + transform="matrix(1.0408,0,0.054493,1.0408,-8.6702,2.6706)" + style="fill:#ffffff;fill-opacity:0.75705997"> + <path + id="path221" + d="M 42.417,8.5152 C 42.422,8.4181 42.289,8.2682 42.182,8.2682 L 29.151,8.2661 c 0,0 0.911,0.5879 2.201,0.5962 l 11.054,0.071 c 0.011,-0.2117 0.003,-0.256 0.011,-0.4181 z" + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:0.50847" /> + </g> + <path + id="path233" + d="M 39.784,39.511 C 40.927,39.467 41.747,38.414 41.831,37.19 42.622,25.641 43.49,15.958 43.49,15.958 43.562,15.71 43.322,15.463 43.01,15.463 H 8.639 c -4e-4,0 -1.8507,21.867 -1.8507,21.867 -0.1145,0.982 -0.466,1.804 -1.5498,2.183 l 34.546,-0.002 z" + display="block" + inkscape:connector-curvature="0" + style="display:block;fill:url(#linearGradient9772);stroke:#3465a4;stroke-linejoin:round" /> + <path + id="path304" + d="m 9.6202,16.464 32.791,0.065 -1.574,20.002 c -0.084,1.071 -0.45,1.428 -1.872,1.428 -1.872,0 -28.678,-0.032 -31.395,-0.032 0.2335,-0.321 0.3337,-0.989 0.335,-1.005 L 9.6204,16.464 Z" + inkscape:connector-curvature="0" + style="opacity:0.46591001;fill:none;stroke:url(#linearGradient322);stroke-width:1px;stroke-linecap:round" /> + <path + id="path323" + d="M 9.6202,16.223 8.4536,31.866 c 0,0 8.2964,-4.148 18.666,-4.148 10.3696,0 15.555,-11.495 15.555,-11.495 H 9.6196 Z" + inkscape:connector-curvature="0" + style="fill:#ffffff;fill-opacity:0.089286;fill-rule:evenodd" /> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="4.9807" + y="12.562" + id="text872"><tspan + sodipodi:role="line" + id="tspan870" + x="4.9807" + y="47.952625" /></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="12.084706" + y="-1.9200009" + id="text876"><tspan + sodipodi:role="line" + id="tspan874" + x="12.084706" + y="33.470623" /></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:43.91484451px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.09787118" + x="1.1159539" + y="28.247671" + id="text880" + transform="scale(0.91085367,1.0978712)"><tspan + sodipodi:role="line" + id="tspan878" + x="1.1159539" + y="28.247671" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.56593895px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:1.09787118">REST</tspan></text> +</svg> diff --git a/visimpl/resources.qrc b/visimpl/resources.qrc index 801a3f6c3ead4e3a1506d6a49837ca2404ec81b8..f7133a678d684e8061ce2d1c4d09aaa009c2d0de 100644 --- a/visimpl/resources.qrc +++ b/visimpl/resources.qrc @@ -13,6 +13,7 @@ <file>icons/folder-bc.svg</file> <file>icons/folder-csv.svg</file> <file>icons/folder-h5.svg</file> + <file>icons/folder-rest.svg</file> <file>icons/colorpicker.svg</file> <file>icons/play.svg</file> <file>icons/pause.svg</file> diff --git a/visimpl/visimpl.cpp b/visimpl/visimpl.cpp index 8874fd34914e3cec877ddc755c0773f9f6604374..3709ff79aa341f8383ad2caa3b632de958f8d8bb 100644 --- a/visimpl/visimpl.cpp +++ b/visimpl/visimpl.cpp @@ -39,6 +39,7 @@ // Project #include "MainWindow.h" #include <visimpl/version.h> +#include <sumrice/sumrice.h> #ifdef VISIMPL_USE_ZEROEQ // zeroeq @@ -349,9 +350,31 @@ int main( int argc, char** argv ) } } - if(dataType != simil::TDataUndefined) + switch(dataType) { - mainWindow.loadData(dataType, networkFile, activityFile, simType, subsetEventFile); + case simil::TDataType::TREST: + { +#ifdef SIMIL_WITH_REST_API + simil::LoaderRestData::Configuration config; + config.url = networkFile; + config.port = stoi(activityFile); + config.api = simil::LoaderRestData::Rest_API::NEST; + + mainWindow.loadRESTData(config); +#else + std::cerr << "REST API not supported." << std::endl; + exit(-1); +#endif + + } + break; + case simil::TDataType::TBlueConfig: + case simil::TDataType::TCSV: + case simil::TDataType::THDF5: + mainWindow.loadData(dataType, networkFile, activityFile, simType, subsetEventFile); + break; + default: + break; } return application.exec(); diff --git a/visimpl/visimpl.ui b/visimpl/visimpl.ui index 7342c7778aad9204f00507049abf511a2d15f8c8..53361d1dc9b62acd20f0b8ed3e55a1a7065f0fec 100644 --- a/visimpl/visimpl.ui +++ b/visimpl/visimpl.ui @@ -34,6 +34,7 @@ <addaction name="actionOpenBlueConfig"/> <addaction name="actionOpenCSVFiles"/> <addaction name="actionOpenH5Files"/> + <addaction name="actionConnectREST"/> <addaction name="separator"/> <addaction name="actionOpenSubsetEventsFile"/> <addaction name="separator"/> @@ -71,6 +72,8 @@ <addaction name="separator"/> <addaction name="actionUpdateOnIdle"/> <addaction name="actionShowFPSOnIdleUpdate"/> + <addaction name="separator"/> + <addaction name="actionConfigureREST"/> </widget> <widget class="QMenu" name="stackVizOptions"> <property name="title"> @@ -115,6 +118,7 @@ <addaction name="actionOpenBlueConfig"/> <addaction name="actionOpenCSVFiles"/> <addaction name="actionOpenH5Files"/> + <addaction name="actionConnectREST"/> <addaction name="separator"/> <addaction name="actionOpenSubsetEventsFile"/> <addaction name="separator"/> @@ -199,7 +203,7 @@ <normaloff>:/icons/close.svg</normaloff>:/icons/close.svg</iconset> </property> <property name="text"> - <string>Close Data</string> + <string>Close Dataset</string> </property> <property name="toolTip"> <string>Close Data</string> @@ -572,6 +576,32 @@ <string>Remove camera position...</string> </property> </action> + <action name="actionConnectREST"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/icons/folder-rest.svg</normaloff>:/icons/folder-rest.svg</iconset> + </property> + <property name="text"> + <string>Connect to REST server...</string> + </property> + <property name="toolTip"> + <string>Connects to a REST API server...</string> + </property> + </action> + <action name="actionConfigureREST"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Configure REST connection...</string> + </property> + <property name="toolTip"> + <string>Configures REST connection options.</string> + </property> + </action> </widget> <resources> <include location="resources.qrc"/>