From 3a529c30e79fdd5be130ff71c7e2ffeabdf06924 Mon Sep 17 00:00:00 2001 From: GPayne Date: Thu, 24 Feb 2022 23:16:17 -0700 Subject: [PATCH] Added save file dialog and option to run with temp config file --- .../launcher/include/sgctedit/filesupport.h | 38 ++++++-- .../ext/launcher/include/sgctedit/sgctedit.h | 6 +- .../ext/launcher/src/launcherwindow.cpp | 26 ++++-- .../ext/launcher/src/sgctedit/filesupport.cpp | 90 ++++++++++--------- .../ext/launcher/src/sgctedit/sgctedit.cpp | 17 ++-- 5 files changed, 117 insertions(+), 60 deletions(-) diff --git a/apps/OpenSpace/ext/launcher/include/sgctedit/filesupport.h b/apps/OpenSpace/ext/launcher/include/sgctedit/filesupport.h index e713596465..669995675f 100644 --- a/apps/OpenSpace/ext/launcher/include/sgctedit/filesupport.h +++ b/apps/OpenSpace/ext/launcher/include/sgctedit/filesupport.h @@ -27,14 +27,17 @@ #include +#include #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -49,23 +52,44 @@ using ProjectionOptions = std::variant< sgct::config::SpoutOutputProjection >; +struct SgctConfigElements { + std::vector& windowList; + sgct::config::Cluster& cluster; +}; + +struct UserConfigurationElements { + std::vector& monitorList; + std::shared_ptr display; + Orientation* orientation; + const std::string configSavePath; +}; + class FileSupport : public QWidget { Q_OBJECT public: - FileSupport(QVBoxLayout* parentLayout, std::vector& monitorList, - std::shared_ptr display, Orientation* orientation, - std::vector& windowList, sgct::config::Cluster& cluster, - std::function cb); + /** + * Constructor for FileSupport class, which saves the window configuration settings + * into the SGCT json structure according to the sgct code + * + * \param parentLayout Qt vertical (QVBoxLayout) layout where controls are added + * \param cfgElements struct of elements needed to read user settings from GUI + * \param sgctElements struct of the window and cluster objects needed for saving + * \param finishedCallback function to be called when user has selected to either + * save changes to file, apply and run without saving, or cancel + */ + FileSupport(QVBoxLayout* parentLayout, UserConfigurationElements& cfgElements, + SgctConfigElements& sgctElements, std::function finishedCallback); std::string saveFilename(); private slots: - void filenameEdited(const QString& newString); void cancel(); void save(); + void apply(); private: bool isWindowFullscreen(unsigned int monitorIdx, sgct::ivec2 wDims); std::optional findGuiWindow(); + void saveConfigToSgctFormat(); void saveCluster(); void saveWindows(); void saveUser(); @@ -80,13 +104,15 @@ private: QHBoxLayout* _layoutButtonBox = nullptr; QPushButton* _saveButton = nullptr; QPushButton* _cancelButton = nullptr; + QPushButton* _applyButton = nullptr; std::shared_ptr _displayWidget; Orientation* _orientationWidget; std::vector& _monitors; sgct::config::Cluster& _cluster; std::vector& _windowList; - QLineEdit* _lineFilename = nullptr; std::function _finishedCallback; + const std::string _userConfigPath; + std::string _saveTarget; }; #endif // __OPENSPACE_UI_LAUNCHER___FILESUPPORT___H__ diff --git a/apps/OpenSpace/ext/launcher/include/sgctedit/sgctedit.h b/apps/OpenSpace/ext/launcher/include/sgctedit/sgctedit.h index a664a60706..8891341f8d 100644 --- a/apps/OpenSpace/ext/launcher/include/sgctedit/sgctedit.h +++ b/apps/OpenSpace/ext/launcher/include/sgctedit/sgctedit.h @@ -57,9 +57,12 @@ public: * objects that will be modified by the window configuration settings * \param screenList A QList containing a QScreen object for each monitor in the * system + * \param userConfigPath A string containing the file path of the user config + * directory where all window configs are stored */ SgctEdit(QWidget* parent, std::vector& windowList, - sgct::config::Cluster& cluster, const QList& screenList); + sgct::config::Cluster& cluster, const QList& screenList, + const std::string userConfigPath); ~SgctEdit(); /** * Used to determine if the window configuration was saved to file, or canceled @@ -89,6 +92,7 @@ private: Orientation* _orientationWidget = nullptr; sgct::config::Cluster& _cluster; std::vector& _windowList; + const std::string _userConfigPath; bool _saveSelected = false; unsigned int _nMaxWindows = 3; const std::array _colorsForWindows = { diff --git a/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp b/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp index e6aba73710..36a1841b74 100644 --- a/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp +++ b/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp @@ -500,6 +500,8 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) { ); } + //Always add the .cfg sgct default as first item + _windowConfigBox->insertItem(0, QString::fromStdString(_sgctConfigName)); // Try to find the requested configuration file and set it as the current one. As we // have support for function-generated configuration files that will not be in the // list we need to add a preset that doesn't exist a file for @@ -509,8 +511,11 @@ void LauncherWindow::populateWindowConfigsList(std::string preset) { } else { // Add the requested preset at the top - _windowConfigBox->insertItem(0, QString::fromStdString(preset)); - _windowConfigBox->setCurrentIndex(0); + _windowConfigBox->insertItem(1, QString::fromStdString(preset)); + //Increment the user config count because there is an additional option added + //before the user config options + _userConfigCount++; + _windowConfigBox->setCurrentIndex(1); } } @@ -559,19 +564,26 @@ void LauncherWindow::openWindowEditor() { } sgct::config::Cluster cluster; std::vector windowList; - SgctEdit editor(this, windowList, cluster, screenList); + SgctEdit editor(this, windowList, cluster, screenList, _userConfigPath); editor.exec(); if (editor.wasSaved()) { - std::string fullFilename = editor.saveFilename() + ".json"; - const std::string path = _userConfigPath + fullFilename; + std::string ext = ".json"; + std::string savePath = editor.saveFilename(); + if (savePath.size() >= ext.size() + && !(savePath.substr(savePath.size() - ext.size()).compare(ext) == 0)) + { + savePath += ext; + } if (cluster.nodes.size() == 0) { cluster.nodes.push_back(sgct::config::Node()); } for (auto w : windowList) { cluster.nodes[0].windows.push_back(w); } - saveWindowConfig(this, path, cluster); - populateWindowConfigsList(fullFilename); + saveWindowConfig(this, savePath, cluster); + //Truncate path to convert this back to path relative to _userConfigPath + savePath = savePath.substr(_userConfigPath.size()); + populateWindowConfigsList(savePath); } else { const std::string current = _windowConfigBox->currentText().toStdString(); diff --git a/apps/OpenSpace/ext/launcher/src/sgctedit/filesupport.cpp b/apps/OpenSpace/ext/launcher/src/sgctedit/filesupport.cpp index 58033bd02b..f76f64ea0e 100644 --- a/apps/OpenSpace/ext/launcher/src/sgctedit/filesupport.cpp +++ b/apps/OpenSpace/ext/launcher/src/sgctedit/filesupport.cpp @@ -24,50 +24,37 @@ #include "sgctedit/filesupport.h" -FileSupport::FileSupport(QVBoxLayout* parentLayout, std::vector& monitorList, - std::shared_ptr display, Orientation* orientation, - std::vector& windowList, - sgct::config::Cluster& cluster, std::function cb) - : _displayWidget(display) - , _orientationWidget(orientation) - , _monitors(monitorList) - , _cluster(cluster) - , _windowList(windowList) - , _finishedCallback(cb) +FileSupport::FileSupport(QVBoxLayout* parentLayout, + UserConfigurationElements& cfgElements, + SgctConfigElements& sgctElements, + std::function finishedCallback) + : _displayWidget(cfgElements.display) + , _orientationWidget(cfgElements.orientation) + , _monitors(cfgElements.monitorList) + , _cluster(sgctElements.cluster) + , _windowList(sgctElements.windowList) + , _finishedCallback(finishedCallback) + , _userConfigPath(cfgElements.configSavePath) { QVBoxLayout* layoutFullVertical = new QVBoxLayout; - _lineFilename = new QLineEdit; - _lineFilename->setFixedWidth(190); - { - QHBoxLayout* layoutFilename = new QHBoxLayout; - QLabel* labelFilename = new QLabel; - QString fileTip = "Enter a filename for this custom configuration to be saved " - "as a .json file in the user/config/ directory"; - labelFilename->setToolTip(fileTip); - _lineFilename->setToolTip(fileTip); - labelFilename->setText("Filename: "); - layoutFilename->addStretch(1); - layoutFilename->addWidget(labelFilename); - layoutFilename->addWidget(_lineFilename); - layoutFilename->addStretch(1); - layoutFullVertical->addLayout(layoutFilename); - } - _saveButton = new QPushButton("Save"); - _saveButton->setToolTip("Save global orientation changes"); + _saveButton = new QPushButton("Save As"); + _saveButton->setToolTip("Save configuration changes (opens file chooser dialog)"); connect(_saveButton, &QPushButton::released, this, &FileSupport::save); - _saveButton->setEnabled(false); _cancelButton = new QPushButton("Cancel"); - _cancelButton->setToolTip("Cancel global orientation changes"); + _cancelButton->setToolTip("Cancel changes"); connect(_cancelButton, &QPushButton::released, this, &FileSupport::cancel); + _applyButton = new QPushButton("Apply Without Saving"); + _applyButton->setToolTip("Apply configuration changes without saving to file"); + connect(_applyButton, &QPushButton::released, this, &FileSupport::apply); { QHBoxLayout* layoutButtonBox = new QHBoxLayout; layoutButtonBox->addStretch(1); - layoutButtonBox->addWidget(_saveButton); layoutButtonBox->addWidget(_cancelButton); + layoutButtonBox->addWidget(_saveButton); + layoutButtonBox->addWidget(_applyButton); layoutFullVertical->addLayout(layoutButtonBox); } parentLayout->addLayout(layoutFullVertical); - connect(_lineFilename, &QLineEdit::textEdited, this, &FileSupport::filenameEdited); } void FileSupport::saveCluster() { @@ -251,21 +238,42 @@ ProjectionOptions FileSupport::saveProjectionNoSpout( } } -void FileSupport::filenameEdited(const QString& newString) { - _saveButton->setEnabled(!newString.isEmpty()); -} - std::string FileSupport::saveFilename() { - return _lineFilename->text().toStdString(); + return _saveTarget; } void FileSupport::save() { - saveCluster(); - saveWindows(); - saveUser(); - _finishedCallback(true); + QString fileName = QFileDialog::getSaveFileName(this, + "Save Window Configuration File", QString::fromStdString(_userConfigPath), + "Window Configuration (*.json);;(*.json)", nullptr, + QFileDialog::DontUseNativeDialog); + if (fileName.length() != 0) { + _saveTarget = fileName.toStdString(); + saveConfigToSgctFormat(); + _finishedCallback(true); + } } void FileSupport::cancel() { _finishedCallback(false); } + +void FileSupport::apply() { + std::string userCfgTempDir = _userConfigPath; + if (userCfgTempDir.back() != '/') { + userCfgTempDir += "/"; + } + userCfgTempDir += "temp"; + if (!std::filesystem::is_directory(userCfgTempDir)) { + std::filesystem::create_directories(absPath(userCfgTempDir)); + } + _saveTarget = userCfgTempDir + "/" + "apply-without-saving.json"; + saveConfigToSgctFormat(); + _finishedCallback(true); +} + +void FileSupport::saveConfigToSgctFormat() { + saveCluster(); + saveWindows(); + saveUser(); +} diff --git a/apps/OpenSpace/ext/launcher/src/sgctedit/sgctedit.cpp b/apps/OpenSpace/ext/launcher/src/sgctedit/sgctedit.cpp index aa94140a98..c12fa05097 100644 --- a/apps/OpenSpace/ext/launcher/src/sgctedit/sgctedit.cpp +++ b/apps/OpenSpace/ext/launcher/src/sgctedit/sgctedit.cpp @@ -23,12 +23,15 @@ ****************************************************************************************/ #include "sgctedit/sgctedit.h" +#include SgctEdit::SgctEdit(QWidget* parent, std::vector& windowList, - sgct::config::Cluster& cluster, const QList& screenList) + sgct::config::Cluster& cluster, const QList& screenList, + const std::string userConfigPath) : QDialog(parent) , _cluster(cluster) , _windowList(windowList) + , _userConfigPath(userConfigPath) { systemMonitorConfiguration(screenList); setWindowTitle("Window Configuration Editor"); @@ -79,13 +82,17 @@ void SgctEdit::createWidgets() { { layoutMainV->addLayout(layoutMainH); _orientationWidget->addControlsToParentLayout(layoutMainV); - _fileSupportWidget = new FileSupport( - layoutMainV, + SgctConfigElements sgctCfg = {_windowList, _cluster}; + UserConfigurationElements userCfg = { _monitorSizeList, _displayWidget, _orientationWidget, - _windowList, - _cluster, + _userConfigPath + }; + _fileSupportWidget = new FileSupport( + layoutMainV, + userCfg, + sgctCfg, [this](bool accepted) { if (accepted) { _saveSelected = true;