From a4382f72d7fb924f9649ae352d70a36df2d662a8 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Tue, 29 Sep 2020 10:17:47 -0400 Subject: CMake GUI: Add presets functionality --- Source/QtDialog/CMakeLists.txt | 8 + Source/QtDialog/CMakeSetup.cxx | 25 +- Source/QtDialog/CMakeSetupDialog.cxx | 86 ++++++- Source/QtDialog/CMakeSetupDialog.h | 12 + Source/QtDialog/CMakeSetupDialog.ui | 23 +- Source/QtDialog/FirstConfigure.cxx | 54 ++++- Source/QtDialog/FirstConfigure.h | 15 ++ Source/QtDialog/QCMake.cxx | 160 +++++++++++++ Source/QtDialog/QCMake.h | 23 ++ Source/QtDialog/QCMakePreset.cxx | 50 ++++ Source/QtDialog/QCMakePreset.h | 30 +++ Source/QtDialog/QCMakePresetComboBox.cxx | 64 +++++ Source/QtDialog/QCMakePresetComboBox.h | 35 +++ Source/QtDialog/QCMakePresetItemModel.cxx | 143 +++++++++++ Source/QtDialog/QCMakePresetItemModel.h | 45 ++++ Tests/CMakeGUI/CMakeGUITest.cmake | 38 +++ Tests/CMakeGUI/CMakeGUITest.cxx | 265 +++++++++++++++++++++ Tests/CMakeGUI/CMakeGUITest.h | 3 + Tests/CMakeGUI/CMakeLists.txt | 21 ++ Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx | 80 +++++++ Tests/CMakeGUI/QCMakePresetComboBoxTest.h | 13 + Tests/CMakeGUI/QCMakePresetItemModelTest.cxx | 162 +++++++++++++ Tests/CMakeGUI/QCMakePresetItemModelTest.h | 17 ++ Tests/CMakeGUI/QCMakePresetTest.cxx | 82 +++++++ Tests/CMakeGUI/QCMakePresetTest.h | 14 ++ .../CMakePresets.json.in | 33 +++ .../CMakeGUI/presetArg-preset/CMakePresets.json.in | 33 +++ .../presetArg-presetBinary/CMakePresets.json.in | 33 +++ .../CMakePresets.json.in | 39 +++ .../presetArg-presetConfigExists/CMakeLists.txt.in | 2 + .../CMakePresets.json.in | 33 +++ .../presetArg-presetConfigExists/CMakeSetup.ini.in | 2 + 32 files changed, 1632 insertions(+), 11 deletions(-) create mode 100644 Source/QtDialog/QCMakePreset.cxx create mode 100644 Source/QtDialog/QCMakePreset.h create mode 100644 Source/QtDialog/QCMakePresetComboBox.cxx create mode 100644 Source/QtDialog/QCMakePresetComboBox.h create mode 100644 Source/QtDialog/QCMakePresetItemModel.cxx create mode 100644 Source/QtDialog/QCMakePresetItemModel.h create mode 100644 Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx create mode 100644 Tests/CMakeGUI/QCMakePresetComboBoxTest.h create mode 100644 Tests/CMakeGUI/QCMakePresetItemModelTest.cxx create mode 100644 Tests/CMakeGUI/QCMakePresetItemModelTest.h create mode 100644 Tests/CMakeGUI/QCMakePresetTest.cxx create mode 100644 Tests/CMakeGUI/QCMakePresetTest.h create mode 100644 Tests/CMakeGUI/presetArg-noPresetBinaryChange/CMakePresets.json.in create mode 100644 Tests/CMakeGUI/presetArg-preset/CMakePresets.json.in create mode 100644 Tests/CMakeGUI/presetArg-presetBinary/CMakePresets.json.in create mode 100644 Tests/CMakeGUI/presetArg-presetBinaryChange/CMakePresets.json.in create mode 100644 Tests/CMakeGUI/presetArg-presetConfigExists/CMakeLists.txt.in create mode 100644 Tests/CMakeGUI/presetArg-presetConfigExists/CMakePresets.json.in create mode 100644 Tests/CMakeGUI/presetArg-presetConfigExists/CMakeSetup.ini.in diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 5fd0e89..394762a 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -92,6 +92,12 @@ set(SRCS QCMake.h QCMakeCacheView.cxx QCMakeCacheView.h + QCMakePreset.cxx + QCMakePreset.h + QCMakePresetComboBox.cxx + QCMakePresetComboBox.h + QCMakePresetItemModel.cxx + QCMakePresetItemModel.h QCMakeWidgets.cxx QCMakeWidgets.h RegexExplorer.cxx @@ -116,6 +122,8 @@ qt5_wrap_cpp(MOC_SRCS FirstConfigure.h QCMake.h QCMakeCacheView.h + QCMakePresetComboBox.h + QCMakePresetItemModel.h QCMakeWidgets.h RegexExplorer.h WarningMessagesDialog.h diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 37c1f15..a5b2f34 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -32,7 +32,8 @@ static const char* cmDocumentationUsage[][2] = { " cmake-gui [options]\n" " cmake-gui [options] \n" " cmake-gui [options] \n" - " cmake-gui [options] -S -B \n" }, + " cmake-gui [options] -S -B \n" + " cmake-gui [options] -S --preset=\n" }, { nullptr, nullptr } }; @@ -147,6 +148,7 @@ int main(int argc, char** argv) QStringList args = QApplication::arguments(); std::string binaryDirectory; std::string sourceDirectory; + std::string presetName; for (int i = 1; i < args.size(); ++i) { const QString& arg = args[i]; if (arg.startsWith("-S")) { @@ -185,11 +187,28 @@ int main(int argc, char** argv) binaryDirectory = cmSystemTools::CollapseFullPath(path.toLocal8Bit().data()); cmSystemTools::ConvertToUnixSlashes(binaryDirectory); + } else if (arg.startsWith("--preset=")) { + QString preset = arg.mid(cmStrLen("--preset=")); + if (preset.isEmpty()) { + std::cerr << "No preset specified for --preset" << std::endl; + return 1; + } + presetName = preset.toLocal8Bit().data(); } } - if (!sourceDirectory.empty() && !binaryDirectory.empty()) { + if (!sourceDirectory.empty() && + (!binaryDirectory.empty() || !presetName.empty())) { dialog.setSourceDirectory(QString::fromLocal8Bit(sourceDirectory.c_str())); - dialog.setBinaryDirectory(QString::fromLocal8Bit(binaryDirectory.c_str())); + if (!binaryDirectory.empty()) { + dialog.setBinaryDirectory( + QString::fromLocal8Bit(binaryDirectory.c_str())); + if (!presetName.empty()) { + dialog.setStartupBinaryDirectory(true); + } + } + if (!presetName.empty()) { + dialog.setDeferredPreset(QString::fromLocal8Bit(presetName.c_str())); + } } else { if (args.count() == 2) { std::string filePath = diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index df22028..acd32ec 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #ifdef QT_WINEXTRAS # include @@ -263,6 +265,8 @@ void CMakeSetupDialog::initialize() &CMakeSetupDialog::onBinaryDirectoryChanged); QObject::connect(this->SourceDirectory, &QLineEdit::textChanged, this, &CMakeSetupDialog::onSourceDirectoryChanged); + QObject::connect(this->Preset, &QCMakePresetComboBox::presetChanged, this, + &CMakeSetupDialog::onBuildPresetChanged); QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::sourceDirChanged, this, @@ -270,6 +274,13 @@ void CMakeSetupDialog::initialize() QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::binaryDirChanged, this, &CMakeSetupDialog::updateBinaryDirectory); + QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::presetsChanged, + this, &CMakeSetupDialog::updatePresets); + QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::presetChanged, + this, &CMakeSetupDialog::updatePreset); + QObject::connect(this->CMakeThread->cmakeInstance(), + &QCMake::presetLoadError, this, + &CMakeSetupDialog::showPresetLoadError); QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::progressChanged, this, @@ -314,9 +325,15 @@ void CMakeSetupDialog::initialize() QObject::connect(this->WarnUninitializedAction, &QAction::triggered, this->CMakeThread->cmakeInstance(), &QCMake::setWarnUninitializedMode); + QObject::connect(this->CMakeThread->cmakeInstance(), + &QCMake::warnUninitializedModeChanged, + this->WarnUninitializedAction, &QAction::setChecked); - if (!this->SourceDirectory->text().isEmpty() || - !this->BinaryDirectory->lineEdit()->text().isEmpty()) { + if (!this->SourceDirectory->text().isEmpty() && + !this->DeferredPreset.isNull()) { + this->onSourceDirectoryChanged(this->SourceDirectory->text()); + } else if (!this->SourceDirectory->text().isEmpty() || + !this->BinaryDirectory->lineEdit()->text().isEmpty()) { this->onSourceDirectoryChanged(this->SourceDirectory->text()); this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text()); } else { @@ -671,6 +688,41 @@ void CMakeSetupDialog::updateBinaryDirectory(const QString& dir) } } +void CMakeSetupDialog::updatePresets(const QVector& presets) +{ + if (this->Preset->presets() != presets) { + this->Preset->blockSignals(true); + this->Preset->setPresets(presets); + this->Preset->blockSignals(false); + } + + this->Preset->setHidden(presets.isEmpty()); + this->PresetLabel->setHidden(presets.isEmpty()); + + if (!this->DeferredPreset.isNull()) { + this->Preset->setPresetName(this->DeferredPreset); + this->DeferredPreset = QString{}; + } +} + +void CMakeSetupDialog::updatePreset(const QString& name) +{ + if (this->Preset->presetName() != name) { + this->Preset->blockSignals(true); + this->Preset->setPresetName(name); + this->Preset->blockSignals(false); + } +} + +void CMakeSetupDialog::showPresetLoadError( + const QString& dir, cmCMakePresetsFile::ReadFileResult result) +{ + QMessageBox::warning( + this, "Error Reading CMake Presets", + QString::fromLocal8Bit("Could not read presets from %1: %2") + .arg(dir, cmCMakePresetsFile::ResultToString(result))); +} + void CMakeSetupDialog::doBinaryBrowse() { QString dir = QFileDialog::getExistingDirectory( @@ -686,6 +738,11 @@ void CMakeSetupDialog::setBinaryDirectory(const QString& dir) this->BinaryDirectory->setEditText(dir); } +void CMakeSetupDialog::setStartupBinaryDirectory(bool startup) +{ + this->StartupBinaryDirectory = startup; +} + void CMakeSetupDialog::onSourceDirectoryChanged(const QString& dir) { this->Output->clear(); @@ -711,11 +768,24 @@ void CMakeSetupDialog::onBinaryDirectoryChanged(const QString& dir) Q_ARG(QString, dir)); } +void CMakeSetupDialog::onBuildPresetChanged(const QString& name) +{ + QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "setPreset", + Qt::QueuedConnection, Q_ARG(QString, name), + Q_ARG(bool, !this->StartupBinaryDirectory)); + this->StartupBinaryDirectory = false; +} + void CMakeSetupDialog::setSourceDirectory(const QString& dir) { this->SourceDirectory->setText(dir); } +void CMakeSetupDialog::setDeferredPreset(const QString& preset) +{ + this->DeferredPreset = preset; +} + void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent) { percent = (percent * ProgressFactor) + ProgressOffset; @@ -753,6 +823,7 @@ void CMakeSetupDialog::setEnabledState(bool enabled) this->CacheValues->cacheModel()->setEditEnabled(enabled); this->SourceDirectory->setEnabled(enabled); this->BrowseSourceDirectoryButton->setEnabled(enabled); + this->Preset->setEnabled(enabled); this->BinaryDirectory->setEnabled(enabled); this->BrowseBinaryDirectoryButton->setEnabled(enabled); this->ReloadCacheAction->setEnabled(enabled); @@ -777,6 +848,17 @@ bool CMakeSetupDialog::setupFirstConfigure() // restore from settings dialog.loadFromSettings(); + auto presetData = this->Preset->currentData(); + if (presetData.isValid()) { + auto preset = presetData.value(); + dialog.setCurrentGenerator(preset.generator); + if (preset.setGenConfig) { + dialog.setPlatform(preset.architecture); + dialog.setToolset(preset.toolset); + } + dialog.setCompilerOption(CompilerOption::DefaultNative); + } + if (dialog.exec() == QDialog::Accepted) { dialog.saveToSettings(); this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator()); diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h index d752ef2..f0cc929 100644 --- a/Source/QtDialog/CMakeSetupDialog.h +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -5,12 +5,15 @@ #include #include "QCMake.h" +#include "QCMakePreset.h" #include #include #include +#include #include "ui_CMakeSetupDialog.h" +class QCMakePresetItemModel; class QCMakeThread; class CMakeCacheModel; class QProgressBar; @@ -33,6 +36,8 @@ public: public slots: void setBinaryDirectory(const QString& dir); void setSourceDirectory(const QString& dir); + void setDeferredPreset(const QString& preset); + void setStartupBinaryDirectory(bool startup); protected slots: void initialize(); @@ -52,6 +57,10 @@ protected slots: void doDeleteCache(); void updateSourceDirectory(const QString& dir); void updateBinaryDirectory(const QString& dir); + void updatePresets(const QVector& presets); + void updatePreset(const QString& name); + void showPresetLoadError(const QString& dir, + cmCMakePresetsFile::ReadFileResult result); void showProgress(const QString& msg, float percent); void setEnabledState(bool); bool setupFirstConfigure(); @@ -62,6 +71,7 @@ protected slots: void saveBuildPaths(const QStringList&); void onBinaryDirectoryChanged(const QString& dir); void onSourceDirectoryChanged(const QString& dir); + void onBuildPresetChanged(const QString& name); void setCacheModified(); void removeSelectedCacheEntries(); void selectionChanged(); @@ -113,6 +123,8 @@ protected: QAction* WarnUninitializedAction; QAction* InstallForCommandLineAction; State CurrentState; + QString DeferredPreset; + bool StartupBinaryDirectory = false; QTextCharFormat ErrorFormat; QTextCharFormat MessageFormat; diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui index 5feee91..afb25eb 100644 --- a/Source/QtDialog/CMakeSetupDialog.ui +++ b/Source/QtDialog/CMakeSetupDialog.ui @@ -44,7 +44,7 @@ 6 - + Where is the source code: @@ -61,13 +61,23 @@ - + - Where to build the binaries: + Preset: + + + + + + Where to build the binaries: + + + + @@ -83,7 +93,7 @@ - + Browse &Build... @@ -367,6 +377,11 @@ QTreeView
QCMakeCacheView.h
+ + QCMakePresetComboBox + QComboBox +
QCMakePresetComboBox.h
+
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx index 918f137..10360bb 100644 --- a/Source/QtDialog/FirstConfigure.cxx +++ b/Source/QtDialog/FirstConfigure.cxx @@ -145,6 +145,36 @@ void StartCompilerSetup::setCurrentGenerator(const QString& gen) } } +void StartCompilerSetup::setPlatform(const QString& platform) +{ + this->PlatformOptions->setCurrentText(platform); +} + +void StartCompilerSetup::setToolset(const QString& toolset) +{ + this->Toolset->setText(toolset); +} + +void StartCompilerSetup::setCompilerOption(CompilerOption option) +{ + std::size_t index = 0; + switch (option) { + case CompilerOption::DefaultNative: + index = 0; + break; + case CompilerOption::SpecifyNative: + index = 1; + break; + case CompilerOption::ToolchainFile: + index = 2; + break; + case CompilerOption::Options: + index = 3; + break; + } + this->CompilerSetupOptions[index]->setChecked(true); +} + QString StartCompilerSetup::getGenerator() const { return this->GeneratorOptions->currentText(); @@ -482,6 +512,26 @@ void FirstConfigure::setGenerators( this->mStartCompilerSetupPage->setGenerators(gens); } +void FirstConfigure::setCurrentGenerator(const QString& gen) +{ + this->mStartCompilerSetupPage->setCurrentGenerator(gen); +} + +void FirstConfigure::setPlatform(const QString& platform) +{ + this->mStartCompilerSetupPage->setPlatform(platform); +} + +void FirstConfigure::setToolset(const QString& toolset) +{ + this->mStartCompilerSetupPage->setToolset(toolset); +} + +void FirstConfigure::setCompilerOption(CompilerOption option) +{ + this->mStartCompilerSetupPage->setCompilerOption(option); +} + QString FirstConfigure::getGenerator() const { return this->mStartCompilerSetupPage->getGenerator(); @@ -503,7 +553,7 @@ void FirstConfigure::loadFromSettings() // restore generator settings.beginGroup("Settings/StartPath"); QString lastGen = settings.value("LastGenerator").toString(); - this->mStartCompilerSetupPage->setCurrentGenerator(lastGen); + this->setCurrentGenerator(lastGen); settings.endGroup(); // restore compiler setup @@ -550,7 +600,7 @@ void FirstConfigure::loadFromSettings() // this prevents them from being taken from environment, while the // generator is taken from application settings if (!mDefaultGenerator.isEmpty()) { - this->mStartCompilerSetupPage->setCurrentGenerator(mDefaultGenerator); + this->setCurrentGenerator(mDefaultGenerator); } } diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h index ca5f52e..5844f3a 100644 --- a/Source/QtDialog/FirstConfigure.h +++ b/Source/QtDialog/FirstConfigure.h @@ -22,6 +22,14 @@ enum FirstConfigurePages Done }; +enum class CompilerOption +{ + DefaultNative, + SpecifyNative, + ToolchainFile, + Options, +}; + //! the first page that gives basic options for what compilers setup to choose //! from class StartCompilerSetup : public QWizardPage @@ -33,6 +41,9 @@ public: ~StartCompilerSetup(); void setGenerators(std::vector const& gens); void setCurrentGenerator(const QString& gen); + void setToolset(const QString& toolset); + void setPlatform(const QString& platform); + void setCompilerOption(CompilerOption option); QString getGenerator() const; QString getToolset() const; QString getPlatform() const; @@ -167,6 +178,10 @@ public: ~FirstConfigure(); void setGenerators(std::vector const& gens); + void setCurrentGenerator(const QString& gen); + void setToolset(const QString& toolset); + void setPlatform(const QString& platform); + void setCompilerOption(CompilerOption option); QString getGenerator() const; QString getPlatform() const; QString getToolset() const; diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 974c545..9017a63 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -2,10 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "QCMake.h" +#include + #include #include #include +#include +#include #include "cmExternalMakefileProjectGenerator.h" #include "cmGlobalGenerator.h" @@ -19,12 +23,15 @@ QCMake::QCMake(QObject* p) : QObject(p) + , StartEnvironment(QProcessEnvironment::systemEnvironment()) , Environment(QProcessEnvironment::systemEnvironment()) { this->WarnUninitializedMode = false; qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType>(); + qRegisterMetaType(); cmSystemTools::DisableRunCommandOutput(); cmSystemTools::SetRunCommandHideConsole(true); @@ -57,6 +64,17 @@ QCMake::QCMake(QObject* p) for (cmake::GeneratorInfo const& gen : generators) { this->AvailableGenerators.push_back(gen); } + + connect(&this->LoadPresetsTimer, &QTimer::timeout, this, [this]() { + this->loadPresets(); + if (!this->PresetName.isEmpty() && + this->CMakePresetsFile.Presets.find( + std::string(this->PresetName.toLocal8Bit())) == + this->CMakePresetsFile.Presets.end()) { + this->setPreset(QString{}); + } + }); + this->LoadPresetsTimer.start(1000); } QCMake::~QCMake() = default; @@ -73,6 +91,8 @@ void QCMake::setSourceDirectory(const QString& _dir) if (this->SourceDirectory != dir) { this->SourceDirectory = QDir::fromNativeSeparators(dir); emit this->sourceDirChanged(this->SourceDirectory); + this->loadPresets(); + this->setPreset(QString{}); } } @@ -129,6 +149,56 @@ void QCMake::setBinaryDirectory(const QString& _dir) } } +void QCMake::setPreset(const QString& name, bool setBinary) +{ + if (this->PresetName != name) { + this->PresetName = name; + emit this->presetChanged(this->PresetName); + + if (!name.isNull()) { + std::string presetName(name.toLocal8Bit()); + auto const& preset = this->CMakePresetsFile.Presets[presetName]; + auto expandedPreset = this->CMakePresetsFile.ExpandMacros(preset); + if (expandedPreset) { + if (setBinary) { + QString binaryDir = + QString::fromLocal8Bit(expandedPreset->BinaryDir.data()); + this->setBinaryDirectory(binaryDir); + } + if (expandedPreset->WarnDev) { + this->CMakeInstance->SetSuppressDevWarnings( + !*expandedPreset->WarnDev); + } + if (expandedPreset->ErrorDev) { + this->CMakeInstance->SetDevWarningsAsErrors( + *expandedPreset->ErrorDev); + } + if (expandedPreset->WarnDeprecated) { + this->CMakeInstance->SetSuppressDeprecatedWarnings( + !*expandedPreset->WarnDeprecated); + } + if (expandedPreset->ErrorDeprecated) { + this->CMakeInstance->SetDeprecatedWarningsAsErrors( + *expandedPreset->ErrorDeprecated); + } + if (expandedPreset->WarnUninitialized) { + this->WarnUninitializedMode = *expandedPreset->WarnUninitialized; + emit this->warnUninitializedModeChanged( + *expandedPreset->WarnUninitialized); + } + this->Environment = this->StartEnvironment; + for (auto const& v : expandedPreset->Environment) { + if (v.second) { + this->Environment.insert(QString::fromLocal8Bit(v.first.data()), + QString::fromLocal8Bit(v.second->data())); + } + } + } + } + emit this->propertiesChanged(this->properties()); + } +} + void QCMake::setGenerator(const QString& gen) { if (this->Generator != gen) { @@ -348,6 +418,56 @@ QCMakePropertyList QCMake::properties() const ret.append(prop); } + if (!this->PresetName.isNull()) { + std::string presetName(this->PresetName.toLocal8Bit()); + auto p = this->CMakePresetsFile.ExpandMacros( + this->CMakePresetsFile.Presets.at(presetName)); + if (p) { + for (auto const& v : p->CacheVariables) { + if (!v.second) { + continue; + } + QCMakeProperty prop; + prop.Key = QString::fromLocal8Bit(v.first.data()); + prop.Value = QString::fromLocal8Bit(v.second->Value.data()); + prop.Type = QCMakeProperty::STRING; + if (!v.second->Type.empty()) { + auto type = cmState::StringToCacheEntryType(v.second->Type); + switch (type) { + case cmStateEnums::BOOL: + prop.Type = QCMakeProperty::BOOL; + prop.Value = cmIsOn(v.second->Value); + break; + case cmStateEnums::PATH: + prop.Type = QCMakeProperty::PATH; + break; + case cmStateEnums::FILEPATH: + prop.Type = QCMakeProperty::FILEPATH; + break; + default: + prop.Type = QCMakeProperty::STRING; + break; + } + } + + // QCMakeCacheModel prefers variables earlier in the list rather than + // later, so overwrite them if they already exist rather than simply + // appending + bool found = false; + for (auto& orig : ret) { + if (orig.Key == prop.Key) { + orig = prop; + found = true; + break; + } + } + if (!found) { + ret.append(prop); + } + } + } + } + return ret; } @@ -405,6 +525,46 @@ void QCMake::setUpEnvironment() const } } +void QCMake::loadPresets() +{ + auto result = this->CMakePresetsFile.ReadProjectPresets( + this->SourceDirectory.toLocal8Bit().data(), true); + if (result != this->LastLoadPresetsResult && + result != cmCMakePresetsFile::ReadFileResult::READ_OK) { + emit this->presetLoadError(this->SourceDirectory, result); + } + this->LastLoadPresetsResult = result; + + QVector presets; + for (auto const& name : this->CMakePresetsFile.PresetOrder) { + auto const& p = this->CMakePresetsFile.Presets[name]; + if (p.Hidden) { + continue; + } + + QCMakePreset preset; + preset.name = std::move(QString::fromLocal8Bit(p.Name.data())); + preset.displayName = + std::move(QString::fromLocal8Bit(p.DisplayName.data())); + preset.description = + std::move(QString::fromLocal8Bit(p.Description.data())); + preset.generator = std::move(QString::fromLocal8Bit(p.Generator.data())); + preset.architecture = + std::move(QString::fromLocal8Bit(p.Architecture.data())); + preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data())); + preset.setGenConfig = !p.GeneratorConfig || + p.GeneratorConfig == cmCMakePresetsFile::CMakeGeneratorConfig::Default; + preset.enabled = std::find_if(this->AvailableGenerators.begin(), + this->AvailableGenerators.end(), + [&p](const cmake::GeneratorInfo& g) { + return g.name == p.Generator; + }) != this->AvailableGenerators.end() && + this->CMakePresetsFile.ExpandMacros(p); + presets.push_back(preset); + } + emit this->presetsChanged(presets); +} + QString QCMake::binaryDirectory() const { return this->BinaryDirectory; diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index f569951..a6751b0 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmCMakePresetsFile.h" #include "cmake.h" #ifdef _MSC_VER @@ -14,6 +15,7 @@ #include #include +#include "QCMakePreset.h" #include #include #include @@ -21,6 +23,7 @@ #include #include #include +#include #include /// struct to represent cmake properties in Qt @@ -57,6 +60,7 @@ using QCMakePropertyList = QList; Q_DECLARE_METATYPE(QCMakeProperty) Q_DECLARE_METATYPE(QCMakePropertyList) Q_DECLARE_METATYPE(QProcessEnvironment) +Q_DECLARE_METATYPE(cmCMakePresetsFile::ReadFileResult) /// Qt API for CMake library. /// Wrapper like class allows for easier integration with @@ -74,6 +78,8 @@ public slots: void setSourceDirectory(const QString& dir); /// set the binary directory to build in void setBinaryDirectory(const QString& dir); + /// set the preset name to use + void setPreset(const QString& name, bool setBinary = true); /// set the desired generator to use void setGenerator(const QString& generator); /// set the desired generator to use @@ -147,6 +153,15 @@ signals: void sourceDirChanged(const QString& dir); /// signal when the binary directory changes void binaryDirChanged(const QString& dir); + /// signal when the preset list changes + void presetsChanged(const QVector& presets); + /// signal when the selected preset changes + void presetChanged(const QString& name); + /// signal when there's an error reading the presets files + void presetLoadError(const QString& dir, + cmCMakePresetsFile::ReadFileResult error); + /// signal when uninitialized warning changes + void warnUninitializedModeChanged(bool value); /// signal for progress events void progressChanged(const QString& msg, float percent); /// signal when configure is done @@ -178,6 +193,8 @@ protected: void stderrCallback(std::string const& msg); void setUpEnvironment() const; + void loadPresets(); + bool WarnUninitializedMode; QString SourceDirectory; QString BinaryDirectory; @@ -185,7 +202,13 @@ protected: QString Platform; QString Toolset; std::vector AvailableGenerators; + cmCMakePresetsFile CMakePresetsFile; + cmCMakePresetsFile::ReadFileResult LastLoadPresetsResult = + cmCMakePresetsFile::ReadFileResult::READ_OK; + QString PresetName; QString CMakeExecutable; QAtomicInt InterruptFlag; + QProcessEnvironment StartEnvironment; QProcessEnvironment Environment; + QTimer LoadPresetsTimer; }; diff --git a/Source/QtDialog/QCMakePreset.cxx b/Source/QtDialog/QCMakePreset.cxx new file mode 100644 index 0000000..b10cf07 --- /dev/null +++ b/Source/QtDialog/QCMakePreset.cxx @@ -0,0 +1,50 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "QCMakePreset.h" + +bool operator==(const QCMakePreset& lhs, const QCMakePreset& rhs) +{ + return lhs.name == rhs.name && lhs.displayName == rhs.displayName && + lhs.description == rhs.description && lhs.generator == rhs.generator && + lhs.architecture == rhs.architecture && lhs.toolset == rhs.toolset && + lhs.setGenConfig == rhs.setGenConfig && lhs.enabled == rhs.enabled; +} + +bool operator!=(const QCMakePreset& lhs, const QCMakePreset& rhs) +{ + return !(lhs == rhs); +} + +bool operator<(const QCMakePreset& lhs, const QCMakePreset& rhs) +{ + return lhs.name < rhs.name || + (lhs.name == rhs.name && + (lhs.displayName < rhs.displayName || + (lhs.displayName == rhs.displayName && + (lhs.description < rhs.description || + (lhs.description == rhs.description && + (lhs.generator < rhs.generator || + (lhs.generator == rhs.generator && + (lhs.architecture < rhs.architecture || + (lhs.architecture == rhs.architecture && + (lhs.toolset < rhs.toolset || + (lhs.toolset == rhs.toolset && + (lhs.setGenConfig < rhs.setGenConfig || + (lhs.setGenConfig == rhs.setGenConfig && + (lhs.enabled < rhs.enabled)))))))))))))); +} + +bool operator<=(const QCMakePreset& lhs, const QCMakePreset& rhs) +{ + return rhs >= lhs; +} + +bool operator>(const QCMakePreset& lhs, const QCMakePreset& rhs) +{ + return rhs < lhs; +} + +bool operator>=(const QCMakePreset& lhs, const QCMakePreset& rhs) +{ + return !(lhs < rhs); +} diff --git a/Source/QtDialog/QCMakePreset.h b/Source/QtDialog/QCMakePreset.h new file mode 100644 index 0000000..93d70d8 --- /dev/null +++ b/Source/QtDialog/QCMakePreset.h @@ -0,0 +1,30 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include + +#include "cmCMakePresetsFile.h" + +class QCMakePreset +{ +public: + QString name; + QString displayName; + QString description; + QString generator; + QString architecture; + QString toolset; + bool setGenConfig; + bool enabled; +}; + +bool operator==(const QCMakePreset& lhs, const QCMakePreset& rhs); +bool operator!=(const QCMakePreset& lhs, const QCMakePreset& rhs); +bool operator<(const QCMakePreset& lhs, const QCMakePreset& rhs); +bool operator<=(const QCMakePreset& lhs, const QCMakePreset& rhs); +bool operator>(const QCMakePreset& lhs, const QCMakePreset& rhs); +bool operator>=(const QCMakePreset& lhs, const QCMakePreset& rhs); + +Q_DECLARE_METATYPE(QCMakePreset) diff --git a/Source/QtDialog/QCMakePresetComboBox.cxx b/Source/QtDialog/QCMakePresetComboBox.cxx new file mode 100644 index 0000000..efadb73 --- /dev/null +++ b/Source/QtDialog/QCMakePresetComboBox.cxx @@ -0,0 +1,64 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "QCMakePresetComboBox.h" + +#include "QCMakePresetItemModel.h" + +QCMakePresetComboBox::QCMakePresetComboBox(QWidget* parent) + : QComboBox(parent) +{ + this->m_model = new QCMakePresetItemModel(this); + this->setModel(this->m_model); + + QObject::connect(this->m_model, &QCMakePresetItemModel::modelAboutToBeReset, + this, [this]() { this->m_resetting = true; }); + QObject::connect(this->m_model, &QCMakePresetItemModel::modelReset, this, + [this]() { + this->setPresetName(this->m_lastPreset); + this->m_resetting = false; + this->emitPresetChanged(); + }); + QObject::connect( + this, + static_cast(&QComboBox::currentIndexChanged), + this, [this](int /*row*/) { + if (!this->m_resetting) { + this->emitPresetChanged(); + } + }); +} + +const QVector& QCMakePresetComboBox::presets() const +{ + return this->m_model->presets(); +} + +QString QCMakePresetComboBox::presetName() const +{ + auto preset = this->currentData(); + if (preset.canConvert()) { + return preset.value().name; + } + return QString{}; +} + +void QCMakePresetComboBox::setPresets(const QVector& presets) +{ + this->m_model->setPresets(presets); +} + +void QCMakePresetComboBox::setPresetName(const QString& name) +{ + this->setCurrentIndex(this->m_model->presetNameToRow(name)); + if (this->signalsBlocked()) { + this->m_lastPreset = this->presetName(); + } +} + +void QCMakePresetComboBox::emitPresetChanged() +{ + if (this->presetName() != this->m_lastPreset) { + emit this->presetChanged(this->presetName()); + this->m_lastPreset = this->presetName(); + } +} diff --git a/Source/QtDialog/QCMakePresetComboBox.h b/Source/QtDialog/QCMakePresetComboBox.h new file mode 100644 index 0000000..d1eeffe --- /dev/null +++ b/Source/QtDialog/QCMakePresetComboBox.h @@ -0,0 +1,35 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "QCMakePreset.h" +#include +#include +#include +#include + +class QCMakePresetItemModel; + +class QCMakePresetComboBox : public QComboBox +{ + Q_OBJECT +public: + QCMakePresetComboBox(QWidget* parent = nullptr); + + const QVector& presets() const; + QString presetName() const; + +public slots: + void setPresets(const QVector& presets); + void setPresetName(const QString& name); + +signals: + void presetChanged(const QString& name); + +private: + QCMakePresetItemModel* m_model; + bool m_resetting = false; + QString m_lastPreset; + + void emitPresetChanged(); +}; diff --git a/Source/QtDialog/QCMakePresetItemModel.cxx b/Source/QtDialog/QCMakePresetItemModel.cxx new file mode 100644 index 0000000..00a4e18 --- /dev/null +++ b/Source/QtDialog/QCMakePresetItemModel.cxx @@ -0,0 +1,143 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "QCMakePresetItemModel.h" + +#include + +QCMakePresetItemModel::QCMakePresetItemModel(QObject* parent) + : QAbstractItemModel(parent) +{ +} + +QVariant QCMakePresetItemModel::data(const QModelIndex& index, int role) const +{ + switch (role) { + case Qt::AccessibleDescriptionRole: + // Separators have to return "separator" for the + // AccessibleDescriptionRole. This was determined by looking at + // QComboBoxDelegate::isSeparator() (located in qcombobox_p.h.) + if (index.internalId() == SEPARATOR_INDEX) { + return QString::fromLocal8Bit("separator"); + } + return QString{}; + case Qt::DisplayRole: { + if (index.internalId() == CUSTOM_INDEX) { + return QString::fromLocal8Bit(""); + } + if (index.internalId() == SEPARATOR_INDEX) { + return QVariant{}; + } + auto const& preset = this->m_presets[index.internalId()]; + return preset.displayName.isEmpty() ? preset.name : preset.displayName; + } + case Qt::ToolTipRole: + if (index.internalId() == CUSTOM_INDEX) { + return QString::fromLocal8Bit("Specify all settings manually"); + } + if (index.internalId() == SEPARATOR_INDEX) { + return QVariant{}; + } + return this->m_presets[index.internalId()].description; + case Qt::UserRole: + if (index.internalId() == CUSTOM_INDEX) { + return QVariant{}; + } + if (index.internalId() == SEPARATOR_INDEX) { + return QVariant{}; + } + return QVariant::fromValue(this->m_presets[index.internalId()]); + case Qt::FontRole: + if (index.internalId() == CUSTOM_INDEX) { + QFont font; + font.setItalic(true); + return font; + } + return QFont{}; + default: + return QVariant{}; + } +} + +Qt::ItemFlags QCMakePresetItemModel::flags(const QModelIndex& index) const +{ + Qt::ItemFlags flags = + Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; + if (index.internalId() != SEPARATOR_INDEX && + (index.internalId() == CUSTOM_INDEX || + this->m_presets[index.internalId()].enabled)) { + flags |= Qt::ItemIsSelectable | Qt::ItemIsEnabled; + } + return flags; +} + +int QCMakePresetItemModel::rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) { + return 0; + } + if (this->m_presets.empty()) { + return 1; + } + return this->m_presets.size() + 2; +} + +int QCMakePresetItemModel::columnCount(const QModelIndex& parent) const +{ + if (parent.isValid()) { + return 0; + } + return 1; +} + +QModelIndex QCMakePresetItemModel::index(int row, int column, + const QModelIndex& parent) const +{ + if (parent.isValid() || column != 0 || row < 0 || + row >= this->rowCount(QModelIndex{})) { + return QModelIndex{}; + } + + if (this->m_presets.empty() || row == this->m_presets.size() + 1) { + return this->createIndex(row, column, CUSTOM_INDEX); + } + + if (row == this->m_presets.size()) { + return this->createIndex(row, column, SEPARATOR_INDEX); + } + + return this->createIndex(row, column, static_cast(row)); +} + +QModelIndex QCMakePresetItemModel::parent(const QModelIndex& /*index*/) const +{ + return QModelIndex{}; +} + +QVector const& QCMakePresetItemModel::presets() const +{ + return this->m_presets; +} + +void QCMakePresetItemModel::setPresets(QVector const& presets) +{ + this->beginResetModel(); + this->m_presets = presets; + this->endResetModel(); +} + +int QCMakePresetItemModel::presetNameToRow(const QString& name) const +{ + if (this->m_presets.empty()) { + return 0; + } + + int index = 0; + for (auto const& preset : this->m_presets) { + if (preset.name == name) { + return index; + } + index++; + } + + return this->m_presets.size() + 1; +} diff --git a/Source/QtDialog/QCMakePresetItemModel.h b/Source/QtDialog/QCMakePresetItemModel.h new file mode 100644 index 0000000..79fba29 --- /dev/null +++ b/Source/QtDialog/QCMakePresetItemModel.h @@ -0,0 +1,45 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include + +#include "QCMakePreset.h" +#include +#include +#include +#include +#include +#include + +class QObject; + +class QCMakePresetItemModel : public QAbstractItemModel +{ + Q_OBJECT +public: + QCMakePresetItemModel(QObject* parent = nullptr); + + QVariant data(const QModelIndex& index, int role) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + + int rowCount(const QModelIndex& parent = QModelIndex{}) const override; + int columnCount(const QModelIndex& parent = QModelIndex{}) const override; + + QModelIndex index(int row, int column, + const QModelIndex& parent = QModelIndex{}) const override; + QModelIndex parent(const QModelIndex& index) const override; + + QVector const& presets() const; + + int presetNameToRow(const QString& name) const; + +public slots: + void setPresets(QVector const& presets); + +private: + QVector m_presets; + + static constexpr quintptr SEPARATOR_INDEX = static_cast(-2); + static constexpr quintptr CUSTOM_INDEX = static_cast(-1); +}; diff --git a/Tests/CMakeGUI/CMakeGUITest.cmake b/Tests/CMakeGUI/CMakeGUITest.cmake index b60ec35..2c6baf3 100644 --- a/Tests/CMakeGUI/CMakeGUITest.cmake +++ b/Tests/CMakeGUI/CMakeGUITest.cmake @@ -27,6 +27,10 @@ function(run_cmake_gui_test name) if(EXISTS "${_cmakelists_in}") configure_file("${_cmakelists_in}" "${_workdir}/src/CMakeLists.txt" @ONLY) endif() + set(_cmakepresets_in "${_srcdir}/CMakePresets.json.in") + if(EXISTS "${_cmakepresets_in}") + configure_file("${_cmakepresets_in}" "${_workdir}/src/CMakePresets.json" @ONLY) + endif() if(_rcgt_DO_CONFIGURE) if(NOT _rcgt_GENERATOR) set(_rcgt_GENERATOR "${CMakeGUITest_GENERATOR}") @@ -118,3 +122,37 @@ set(ENV{KEPT_VARIABLE} "Kept variable") set(ENV{CHANGED_VARIABLE} "This variable will be changed") set(ENV{REMOVED_VARIABLE} "Removed variable") run_cmake_gui_test(environment) + +run_cmake_gui_test(presetArg:preset + ARGS + -S "${CMakeGUITest_BINARY_DIR}/presetArg-preset/src" + "--preset=ninja" + ) +run_cmake_gui_test(presetArg:presetBinary + ARGS + -S "${CMakeGUITest_BINARY_DIR}/presetArg-presetBinary/src" + -B "${CMakeGUITest_BINARY_DIR}/presetArg-presetBinary/build" + "--preset=ninja" + ) +run_cmake_gui_test(presetArg:presetBinaryChange + ARGS + -S "${CMakeGUITest_BINARY_DIR}/presetArg-presetBinaryChange/src" + -B "${CMakeGUITest_BINARY_DIR}/presetArg-presetBinaryChange/build" + "--preset=ninja" + ) +run_cmake_gui_test(presetArg:noPresetBinaryChange + ARGS + -S "${CMakeGUITest_BINARY_DIR}/presetArg-noPresetBinaryChange/src" + -B "${CMakeGUITest_BINARY_DIR}/presetArg-noPresetBinaryChange/build" + ) +run_cmake_gui_test(presetArg:presetConfigExists + ARGS + -S "${CMakeGUITest_BINARY_DIR}/presetArg-presetConfigExists/src" + "--preset=ninja" + ) +run_cmake_gui_test(presetArg:noExist + ARGS + -S "${CMakeGUITest_BINARY_DIR}/presetArg-noExist/src" + "--preset=noExist" + ) +run_cmake_gui_test(changingPresets) diff --git a/Tests/CMakeGUI/CMakeGUITest.cxx b/Tests/CMakeGUI/CMakeGUITest.cxx index 25a92a5..5a6bec3 100644 --- a/Tests/CMakeGUI/CMakeGUITest.cxx +++ b/Tests/CMakeGUI/CMakeGUITest.cxx @@ -5,6 +5,10 @@ #include "QCMake.h" #include #include +#include +#include +#include +#include #include #include #include @@ -18,6 +22,9 @@ #include "CatchShow.h" #include "FirstConfigure.h" +using WindowSetupHelper = std::function; +Q_DECLARE_METATYPE(WindowSetupHelper) + namespace { void loopSleep(int msecs = 500) { @@ -172,6 +179,264 @@ void CMakeGUITest::environment() QCOMPARE(penv.value("REMOVED_VARIABLE"), "Removed variable"); } +void CMakeGUITest::presetArg() +{ + QFETCH(WindowSetupHelper, setupFunction); + QFETCH(QString, presetName); + QFETCH(QString, sourceDir); + QFETCH(QString, binaryDir); + QFETCH(QCMakePropertyList, properties); + + if (setupFunction) { + setupFunction(this->m_window); + } + + // Wait a bit for everything to update + loopSleep(); + + QCOMPARE(this->m_window->Preset->presetName(), presetName); + QCOMPARE(this->m_window->SourceDirectory->text(), sourceDir); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), binaryDir); + + auto actualProperties = + this->m_window->CacheValues->cacheModel()->properties(); + QCOMPARE(actualProperties.size(), properties.size()); + for (int i = 0; i < actualProperties.size(); ++i) { + // operator==() only compares Key, we need to compare Value and Type too + QCOMPARE(actualProperties[i].Key, properties[i].Key); + QCOMPARE(actualProperties[i].Value, properties[i].Value); + QCOMPARE(actualProperties[i].Type, properties[i].Type); + } +} + +namespace { +QCMakePropertyList makePresetProperties(const QString& name) +{ + return QCMakePropertyList{ + QCMakeProperty{ + /*Key=*/"FALSE_VARIABLE", + /*Value=*/false, + /*Strings=*/{}, + /*Help=*/"", + /*Type=*/QCMakeProperty::BOOL, + /*Advanced=*/false, + }, + QCMakeProperty{ + /*Key=*/"FILEPATH_VARIABLE", + /*Value=*/ + QString::fromLocal8Bit(CMakeGUITest_BINARY_DIR "/%1/src/CMakeLists.txt") + .arg(name), + /*Strings=*/{}, + /*Help=*/"", + /*Type=*/QCMakeProperty::FILEPATH, + /*Advanced=*/false, + }, + QCMakeProperty{ + /*Key=*/"ON_VARIABLE", + /*Value=*/true, + /*Strings=*/{}, + /*Help=*/"", + /*Type=*/QCMakeProperty::BOOL, + /*Advanced=*/false, + }, + QCMakeProperty{ + /*Key=*/"PATH_VARIABLE", + /*Value=*/ + QString::fromLocal8Bit(CMakeGUITest_BINARY_DIR "/%1/src").arg(name), + /*Strings=*/{}, + /*Help=*/"", + /*Type=*/QCMakeProperty::PATH, + /*Advanced=*/false, + }, + QCMakeProperty{ + /*Key=*/"STRING_VARIABLE", + /*Value=*/"String value", + /*Strings=*/{}, + /*Help=*/"", + /*Type=*/QCMakeProperty::STRING, + /*Advanced=*/false, + }, + QCMakeProperty{ + /*Key=*/"UNINITIALIZED_VARIABLE", + /*Value=*/"Uninitialized value", + /*Strings=*/{}, + /*Help=*/"", + /*Type=*/QCMakeProperty::STRING, + /*Advanced=*/false, + }, + }; +} +} + +void CMakeGUITest::presetArg_data() +{ + QTest::addColumn("setupFunction"); + QTest::addColumn("presetName"); + QTest::addColumn("sourceDir"); + QTest::addColumn("binaryDir"); + QTest::addColumn("properties"); + + QTest::newRow("preset") << WindowSetupHelper{} << "ninja" + << CMakeGUITest_BINARY_DIR "/presetArg-preset/src" + << CMakeGUITest_BINARY_DIR + "/presetArg-preset/src/build" + << makePresetProperties("presetArg-preset"); + QTest::newRow("presetBinary") + << WindowSetupHelper{} << "ninja" + << CMakeGUITest_BINARY_DIR "/presetArg-presetBinary/src" + << CMakeGUITest_BINARY_DIR "/presetArg-presetBinary/build" + << makePresetProperties("presetArg-presetBinary"); + QTest::newRow("presetBinaryChange") + << WindowSetupHelper{ [](CMakeSetupDialog* window) { + loopSleep(); + window->Preset->setPresetName("ninja2"); + } } + << "ninja2" << CMakeGUITest_BINARY_DIR "/presetArg-presetBinaryChange/src" + << CMakeGUITest_BINARY_DIR "/presetArg-presetBinaryChange/src/build" + << makePresetProperties("presetArg-presetBinaryChange"); + QTest::newRow("noPresetBinaryChange") + << WindowSetupHelper{ [](CMakeSetupDialog* window) { + loopSleep(); + window->Preset->setPresetName("ninja"); + } } + << "ninja" << CMakeGUITest_BINARY_DIR "/presetArg-noPresetBinaryChange/src" + << CMakeGUITest_BINARY_DIR "/presetArg-noPresetBinaryChange/src/build" + << makePresetProperties("presetArg-noPresetBinaryChange"); + QTest::newRow("presetConfigExists") + << WindowSetupHelper{} << "ninja" + << CMakeGUITest_BINARY_DIR "/presetArg-presetConfigExists/src" + << CMakeGUITest_BINARY_DIR "/presetArg-presetConfigExists/src/build" + << makePresetProperties("presetArg-presetConfigExists"); + QTest::newRow("noExist") << WindowSetupHelper{} << QString{} + << CMakeGUITest_BINARY_DIR "/presetArg-noExist/src" + << "" << QCMakePropertyList{}; +} + +namespace { +void writePresets(const QString& buildDir, const QStringList& names) +{ + QJsonArray presets{ + QJsonObject{ + { "name", "base" }, + { "generator", "Ninja" }, + { "binaryDir", + QString::fromLocal8Bit("${sourceDir}/%1/${presetName}") + .arg(buildDir) }, + { "hidden", true }, + }, + }; + + for (auto const& name : names) { + presets.append(QJsonObject{ + { "name", name }, + { "inherits", QJsonArray{ "base" } }, + }); + } + + QJsonDocument doc{ QJsonObject{ + { "version", 1 }, + { "configurePresets", presets }, + } }; + + QFile presetsFile(CMakeGUITest_BINARY_DIR + "/changingPresets/src/CMakePresets.json"); + bool open = presetsFile.open(QIODevice::WriteOnly); + Q_ASSERT(open); + presetsFile.write(doc.toJson()); +} +} + +void CMakeGUITest::changingPresets() +{ + QDir::root().mkpath(CMakeGUITest_BINARY_DIR "/changingPresets/src"); + + this->m_window->SourceDirectory->setText(CMakeGUITest_BINARY_DIR + "/changingPresets/src"); + loopSleep(); + QCOMPARE(this->m_window->Preset->presetName(), QString{}); + QCOMPARE(this->m_window->Preset->presets().size(), 0); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), ""); + QCOMPARE(this->m_window->Preset->isHidden(), true); + QCOMPARE(this->m_window->PresetLabel->isHidden(), true); + + writePresets("build1", { "preset" }); + loopSleep(1500); + QCOMPARE(this->m_window->Preset->presetName(), QString{}); + QCOMPARE(this->m_window->Preset->presets().size(), 1); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), ""); + QCOMPARE(this->m_window->Preset->isHidden(), false); + QCOMPARE(this->m_window->PresetLabel->isHidden(), false); + + this->m_window->Preset->setPresetName("preset"); + loopSleep(); + QCOMPARE(this->m_window->Preset->presetName(), "preset"); + QCOMPARE(this->m_window->Preset->presets().size(), 1); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), + CMakeGUITest_BINARY_DIR "/changingPresets/src/build1/preset"); + QCOMPARE(this->m_window->Preset->isHidden(), false); + QCOMPARE(this->m_window->PresetLabel->isHidden(), false); + + writePresets("build2", { "preset2", "preset" }); + loopSleep(1500); + QCOMPARE(this->m_window->Preset->presetName(), "preset"); + QCOMPARE(this->m_window->Preset->presets().size(), 2); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), + CMakeGUITest_BINARY_DIR "/changingPresets/src/build1/preset"); + QCOMPARE(this->m_window->Preset->isHidden(), false); + QCOMPARE(this->m_window->PresetLabel->isHidden(), false); + + writePresets("build3", { "preset2" }); + loopSleep(1500); + QCOMPARE(this->m_window->Preset->presetName(), QString{}); + QCOMPARE(this->m_window->Preset->presets().size(), 1); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), + CMakeGUITest_BINARY_DIR "/changingPresets/src/build1/preset"); + QCOMPARE(this->m_window->Preset->isHidden(), false); + QCOMPARE(this->m_window->PresetLabel->isHidden(), false); + + this->m_window->Preset->setPresetName("preset2"); + loopSleep(); + QCOMPARE(this->m_window->Preset->presetName(), "preset2"); + QCOMPARE(this->m_window->Preset->presets().size(), 1); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), + CMakeGUITest_BINARY_DIR "/changingPresets/src/build3/preset2"); + QCOMPARE(this->m_window->Preset->isHidden(), false); + QCOMPARE(this->m_window->PresetLabel->isHidden(), false); + + QDir::root().mkpath(CMakeGUITest_BINARY_DIR "/changingPresets/src2"); + QFile::copy(CMakeGUITest_BINARY_DIR "/changingPresets/src/CMakePresets.json", + CMakeGUITest_BINARY_DIR + "/changingPresets/src2/CMakePresets.json"); + this->m_window->SourceDirectory->setText(CMakeGUITest_BINARY_DIR + "/changingPresets/src2"); + loopSleep(); + QCOMPARE(this->m_window->Preset->presetName(), QString{}); + QCOMPARE(this->m_window->Preset->presets().size(), 1); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), + CMakeGUITest_BINARY_DIR "/changingPresets/src/build3/preset2"); + QCOMPARE(this->m_window->Preset->isHidden(), false); + QCOMPARE(this->m_window->PresetLabel->isHidden(), false); + + this->m_window->Preset->setPresetName("preset2"); + loopSleep(); + QCOMPARE(this->m_window->Preset->presetName(), "preset2"); + QCOMPARE(this->m_window->Preset->presets().size(), 1); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), + CMakeGUITest_BINARY_DIR "/changingPresets/src2/build3/preset2"); + QCOMPARE(this->m_window->Preset->isHidden(), false); + QCOMPARE(this->m_window->PresetLabel->isHidden(), false); + + QFile(CMakeGUITest_BINARY_DIR "/changingPresets/src2/CMakePresets.json") + .remove(); + loopSleep(1500); + QCOMPARE(this->m_window->Preset->presetName(), QString{}); + QCOMPARE(this->m_window->Preset->presets().size(), 0); + QCOMPARE(this->m_window->BinaryDirectory->currentText(), + CMakeGUITest_BINARY_DIR "/changingPresets/src2/build3/preset2"); + QCOMPARE(this->m_window->Preset->isHidden(), true); + QCOMPARE(this->m_window->PresetLabel->isHidden(), true); +} + void SetupDefaultQSettings() { QSettings::setDefaultFormat(QSettings::IniFormat); diff --git a/Tests/CMakeGUI/CMakeGUITest.h b/Tests/CMakeGUI/CMakeGUITest.h index 891cf62..e6293a4 100644 --- a/Tests/CMakeGUI/CMakeGUITest.h +++ b/Tests/CMakeGUI/CMakeGUITest.h @@ -23,4 +23,7 @@ private slots: void simpleConfigure(); void simpleConfigure_data(); void environment(); + void presetArg(); + void presetArg_data(); + void changingPresets(); }; diff --git a/Tests/CMakeGUI/CMakeLists.txt b/Tests/CMakeGUI/CMakeLists.txt index c6bc88a..4e8609b 100644 --- a/Tests/CMakeGUI/CMakeLists.txt +++ b/Tests/CMakeGUI/CMakeLists.txt @@ -72,3 +72,24 @@ add_cmake_gui_lib_test(QCMakeCacheModel MOC_SOURCES QCMakeCacheModelTest.h ) +add_cmake_gui_lib_test(QCMakePreset + SOURCES + QCMakePresetTest.cxx + QCMakePresetTest.h + MOC_SOURCES + QCMakePresetTest.h + ) +add_cmake_gui_lib_test(QCMakePresetItemModel + SOURCES + QCMakePresetItemModelTest.cxx + QCMakePresetItemModelTest.h + MOC_SOURCES + QCMakePresetItemModelTest.h + ) +add_cmake_gui_lib_test(QCMakePresetComboBox + SOURCES + QCMakePresetComboBoxTest.cxx + QCMakePresetComboBoxTest.h + MOC_SOURCES + QCMakePresetComboBoxTest.h + ) diff --git a/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx b/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx new file mode 100644 index 0000000..6ee55c3 --- /dev/null +++ b/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx @@ -0,0 +1,80 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "QCMakePresetComboBoxTest.h" + +#include + +void QCMakePresetComboBoxTest::changePresets() +{ + QCMakePresetComboBox box; + QSignalSpy presetChanged(&box, &QCMakePresetComboBox::presetChanged); + + QCOMPARE(presetChanged.size(), 0); + + box.setPresets({}); + QCOMPARE(presetChanged.size(), 0); + + box.setPresetName(QString{}); + QCOMPARE(presetChanged.size(), 0); + + box.setPresets({ + { + /*name=*/"preset", + /*description=*/"", + /*description=*/"", + /*generator=*/"Ninja", + /*architecture=*/"", + /*toolset=*/"", + /*setGenConfig=*/true, + /*enabled=*/true, + }, + }); + QCOMPARE(presetChanged.size(), 0); + + box.setPresetName(QString{}); + QCOMPARE(presetChanged.size(), 0); + + box.setPresetName("noexist"); + QCOMPARE(presetChanged.size(), 0); + + box.setPresetName("preset"); + QCOMPARE(presetChanged.size(), 1); + QCOMPARE(presetChanged.last(), QList{ "preset" }); + + box.setPresets({ + { + /*name=*/"preset", + /*description=*/"", + /*description=*/"", + /*generator=*/"Ninja Multi-Config", + /*architecture=*/"", + /*toolset=*/"", + /*setGenConfig=*/true, + /*enabled=*/true, + }, + }); + QCOMPARE(presetChanged.size(), 1); + + box.setPresetName("noexist"); + QCOMPARE(presetChanged.size(), 2); + QCOMPARE(presetChanged.last(), QList{ QString{} }); + + box.setPresetName("preset"); + QCOMPARE(presetChanged.size(), 3); + QCOMPARE(presetChanged.last(), QList{ "preset" }); + + box.blockSignals(true); + box.setPresetName(QString{}); + box.blockSignals(false); + QCOMPARE(presetChanged.size(), 3); + + box.setPresetName("preset"); + QCOMPARE(presetChanged.size(), 4); + QCOMPARE(presetChanged.last(), QList{ "preset" }); + + box.setPresets({}); + QCOMPARE(presetChanged.size(), 5); + QCOMPARE(presetChanged.last(), QList{ QString{} }); +} + +QTEST_MAIN(QCMakePresetComboBoxTest) diff --git a/Tests/CMakeGUI/QCMakePresetComboBoxTest.h b/Tests/CMakeGUI/QCMakePresetComboBoxTest.h new file mode 100644 index 0000000..433adbb --- /dev/null +++ b/Tests/CMakeGUI/QCMakePresetComboBoxTest.h @@ -0,0 +1,13 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "QCMakePresetComboBox.h" +#include + +class QCMakePresetComboBoxTest : public QObject +{ + Q_OBJECT +private slots: + void changePresets(); +}; diff --git a/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx b/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx new file mode 100644 index 0000000..ee45d39 --- /dev/null +++ b/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx @@ -0,0 +1,162 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "QCMakePresetItemModelTest.h" + +#include + +#include "QCMakePreset.h" +#include "QCMakePresetItemModel.h" +#include +#include +#include +#include +#include +#include + +using QItemDataHash = QHash; + +void QCMakePresetItemModelTest::initTestCase() +{ + QMetaType::registerComparators(); +} + +void QCMakePresetItemModelTest::initTestCase_data() +{ + QTest::addColumn>("presets"); + QTest::addColumn>("data"); + + QVector presets{ + QCMakePreset{ + /*name=*/"no-description", + /*description=*/"", + /*description=*/"", + /*generator=*/"", + /*architecture=*/"", + /*toolset=*/"", + /*setGenConfig=*/true, + /*enabled=*/true, + }, + QCMakePreset{ + /*name=*/"short-description", + /*description=*/"Short Description", + /*description=*/"", + /*generator=*/"", + /*architecture=*/"", + /*toolset=*/"", + /*setGenConfig=*/true, + /*enabled=*/true, + }, + QCMakePreset{ + /*name=*/"long-description", + /*description=*/"", + /*description=*/"Long Description", + /*generator=*/"", + /*architecture=*/"", + /*toolset=*/"", + /*setGenConfig=*/true, + /*enabled=*/true, + }, + QCMakePreset{ + /*name=*/"disabled", + /*description=*/"", + /*description=*/"", + /*generator=*/"", + /*architecture=*/"", + /*toolset=*/"", + /*setGenConfig=*/true, + /*enabled=*/false, + }, + }; + QVector data{ + QItemDataHash{ + { Qt::AccessibleDescriptionRole, "" }, + { Qt::DisplayRole, "no-description" }, + { Qt::ToolTipRole, "" }, + { Qt::UserRole, QVariant::fromValue(presets[0]) }, + { Qt::FontRole, QFont{} }, + }, + QItemDataHash{ + { Qt::AccessibleDescriptionRole, "" }, + { Qt::DisplayRole, "Short Description" }, + { Qt::ToolTipRole, "" }, + { Qt::UserRole, QVariant::fromValue(presets[1]) }, + { Qt::FontRole, QFont{} }, + }, + QItemDataHash{ + { Qt::AccessibleDescriptionRole, "" }, + { Qt::DisplayRole, "long-description" }, + { Qt::ToolTipRole, "Long Description" }, + { Qt::UserRole, QVariant::fromValue(presets[2]) }, + { Qt::FontRole, QFont{} }, + }, + QItemDataHash{ + { Qt::AccessibleDescriptionRole, "" }, + { Qt::DisplayRole, "disabled" }, + { Qt::ToolTipRole, "" }, + { Qt::UserRole, QVariant::fromValue(presets[3]) }, + { Qt::FontRole, QFont{} }, + }, + QItemDataHash{ + { Qt::AccessibleDescriptionRole, "separator" }, + { Qt::DisplayRole, QVariant{} }, + { Qt::ToolTipRole, QVariant{} }, + { Qt::UserRole, QVariant{} }, + { Qt::FontRole, QFont{} }, + }, + QItemDataHash{ + { Qt::AccessibleDescriptionRole, "" }, + { Qt::DisplayRole, "" }, + { Qt::ToolTipRole, "Specify all settings manually" }, + { Qt::UserRole, QVariant{} }, + { Qt::FontRole, + []() { + QFont f; + f.setItalic(true); + return f; + }() }, + }, + }; + QTest::newRow("many") << presets << data; + QTest::newRow("none") << QVector{} + << QVector{ data.last() }; +} + +void QCMakePresetItemModelTest::data() +{ + QFETCH_GLOBAL(QVector, presets); + QFETCH_GLOBAL(QVector, data); + QFETCH(Qt::ItemDataRole, role); + + QCMakePresetItemModel model; + QSignalSpy spy1(&model, &QCMakePresetItemModel::modelAboutToBeReset); + QSignalSpy spy2(&model, &QCMakePresetItemModel::modelReset); + model.setPresets(presets); + QCOMPARE(spy1.size(), 1); + QCOMPARE(spy2.size(), 1); + + QVector expectedData(data.size()); + for (int i = 0; i < data.size(); ++i) { + expectedData[i] = data[i][role]; + } + + auto rows = model.rowCount(); + QVector actualData(rows); + for (int i = 0; i < rows; ++i) { + actualData[i] = model.data(model.index(i, 0), role); + } + + QCOMPARE(actualData, expectedData); +} + +void QCMakePresetItemModelTest::data_data() +{ + QTest::addColumn("role"); + + QTest::newRow("accessible") << Qt::AccessibleDescriptionRole; + QTest::newRow("display") << Qt::DisplayRole; + QTest::newRow("tooltip") << Qt::ToolTipRole; + QTest::newRow("user") << Qt::UserRole; + QTest::newRow("font") << Qt::FontRole; +} + +QTEST_MAIN(QCMakePresetItemModelTest) diff --git a/Tests/CMakeGUI/QCMakePresetItemModelTest.h b/Tests/CMakeGUI/QCMakePresetItemModelTest.h new file mode 100644 index 0000000..ff6efae --- /dev/null +++ b/Tests/CMakeGUI/QCMakePresetItemModelTest.h @@ -0,0 +1,17 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "QCMakePresetItemModel.h" +#include + +class QCMakePresetItemModelTest : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void initTestCase_data(); + + void data(); + void data_data(); +}; diff --git a/Tests/CMakeGUI/QCMakePresetTest.cxx b/Tests/CMakeGUI/QCMakePresetTest.cxx new file mode 100644 index 0000000..8fd07e7 --- /dev/null +++ b/Tests/CMakeGUI/QCMakePresetTest.cxx @@ -0,0 +1,82 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "QCMakePresetTest.h" + +#include + +#include "QCMakePreset.h" +#include + +namespace { +QCMakePreset makePreset() +{ + return QCMakePreset{ + /*name=*/"name", + /*displayName=*/"displayName", + /*description=*/"description", + /*generator=*/"generator", + /*architecture=*/"architecture", + /*toolset=*/"toolset", + /*setGenConfig=*/true, + /*enabled=*/true, + }; +} + +template +QCMakePreset makePreset(T QCMakePreset::*field, U&& value) +{ + auto preset = makePreset(); + preset.*field = std::forward(value); + return preset; +} +} + +void QCMakePresetTest::equality() +{ + QFETCH(QCMakePreset, rhs); + QFETCH(bool, equal); + QFETCH(bool, lt); + QFETCH(bool, gt); + + auto lhs = makePreset(); + QVERIFY((lhs == rhs) == equal); + QVERIFY((lhs != rhs) == !equal); + QVERIFY((lhs < rhs) == lt); + QVERIFY((lhs >= rhs) == !lt); + QVERIFY((lhs > rhs) == gt); + QVERIFY((lhs <= rhs) == !gt); +} + +void QCMakePresetTest::equality_data() +{ + QTest::addColumn("rhs"); + QTest::addColumn("equal"); + QTest::addColumn("lt"); + QTest::addColumn("gt"); + + QTest::newRow("equal") << makePreset() << true << false << false; + QTest::newRow("name") << makePreset(&QCMakePreset::name, "other-name") + << false << true << false; + QTest::newRow("displayName") + << makePreset(&QCMakePreset::displayName, "other-displayName") << false + << true << false; + QTest::newRow("description") + << makePreset(&QCMakePreset::description, "other-description") << false + << true << false; + QTest::newRow("generator") + << makePreset(&QCMakePreset::generator, "other-generator") << false << true + << false; + QTest::newRow("architecture") + << makePreset(&QCMakePreset::architecture, "other-architecture") << false + << true << false; + QTest::newRow("toolset") << makePreset(&QCMakePreset::toolset, + "other-toolset") + << false << false << true; + QTest::newRow("setGenConfig") + << makePreset(&QCMakePreset::setGenConfig, false) << false << false + << true; + QTest::newRow("enabled") << makePreset(&QCMakePreset::enabled, false) + << false << false << true; +} + +QTEST_MAIN(QCMakePresetTest) diff --git a/Tests/CMakeGUI/QCMakePresetTest.h b/Tests/CMakeGUI/QCMakePresetTest.h new file mode 100644 index 0000000..5eac88d --- /dev/null +++ b/Tests/CMakeGUI/QCMakePresetTest.h @@ -0,0 +1,14 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "QCMakePreset.h" +#include + +class QCMakePresetTest : public QObject +{ + Q_OBJECT +private slots: + void equality(); + void equality_data(); +}; diff --git a/Tests/CMakeGUI/presetArg-noPresetBinaryChange/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-noPresetBinaryChange/CMakePresets.json.in new file mode 100644 index 0000000..d78d69d --- /dev/null +++ b/Tests/CMakeGUI/presetArg-noPresetBinaryChange/CMakePresets.json.in @@ -0,0 +1,33 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "ninja", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "STRING_VARIABLE": { + "type": "STRING", + "value": "String value" + }, + "PATH_VARIABLE": { + "type": "PATH", + "value": "${sourceDir}" + }, + "FILEPATH_VARIABLE": { + "type": "FILEPATH", + "value": "${sourceDir}/CMakeLists.txt" + }, + "ON_VARIABLE": { + "type": "BOOL", + "value": "ON" + }, + "FALSE_VARIABLE": { + "type": "BOOL", + "value": "FALSE" + }, + "UNINITIALIZED_VARIABLE": "Uninitialized value" + } + } + ] +} diff --git a/Tests/CMakeGUI/presetArg-preset/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-preset/CMakePresets.json.in new file mode 100644 index 0000000..d78d69d --- /dev/null +++ b/Tests/CMakeGUI/presetArg-preset/CMakePresets.json.in @@ -0,0 +1,33 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "ninja", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "STRING_VARIABLE": { + "type": "STRING", + "value": "String value" + }, + "PATH_VARIABLE": { + "type": "PATH", + "value": "${sourceDir}" + }, + "FILEPATH_VARIABLE": { + "type": "FILEPATH", + "value": "${sourceDir}/CMakeLists.txt" + }, + "ON_VARIABLE": { + "type": "BOOL", + "value": "ON" + }, + "FALSE_VARIABLE": { + "type": "BOOL", + "value": "FALSE" + }, + "UNINITIALIZED_VARIABLE": "Uninitialized value" + } + } + ] +} diff --git a/Tests/CMakeGUI/presetArg-presetBinary/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-presetBinary/CMakePresets.json.in new file mode 100644 index 0000000..d78d69d --- /dev/null +++ b/Tests/CMakeGUI/presetArg-presetBinary/CMakePresets.json.in @@ -0,0 +1,33 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "ninja", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "STRING_VARIABLE": { + "type": "STRING", + "value": "String value" + }, + "PATH_VARIABLE": { + "type": "PATH", + "value": "${sourceDir}" + }, + "FILEPATH_VARIABLE": { + "type": "FILEPATH", + "value": "${sourceDir}/CMakeLists.txt" + }, + "ON_VARIABLE": { + "type": "BOOL", + "value": "ON" + }, + "FALSE_VARIABLE": { + "type": "BOOL", + "value": "FALSE" + }, + "UNINITIALIZED_VARIABLE": "Uninitialized value" + } + } + ] +} diff --git a/Tests/CMakeGUI/presetArg-presetBinaryChange/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-presetBinaryChange/CMakePresets.json.in new file mode 100644 index 0000000..6fe20d6 --- /dev/null +++ b/Tests/CMakeGUI/presetArg-presetBinaryChange/CMakePresets.json.in @@ -0,0 +1,39 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "ninja", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "STRING_VARIABLE": { + "type": "STRING", + "value": "String value" + }, + "PATH_VARIABLE": { + "type": "PATH", + "value": "${sourceDir}" + }, + "FILEPATH_VARIABLE": { + "type": "FILEPATH", + "value": "${sourceDir}/CMakeLists.txt" + }, + "ON_VARIABLE": { + "type": "BOOL", + "value": "ON" + }, + "FALSE_VARIABLE": { + "type": "BOOL", + "value": "FALSE" + }, + "UNINITIALIZED_VARIABLE": "Uninitialized value" + } + }, + { + "name": "ninja2", + "inherits": [ + "ninja" + ] + } + ] +} diff --git a/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeLists.txt.in b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeLists.txt.in new file mode 100644 index 0000000..2ae4a57 --- /dev/null +++ b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeLists.txt.in @@ -0,0 +1,2 @@ +cmake_minimum_required(VERSION 3.18) +project(sourceBinaryArgs-sourceDir NONE) diff --git a/Tests/CMakeGUI/presetArg-presetConfigExists/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakePresets.json.in new file mode 100644 index 0000000..d78d69d --- /dev/null +++ b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakePresets.json.in @@ -0,0 +1,33 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "ninja", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "STRING_VARIABLE": { + "type": "STRING", + "value": "String value" + }, + "PATH_VARIABLE": { + "type": "PATH", + "value": "${sourceDir}" + }, + "FILEPATH_VARIABLE": { + "type": "FILEPATH", + "value": "${sourceDir}/CMakeLists.txt" + }, + "ON_VARIABLE": { + "type": "BOOL", + "value": "ON" + }, + "FALSE_VARIABLE": { + "type": "BOOL", + "value": "FALSE" + }, + "UNINITIALIZED_VARIABLE": "Uninitialized value" + } + } + ] +} diff --git a/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeSetup.ini.in b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeSetup.ini.in new file mode 100644 index 0000000..a5d0c71 --- /dev/null +++ b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeSetup.ini.in @@ -0,0 +1,2 @@ +[Settings] +StartPath\WhereBuild0=@CMake_BINARY_DIR@ -- cgit v0.12