diff --git a/CMakeLists.txt b/CMakeLists.txt index 760bdd7dad49e20ed762ab433c9f05a805fdb5b2..239b2c06bbdc61b411bbf12b42cfc615f89feb7d 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.7.3 ) +project( visimpl VERSION 1.7.4 ) set( visimpl_VERSION_ABI 6 ) SET( VISIMPL_LICENSE "GPL") diff --git a/stackviz/MainWindow.cpp b/stackviz/MainWindow.cpp index f215cfeb799be93eabefbc7490974271f49130f2..299567871e61ec3d81d59e7f616a2f076666bf7a 100644 --- a/stackviz/MainWindow.cpp +++ b/stackviz/MainWindow.cpp @@ -50,6 +50,9 @@ #include <QShortcut> #include <QDateTime> #include <QtGlobal> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> #include <boost/bind.hpp> @@ -162,11 +165,15 @@ void MainWindow::init( const std::string &session ) connect( _ui->actionOpenSubsetEventsFile, SIGNAL( triggered( void )), this, SLOT( openSubsetEventsFileThroughDialog( void ))); + + connect( _ui->actionOpenGroupsFile, SIGNAL( triggered( void )), + this, SLOT( openGroupsThroughDialog( void ))); connect( _ui->actionCloseData, SIGNAL(triggered(bool)), this, SLOT(closeData())); _ui->actionOpenSubsetEventsFile->setEnabled(false); + _ui->actionOpenGroupsFile->setEnabled(false); initPlaybackDock( ); @@ -1049,6 +1056,7 @@ void MainWindow::updateUIonOpen(const std::string &eventsFile) _ui->actionShowDataManager->setEnabled(true); _ui->actionOpenSubsetEventsFile->setEnabled(true); + _ui->actionOpenGroupsFile->setEnabled(true); _ui->actionCloseData->setEnabled(true); _dockSimulation->setEnabled(true); @@ -1459,3 +1467,112 @@ void stackviz::MainWindow::loadRESTData(const simil::LoaderRestData::Configurati m_loader->start( ); } #endif + +void MainWindow::openGroupsThroughDialog() +{ + const auto title = tr("Load Groups"); + + const QString groupsFilename = QFileDialog::getOpenFileName(this, title, + _lastOpenedGroupsFileName, + tr("Json files (*.json)"), + nullptr, QFileDialog::ReadOnly | QFileDialog::DontUseNativeDialog); + + if (groupsFilename.isEmpty()) + return; + + QFile file{groupsFilename}; + if (!file.open(QIODevice::ReadOnly)) + { + const auto message = tr("Couldn't open file %1").arg(groupsFilename); + + QMessageBox msgbox(this); + msgbox.setWindowTitle(title); + msgbox.setIcon(QMessageBox::Icon::Critical); + msgbox.setText(message); + msgbox.setWindowIcon(QIcon(":/visimpl.png")); + msgbox.setStandardButtons(QMessageBox::Ok); + msgbox.exec(); + return; + } + + const auto contents = file.readAll(); + QJsonParseError jsonError; + const auto jsonDoc = QJsonDocument::fromJson(contents, &jsonError); + if (jsonDoc.isNull() || !jsonDoc.isObject()) + { + const auto message = tr("Couldn't read the contents of %1 or parsing error.").arg(groupsFilename); + + QMessageBox msgbox{this}; + msgbox.setWindowTitle(title); + msgbox.setIcon(QMessageBox::Icon::Critical); + msgbox.setText(message); + msgbox.setWindowIcon(QIcon(":/visimpl.png")); + msgbox.setStandardButtons(QMessageBox::Ok); + msgbox.setDetailedText(jsonError.errorString()); + msgbox.exec(); + return; + } + + const auto jsonObj = jsonDoc.object(); + if (jsonObj.isEmpty()) + { + const auto message = tr("Error parsing the contents of %1.").arg(groupsFilename); + + QMessageBox msgbox{this}; + msgbox.setWindowTitle(title); + msgbox.setIcon(QMessageBox::Icon::Critical); + msgbox.setText(message); + msgbox.setWindowIcon(QIcon(":/visimpl.png")); + msgbox.setStandardButtons(QMessageBox::Ok); + msgbox.exec(); + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + + const auto jsonGroups = jsonObj.value("groups").toArray(); + for (const auto group : jsonGroups) + { + const auto o = group.toObject(); + + const auto name = o.value("name").toString(); + const auto gidsStrings = o.value("gids").toString().split(","); + + visimpl::GIDUSet gids; + auto addGids = [&gids](const QString s) + { + if (s.contains(":")) + { + auto limits = s.split(":"); + for (unsigned int id = limits.first().toUInt(); + id <= limits.last().toUInt(); ++id) + gids.insert(id); + } + else + { + gids.insert(s.toUInt()); + } + }; + std::for_each(gidsStrings.cbegin(), gidsStrings.cend(), addGids); + + visimpl::Selection selection; + selection.gids = gids; + selection.name = name.toStdString(); + +#ifdef VISIMPL_USE_ZEROEQ + _summary->AddNewHistogram(selection, false); +#else + _summary->AddNewHistogram(selection); +#endif + } + + _summary->UpdateHistograms(); + + if (_displayManager) + { + _displayManager->dirtyHistograms(); + _displayManager->refresh(); + } + + QApplication::restoreOverrideCursor(); +} \ No newline at end of file diff --git a/stackviz/MainWindow.h b/stackviz/MainWindow.h index 68c92774b470b545c101fc7f115e83c711df0eec..3b22f3963002304c221890c48a1dd8268bbc35aa 100644 --- a/stackviz/MainWindow.h +++ b/stackviz/MainWindow.h @@ -94,6 +94,7 @@ namespace stackviz void openH5FilesThroughDialog( void ); void openSubsetEventsFileThroughDialog( void ); void openRESTThroughDialog(); + void openGroupsThroughDialog(); void aboutDialog( void ); void togglePlaybackDock( void ); @@ -167,6 +168,7 @@ namespace stackviz QString _lastOpenedFileNamePath; QString _lastOpenedSubsetsFileName; + QString _lastOpenedGroupsFileName; simil::TSimulationType _simulationType; diff --git a/stackviz/stackviz.ui b/stackviz/stackviz.ui index d88a43f25429b712cf82f9ff77752b1f516f2701..5ad539b2f887b7a46f4cbc5c2fb133df9ec197fb 100644 --- a/stackviz/stackviz.ui +++ b/stackviz/stackviz.ui @@ -24,7 +24,7 @@ <x>0</x> <y>0</y> <width>1280</width> - <height>22</height> + <height>24</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -38,6 +38,8 @@ <addaction name="separator"/> <addaction name="actionOpenSubsetEventsFile"/> <addaction name="separator"/> + <addaction name="actionOpenGroupsFile"/> + <addaction name="separator"/> <addaction name="actionCloseData"/> <addaction name="separator"/> <addaction name="actionQuit"/> @@ -340,6 +342,21 @@ <string>Ctrl+Q</string> </property> </action> + <action name="actionOpenGroupsFile"> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/icons/folder-doc.svg</normaloff>:/icons/folder-doc.svg</iconset> + </property> + <property name="text"> + <string>Open Groups file...</string> + </property> + <property name="toolTip"> + <string>Open groups as histograms</string> + </property> + <property name="shortcut"> + <string>Ctrl+G</string> + </property> + </action> </widget> <resources> <include location="resources.qrc"/>