From 15237af23c6637514ebc378bba4fcef7bde6bca5 Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Mon, 6 Dec 2021 09:22:03 -0800 Subject: [PATCH 01/12] Refactored ProjectManagerSettings, added tests, changed project built successful to be tracked by project path, added project ids, changed project settings path to use project id and name Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- AutomatedTesting/project.json | 6 +- Code/Tools/ProjectManager/CMakeLists.txt | 3 + .../Source/ExternalLinkDialog.cpp | 10 +- .../Source/GemCatalog/GemInfo.h | 1 - .../ProjectManager/Source/LinkWidget.cpp | 8 +- .../Source/NewProjectSettingsScreen.cpp | 14 +- .../Source/NewProjectSettingsScreen.h | 1 + .../Source/ProjectBuilderController.cpp | 26 +- .../ProjectManager/Source/ProjectInfo.cpp | 10 +- .../Tools/ProjectManager/Source/ProjectInfo.h | 3 +- .../Source/ProjectManagerSettings.cpp | 251 +++++++++++++++--- .../Source/ProjectManagerSettings.h | 27 +- .../Source/ProjectSettingsScreen.cpp | 27 +- .../Source/ProjectSettingsScreen.h | 3 + .../ProjectManager/Source/ProjectsScreen.cpp | 8 +- .../ProjectManager/Source/PythonBindings.cpp | 22 +- .../Source/UpdateProjectCtrl.cpp | 16 +- .../Source/UpdateProjectSettingsScreen.cpp | 4 +- .../project_manager_tests_files.cmake | 3 +- .../tests/ProjectManagerSettingsTests.cpp | 176 ++++++++++++ .../DefaultProject/Template/project.json | 1 + .../MinimalProject/Template/project.json | 1 + q | 48 ++++ scripts/o3de/o3de/engine_template.py | 22 +- scripts/o3de/o3de/project_properties.py | 13 +- scripts/o3de/o3de/register.py | 2 +- scripts/o3de/o3de/validation.py | 17 +- .../tests/unit_test_project_properties.py | 25 +- 28 files changed, 619 insertions(+), 129 deletions(-) create mode 100644 Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp create mode 100644 q diff --git a/AutomatedTesting/project.json b/AutomatedTesting/project.json index 5ee4ee68f8..9222777ef3 100644 --- a/AutomatedTesting/project.json +++ b/AutomatedTesting/project.json @@ -10,5 +10,7 @@ "version_name": "1.0.0.0", "orientation": "landscape" }, - "engine": "o3de" -} \ No newline at end of file + "engine": "o3de", + "display_name": "AutomatedTesting", + "icon_path": "preview.png" +} diff --git a/Code/Tools/ProjectManager/CMakeLists.txt b/Code/Tools/ProjectManager/CMakeLists.txt index 9974125ffb..b0e7ee9697 100644 --- a/Code/Tools/ProjectManager/CMakeLists.txt +++ b/Code/Tools/ProjectManager/CMakeLists.txt @@ -89,6 +89,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) 3rdParty::Qt::Widgets 3rdParty::Python 3rdParty::pybind11 + AZ::AzCore + AZ::AzCoreTestCommon + AZ::AzTestShared AZ::AzTest AZ::AzFramework AZ::AzFrameworkTestShared diff --git a/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp b/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp index 122a5cbf5a..2f3d615863 100644 --- a/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp +++ b/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp @@ -10,8 +10,6 @@ #include #include -#include - #include #include #include @@ -87,12 +85,6 @@ namespace O3DE::ProjectManager void ExternalLinkDialog::SetSkipDialogSetting(bool state) { - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - QString settingsKey = GetExternalLinkWarningKey(); - settingsRegistry->Set(settingsKey.toStdString().c_str(), state); - SaveProjectManagerSettings(); - } + PMSettings::SetProjectManagerKey(PMSettings::GetExternalLinkWarningKey(), state); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h index 23e95cf487..264971428a 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h @@ -9,7 +9,6 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include #include #include diff --git a/Code/Tools/ProjectManager/Source/LinkWidget.cpp b/Code/Tools/ProjectManager/Source/LinkWidget.cpp index f25e38db67..87ccdb9aed 100644 --- a/Code/Tools/ProjectManager/Source/LinkWidget.cpp +++ b/Code/Tools/ProjectManager/Source/LinkWidget.cpp @@ -33,13 +33,7 @@ namespace O3DE::ProjectManager { // Check if user request not to be shown external link warning dialog bool skipDialog = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - - if (settingsRegistry) - { - QString settingsKey = GetExternalLinkWarningKey(); - settingsRegistry->Get(skipDialog, settingsKey.toStdString().c_str()); - } + PMSettings::GetProjectManagerKey(skipDialog, PMSettings::GetExternalLinkWarningKey()); if (!skipDialog) { diff --git a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp index 4febb65782..4c306fc715 100644 --- a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp @@ -16,6 +16,8 @@ #include #include #include + +#include #include #include @@ -41,9 +43,11 @@ namespace O3DE::ProjectManager { const QString defaultName = GetDefaultProjectName(); const QString defaultPath = QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + defaultName); + const QString randomUuid = GenerateNewProjectId(); m_projectName->lineEdit()->setText(defaultName); m_projectPath->lineEdit()->setText(defaultPath); + m_projectId->lineEdit()->setText(randomUuid); // if we don't use a QFrame we cannot "contain" the widgets inside and move them around // as a group @@ -173,6 +177,14 @@ namespace O3DE::ProjectManager return QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + projectName); } + QString NewProjectSettingsScreen::GenerateNewProjectId() + { + AZStd::string uuid; + AZ::Uuid::CreateRandom().ToString(uuid); + + return QString(uuid.c_str()); + } + ProjectManagerScreen NewProjectSettingsScreen::GetScreenEnum() { return ProjectManagerScreen::NewProjectSettings; @@ -225,7 +237,7 @@ namespace O3DE::ProjectManager moreGemsLabel->setObjectName("moreGems"); templateDetailsLayout->addWidget(moreGemsLabel); - QLabel* browseCatalogLabel = new QLabel(tr("Browse the Gems Catalog to further customize your project."), this); + QLabel* browseCatalogLabel = new QLabel(tr("Browse the Gems Catalog to further customize your project."), this); browseCatalogLabel->setObjectName("browseCatalog"); browseCatalogLabel->setWordWrap(true); templateDetailsLayout->addWidget(browseCatalogLabel); diff --git a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h index 42c47cb1ff..cfb215ba0c 100644 --- a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h @@ -47,6 +47,7 @@ namespace O3DE::ProjectManager private: QString GetDefaultProjectName(); QString GetDefaultProjectPath(); + QString GenerateNewProjectId(); QString GetProjectAutoPath(); QFrame* CreateTemplateDetails(int margin); void UpdateTemplateDetails(const ProjectTemplateInfo& templateInfo); diff --git a/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp b/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp index ecb125ae4e..4fc188b289 100644 --- a/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp @@ -29,14 +29,8 @@ namespace O3DE::ProjectManager m_worker = new ProjectBuilderWorker(m_projectInfo); m_worker->moveToThread(&m_workerThread); - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - // Remove key here in case Project Manager crashing while building that causes HandleResults to not be called - QString settingsKey = GetProjectBuiltSuccessfullyKey(m_projectInfo.m_projectName); - settingsRegistry->Remove(settingsKey.toStdString().c_str()); - SaveProjectManagerSettings(); - } + // Remove key here in case Project Manager crashing while building that causes HandleResults to not be called + PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, false); connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater); connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject); @@ -91,8 +85,6 @@ namespace O3DE::ProjectManager void ProjectBuilderController::HandleResults(const QString& result) { - QString settingsKey = GetProjectBuiltSuccessfullyKey(m_projectInfo.m_projectName); - if (!result.isEmpty()) { if (result.contains(tr("log"))) @@ -122,12 +114,7 @@ namespace O3DE::ProjectManager emit NotifyBuildProject(m_projectInfo); } - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - settingsRegistry->Remove(settingsKey.toStdString().c_str()); - SaveProjectManagerSettings(); - } + PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, false); emit Done(false); return; @@ -136,12 +123,7 @@ namespace O3DE::ProjectManager { m_projectInfo.m_buildFailed = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - settingsRegistry->Set(settingsKey.toStdString().c_str(), true); - SaveProjectManagerSettings(); - } + PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, true); } emit Done(true); diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp index b4a1e84831..0d19fff74a 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp @@ -9,14 +9,13 @@ #include #include -#include - namespace O3DE::ProjectManager { ProjectInfo::ProjectInfo( const QString& path, const QString& projectName, const QString& displayName, + const QString& id, const QString& origin, const QString& summary, const QString& iconPath, @@ -26,6 +25,7 @@ namespace O3DE::ProjectManager : m_path(path) , m_projectName(projectName) , m_displayName(displayName) + , m_id(id) , m_origin(origin) , m_summary(summary) , m_iconPath(iconPath) @@ -49,6 +49,10 @@ namespace O3DE::ProjectManager { return false; } + if (m_id != rhs.m_id) + { + return false; + } if (m_origin != rhs.m_origin) { return false; @@ -80,7 +84,7 @@ namespace O3DE::ProjectManager bool ProjectInfo::IsValid() const { - return !m_path.isEmpty() && !m_projectName.isEmpty(); + return !m_path.isEmpty() && !m_projectName.isEmpty() && !m_id.isEmpty(); } const QString& ProjectInfo::GetProjectDisplayName() const diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.h b/Code/Tools/ProjectManager/Source/ProjectInfo.h index 2ce1e8c491..4dcb21aa24 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.h +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.h @@ -9,7 +9,6 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include #include #include @@ -26,6 +25,7 @@ namespace O3DE::ProjectManager const QString& path, const QString& projectName, const QString& displayName, + const QString& id, const QString& origin, const QString& summary, const QString& iconPath, @@ -45,6 +45,7 @@ namespace O3DE::ProjectManager // From project.json QString m_projectName; QString m_displayName; + QString m_id; QString m_origin; QString m_summary; QString m_iconPath; diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerSettings.cpp b/Code/Tools/ProjectManager/Source/ProjectManagerSettings.cpp index 66480aab3e..12dd569ad5 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerSettings.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectManagerSettings.cpp @@ -14,46 +14,235 @@ namespace O3DE::ProjectManager { - void SaveProjectManagerSettings() + namespace PMSettings { - auto settingsRegistry = AZ::SettingsRegistry::Get(); - AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; - dumperSettings.m_prettifyOutput = true; - dumperSettings.m_jsonPointerPrefix = ProjectManagerKeyPrefix; + bool SaveProjectManagerSettings() + { + auto settingsRegistry = AZ::SettingsRegistry::Get(); + AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; + dumperSettings.m_prettifyOutput = true; + dumperSettings.m_jsonPointerPrefix = ProjectManagerKeyPrefix; + + AZStd::string stringBuffer; + AZ::IO::ByteContainerStream stringStream(&stringBuffer); + if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream( + *settingsRegistry, ProjectManagerKeyPrefix, stringStream, dumperSettings)) + { + AZ_Warning("ProjectManager", false, "Could not save Project Manager settings to stream"); + return false; + } + + AZ::IO::FixedMaxPath o3deUserPath = AZ::Utils::GetO3deManifestDirectory(); + o3deUserPath /= AZ::SettingsRegistryInterface::RegistryFolder; + o3deUserPath /= "ProjectManager.setreg"; + + bool saved = false; + constexpr auto configurationMode = + AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY; + + AZ::IO::SystemFile outputFile; + if (outputFile.Open(o3deUserPath.c_str(), configurationMode)) + { + saved = outputFile.Write(stringBuffer.data(), stringBuffer.size()) == stringBuffer.size(); + } + + AZ_Warning("ProjectManager", saved, "Unable to save Project Manager registry file to path: %s", o3deUserPath.c_str()); + return saved; + } - AZStd::string stringBuffer; - AZ::IO::ByteContainerStream stringStream(&stringBuffer); - if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream( - *settingsRegistry, ProjectManagerKeyPrefix, stringStream, dumperSettings)) + bool GetProjectManagerKey(QString& result, const QString& settingsKey) { - AZ_Warning("ProjectManager", false, "Could not save Project Manager settings to stream"); - return; + bool success = false; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + AZStd::string settingsValue; + success = settingsRegistry->Get(settingsValue, settingsKey.toStdString().c_str()); + + result = settingsValue.c_str(); + } + + return success; } - AZ::IO::FixedMaxPath o3deUserPath = AZ::Utils::GetO3deManifestDirectory(); - o3deUserPath /= AZ::SettingsRegistryInterface::RegistryFolder; - o3deUserPath /= "ProjectManager.setreg"; + bool GetProjectManagerKey(bool& result, const QString& settingsKey) + { + bool success = false; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + success = settingsRegistry->Get(result, settingsKey.toStdString().c_str()); + } - bool saved = false; - constexpr auto configurationMode = - AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY; + return success; + } - AZ::IO::SystemFile outputFile; - if (outputFile.Open(o3deUserPath.c_str(), configurationMode)) + bool SetProjectManagerKey(const QString& settingsKey, const QString& settingsValue, bool saveToDisk) { - saved = outputFile.Write(stringBuffer.data(), stringBuffer.size()) == stringBuffer.size(); + bool success = false; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + success = settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue.toStdString().c_str()); + + if (saveToDisk) + { + SaveProjectManagerSettings(); + } + } + + return success; } - AZ_Warning("ProjectManager", saved, "Unable to save Project Manager registry file to path: %s", o3deUserPath.c_str()); - } + bool SetProjectManagerKey(const QString& settingsKey, bool settingsValue, bool saveToDisk) + { + bool success = false; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + success = settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue); - QString GetProjectBuiltSuccessfullyKey(const QString& projectName) - { - return QString("%1/Projects/%2/BuiltSuccessfully").arg(ProjectManagerKeyPrefix).arg(projectName); - } + if (saveToDisk) + { + SaveProjectManagerSettings(); + } + } - QString GetExternalLinkWarningKey() - { - return QString("%1/SkipExternalLinkWarning").arg(ProjectManagerKeyPrefix); - } -} + return success; + } + + bool RemoveProjectManagerKey(const QString& settingsKey, bool saveToDisk) + { + bool success = false; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + success = settingsRegistry->Remove(settingsKey.toStdString().c_str()); + + if (saveToDisk) + { + SaveProjectManagerSettings(); + } + } + + return success; + } + + bool CopyProjectManagerKeyString(const QString& settingsKeyOrig, const QString& settingsKeyDest, bool removeOrig, bool saveToDisk) + { + bool success = false; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + AZStd::string settingsValue; + success = settingsRegistry->Get(settingsValue, settingsKeyOrig.toStdString().c_str()); + + if (success) + { + success = settingsRegistry->Set(settingsKeyDest.toStdString().c_str(), settingsValue); + if (success) + { + if (removeOrig) + { + success = settingsRegistry->Remove(settingsKeyOrig.toStdString().c_str()); + } + + if (saveToDisk) + { + SaveProjectManagerSettings(); + } + } + } + } + + return success; + } + + QString GetProjectKey(const ProjectInfo& projectInfo) + { + return QString("%1/Projects/%2/%3").arg(ProjectManagerKeyPrefix, projectInfo.m_id, projectInfo.m_projectName); + } + + QString GetExternalLinkWarningKey() + { + return QString("%1/SkipExternalLinkWarning").arg(ProjectManagerKeyPrefix); + } + + QString GetProjectsBuiltSuccessfullyKey() + { + return QString("%1/SuccessfulBuildPaths").arg(ProjectManagerKeyPrefix); + } + + bool GetBuiltSuccessfullyPaths(AZStd::set& result) + { + bool success = false; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + QString builtKey = GetProjectsBuiltSuccessfullyKey(); + success = settingsRegistry->GetObject>(result, builtKey.toStdString().c_str()); + } + + return success; + } + + bool GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo) + { + AZStd::set builtPathsResult; + bool success = GetBuiltSuccessfullyPaths(builtPathsResult); + if (success) + { + // Check if buildPath is listed as successfully built + AZStd::string projectPath = projectInfo.m_path.toStdString().c_str(); + if (builtPathsResult.contains(projectPath)) + { + result = true; + } + } + // No project built statuses known + else + { + result = false; + } + + return success; + } + + bool SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt, bool saveToDisk) + { + AZStd::set builtPathsResult; + bool success = GetBuiltSuccessfullyPaths(builtPathsResult); + + AZStd::string projectPath = projectInfo.m_path.toStdString().c_str(); + if (successfullyBuilt) + { + //Add successfully built path to set + builtPathsResult.insert(projectPath); + } + else + { + // Remove unsuccessfully built path from set + builtPathsResult.erase(projectPath); + } + + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + QString builtKey = GetProjectsBuiltSuccessfullyKey(); + success = settingsRegistry->SetObject>(builtKey.toStdString().c_str(), builtPathsResult); + + if (saveToDisk) + { + SaveProjectManagerSettings(); + } + } + else + { + success = false; + } + + return success; + } + + } // namespace PMSettings +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerSettings.h b/Code/Tools/ProjectManager/Source/ProjectManagerSettings.h index 93cfbc5ceb..2a92fcab0f 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerSettings.h +++ b/Code/Tools/ProjectManager/Source/ProjectManagerSettings.h @@ -9,14 +9,29 @@ #pragma once #if !defined(Q_MOC_RUN) -#include +#include +#include #endif namespace O3DE::ProjectManager { - static constexpr char ProjectManagerKeyPrefix[] = "/O3DE/ProjectManager"; + namespace PMSettings + { + static constexpr char ProjectManagerKeyPrefix[] = "/O3DE/ProjectManager"; - void SaveProjectManagerSettings(); - QString GetProjectBuiltSuccessfullyKey(const QString& projectName); - QString GetExternalLinkWarningKey(); -} + bool SaveProjectManagerSettings(); + bool GetProjectManagerKey(QString& result, const QString& settingsKey); + bool GetProjectManagerKey(bool& result, const QString& settingsKey); + bool SetProjectManagerKey(const QString& settingsKey, const QString& settingsValue, bool saveToDisk = true); + bool SetProjectManagerKey(const QString& settingsKey, bool settingsValue, bool saveToDisk = true); + bool RemoveProjectManagerKey(const QString& settingsKey, bool saveToDisk = true); + bool CopyProjectManagerKeyString( + const QString& settingsKeyOrig, const QString& settingsKeyDest, bool removeOrig = false, bool saveToDisk = true); + + QString GetProjectKey(const ProjectInfo& projectInfo); + QString GetExternalLinkWarningKey(); + + bool GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo); + bool SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt, bool saveToDisk = true); + } // namespace PMSettings +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp index d4ac43d655..cf15cb5bbc 100644 --- a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp @@ -60,6 +60,10 @@ namespace O3DE::ProjectManager connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectPathUpdated); m_verticalLayout->addWidget(m_projectPath); + m_projectId = new FormLineEditWidget(tr("Project ID"), "", this); + connect(m_projectId->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectIdUpdated); + m_verticalLayout->addWidget(m_projectId); + projectSettingsFrame->setLayout(m_verticalLayout); m_horizontalLayout->addWidget(projectSettingsFrame); @@ -94,6 +98,7 @@ namespace O3DE::ProjectManager // currently we don't have separate fields for changing the project name and display name projectInfo.m_displayName = projectInfo.m_projectName; projectInfo.m_path = m_projectPath->lineEdit()->text(); + projectInfo.m_id = m_projectId->lineEdit()->text(); return projectInfo; } @@ -142,6 +147,19 @@ namespace O3DE::ProjectManager return projectPathIsValid; } + bool ProjectSettingsScreen::ValidateProjectId() + { + bool projectIdIsValid = true; + if (m_projectId->lineEdit()->text().isEmpty()) + { + projectIdIsValid = false; + m_projectId->setErrorLabelText(tr("Project ID cannot be empty.")); + } + + m_projectId->setErrorLabelVisible(!projectIdIsValid); + return projectIdIsValid; + } + void ProjectSettingsScreen::OnProjectNameUpdated() { ValidateProjectName(); @@ -149,11 +167,16 @@ namespace O3DE::ProjectManager void ProjectSettingsScreen::OnProjectPathUpdated() { - Validate(); + ValidateProjectName() && ValidateProjectPath(); + } + + void ProjectSettingsScreen::OnProjectIdUpdated() + { + ValidateProjectId(); } bool ProjectSettingsScreen::Validate() { - return ValidateProjectName() && ValidateProjectPath(); + return ValidateProjectName() && ValidateProjectPath() && ValidateProjectId(); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h index 752e286ce1..928cde833e 100644 --- a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h @@ -35,10 +35,12 @@ namespace O3DE::ProjectManager protected slots: virtual void OnProjectNameUpdated(); virtual void OnProjectPathUpdated(); + virtual void OnProjectIdUpdated(); protected: bool ValidateProjectName(); virtual bool ValidateProjectPath(); + bool ValidateProjectId(); QString GetDefaultProjectPath(); @@ -46,6 +48,7 @@ namespace O3DE::ProjectManager QVBoxLayout* m_verticalLayout; FormLineEditWidget* m_projectName; FormBrowseEditWidget* m_projectPath; + FormLineEditWidget* m_projectId; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp index acd753a1cb..9816595548 100644 --- a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp @@ -291,13 +291,9 @@ namespace O3DE::ProjectManager // Check whether project manager has successfully built the project if (currentButton) { - auto settingsRegistry = AZ::SettingsRegistry::Get(); bool projectBuiltSuccessfully = false; - if (settingsRegistry) - { - QString settingsKey = GetProjectBuiltSuccessfullyKey(project.m_projectName); - settingsRegistry->Get(projectBuiltSuccessfully, settingsKey.toStdString().c_str()); - } + PMSettings::GetProjectBuiltSuccessfully(projectBuiltSuccessfully, project); + if (!projectBuiltSuccessfully) { currentButton->ShowBuildRequired(); diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 12f97e6d2e..8d11028af6 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -687,8 +687,24 @@ namespace O3DE::ProjectManager auto createProjectResult = m_engineTemplate.attr("create_project")( projectPath, - QString_To_Py_String(projectInfo.m_projectName), - QString_To_Py_Path(projectTemplatePath) + QString_To_Py_String(projectInfo.m_projectName), // project_path + QString_To_Py_Path(projectTemplatePath), // template_path + pybind11::none(), // template_name + pybind11::none(), // project_restricted_path + pybind11::none(), // project_restricted_name + pybind11::none(), // template_restricted_path + pybind11::none(), // template_restricted_name + pybind11::none(), // project_restricted_platform_relative_path + pybind11::none(), // template_restricted_platform_relative_path + pybind11::none(), // keep_restricted_in_project + pybind11::none(), // keep_license_text + pybind11::none(), // replace + pybind11::none(), // force + pybind11::none(), // no_register + pybind11::none(), // system_component_class_id + pybind11::none(), // editor_system_component_class_id + pybind11::none(), // module_id + QString_To_Py_String(projectInfo.m_id) // project_id ); if (createProjectResult.cast() == 0) { @@ -822,6 +838,7 @@ namespace O3DE::ProjectManager { projectInfo.m_projectName = Py_To_String(projectData["project_name"]); projectInfo.m_displayName = Py_To_String_Optional(projectData, "display_name", projectInfo.m_projectName); + projectInfo.m_id = Py_To_String_Optional(projectData, "project_id", projectInfo.m_id); projectInfo.m_origin = Py_To_String_Optional(projectData, "origin", projectInfo.m_origin); projectInfo.m_summary = Py_To_String_Optional(projectData, "summary", projectInfo.m_summary); projectInfo.m_iconPath = Py_To_String_Optional(projectData, "icon", ProjectPreviewImagePath); @@ -926,6 +943,7 @@ namespace O3DE::ProjectManager QString_To_Py_Path(projectInfo.m_path), pybind11::none(), // proj_name not used QString_To_Py_String(projectInfo.m_projectName), + QString_To_Py_String(projectInfo.m_id), QString_To_Py_String(projectInfo.m_origin), QString_To_Py_String(projectInfo.m_displayName), QString_To_Py_String(projectInfo.m_summary), diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 36d78ed2ac..71dae91a81 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -306,17 +305,10 @@ namespace O3DE::ProjectManager if (newProjectSettings.m_projectName != m_projectInfo.m_projectName) { - // update reg key - QString oldSettingsKey = GetProjectBuiltSuccessfullyKey(m_projectInfo.m_projectName); - QString newSettingsKey = GetProjectBuiltSuccessfullyKey(newProjectSettings.m_projectName); - - auto settingsRegistry = AZ::SettingsRegistry::Get(); - bool projectBuiltSuccessfully = false; - if (settingsRegistry && settingsRegistry->Get(projectBuiltSuccessfully, oldSettingsKey.toStdString().c_str())) - { - settingsRegistry->Set(newSettingsKey.toStdString().c_str(), projectBuiltSuccessfully); - SaveProjectManagerSettings(); - } + // Remove project build successfully paths for both old and new project names + // because a full rebuild is required when moving projects + PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, false); + PMSettings::SetProjectBuiltSuccessfully(newProjectSettings, false); } if (!newProjectSettings.m_newPreviewImagePath.isEmpty()) diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp index a430102c27..7c8f981f59 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp @@ -56,6 +56,7 @@ namespace O3DE::ProjectManager { m_projectInfo.m_displayName = m_projectName->lineEdit()->text(); m_projectInfo.m_path = m_projectPath->lineEdit()->text(); + m_projectInfo.m_id = m_projectId->lineEdit()->text(); if (m_userChangedPreview) { @@ -70,8 +71,9 @@ namespace O3DE::ProjectManager m_projectInfo = projectInfo; m_projectName->lineEdit()->setText(projectInfo.GetProjectDisplayName()); - m_projectPath->lineEdit()->setText(projectInfo.m_path); + m_projectId->lineEdit()->setText(projectInfo.m_id); + UpdateProjectPreviewPath(); } diff --git a/Code/Tools/ProjectManager/project_manager_tests_files.cmake b/Code/Tools/ProjectManager/project_manager_tests_files.cmake index 2bfe343038..df9a0070a1 100644 --- a/Code/Tools/ProjectManager/project_manager_tests_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_tests_files.cmake @@ -10,8 +10,9 @@ set(FILES Resources/ProjectManager.qrc Resources/ProjectManager.qss tests/ApplicationTests.cpp - tests/PythonBindingsTests.cpp tests/GemCatalogTests.cpp + tests/ProjectManagerSettingsTests.cpp + tests/PythonBindingsTests.cpp tests/main.cpp tests/UtilsTests.cpp ) diff --git a/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp b/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp new file mode 100644 index 0000000000..7ab93f798c --- /dev/null +++ b/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include + +#include + +namespace O3DE::ProjectManager +{ + class ProjectManagerSettingsTests + : public ::UnitTest::ScopedAllocatorSetupFixture + { + public: + ~ProjectManagerSettingsTests() override = default; + void SetUp() override + { + UnitTest::ScopedAllocatorSetupFixture::SetUp(); + + m_registry = AZStd::make_unique(); + // Store off the old global settings registry to restore after each test + m_oldSettingsRegistry = AZ::SettingsRegistry::Get(); + if (m_oldSettingsRegistry != nullptr) + { + AZ::SettingsRegistry::Unregister(m_oldSettingsRegistry); + } + AZ::SettingsRegistry::Register(m_registry.get()); + + m_serializeContext = AZStd::make_unique(); + m_registrationContext = AZStd::make_unique(); + + m_registry->SetContext(m_serializeContext.get()); + m_registry->SetContext(m_registrationContext.get()); + + m_projectInfo.m_path = "Z:/ProjectTestPath"; + } + + void TearDown() override + { + m_registrationContext.reset(); + m_serializeContext.reset(); + + // Restore the old global settings registry + AZ::SettingsRegistry::Unregister(m_registry.get()); + if (m_oldSettingsRegistry != nullptr) + { + AZ::SettingsRegistry::Register(m_oldSettingsRegistry); + m_oldSettingsRegistry = nullptr; + } + m_registry.reset(); + + UnitTest::ScopedAllocatorSetupFixture::TearDown(); + } + + protected: + const QString m_settingsPath = "/Testing/TestKey"; + const QString m_newSettingsPath = "/Testing/NewTestKey"; + ProjectInfo m_projectInfo; + + private: + AZ::SettingsRegistryInterface* m_oldSettingsRegistry = nullptr; + AZStd::unique_ptr m_registry; + AZStd::unique_ptr m_serializeContext; + AZStd::unique_ptr m_registrationContext; + }; + + TEST_F(ProjectManagerSettingsTests, PMSettings_GetUnsetPathBool_ReturnsFalse) + { + bool settingsResult = false; + EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_FALSE(settingsResult); + } + + TEST_F(ProjectManagerSettingsTests, PMSettings_SetAndGetValueBool_Success) + { + bool settingsResult = false; + EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + + // Don't save to disk in test + EXPECT_TRUE(PMSettings::SetProjectManagerKey(m_settingsPath, true, /*saveToDisk*/ false)); + + settingsResult = false; + EXPECT_TRUE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_TRUE(settingsResult); + } + + TEST_F(ProjectManagerSettingsTests, PMSettings_GetUnsetPathString_ReturnsFalse) + { + QString settingsResult; + EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_TRUE(settingsResult.isEmpty()); + } + + TEST_F(ProjectManagerSettingsTests, PMSettings_SetAndGetValueString_Success) + { + QString settingsResult; + EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + + QString settingsValue = "TestValue"; + + // Don't save to disk in test + EXPECT_TRUE(PMSettings::SetProjectManagerKey(m_settingsPath, settingsValue, /*saveToDisk*/ false)); + + EXPECT_TRUE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_TRUE(settingsResult == settingsValue); + } + + TEST_F(ProjectManagerSettingsTests, PMSettings_CopyStringRemoveOriginal_SuccessAndRemovesOriginal) + { + QString settingsResult; + EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_newSettingsPath)); + + QString settingsValue = "TestValue"; + + // Don't save to disk in test + EXPECT_TRUE(PMSettings::SetProjectManagerKey(m_settingsPath, settingsValue, /*saveToDisk*/ false)); + + EXPECT_TRUE(PMSettings::CopyProjectManagerKeyString(m_settingsPath, m_newSettingsPath, /*removeOrig*/ true, /*saveToDisk*/ false)); + + // Check that old path value is removed + EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + + EXPECT_TRUE(PMSettings::GetProjectManagerKey(settingsResult, m_newSettingsPath)); + EXPECT_TRUE(settingsResult == settingsValue); + } + + TEST_F(ProjectManagerSettingsTests, PMSettings_RemoveProjectManagerKey_RemovesKey) + { + QString settingsResult; + EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + + QString settingsValue = "TestValue"; + + // Don't save to disk in test + EXPECT_TRUE(PMSettings::SetProjectManagerKey(m_settingsPath, settingsValue, /*saveToDisk*/ false)); + EXPECT_TRUE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + + EXPECT_TRUE(PMSettings::RemoveProjectManagerKey(m_settingsPath, /*saveToDisk*/ false)); + EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + } + + TEST_F(ProjectManagerSettingsTests, PMSettings_GetUnsetBuildPath_ReturnsFalse) + { + bool buildResult = true; + EXPECT_FALSE(PMSettings::GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); + EXPECT_FALSE(buildResult); + } + + TEST_F(ProjectManagerSettingsTests, PMSettings_SetProjectBuiltSuccessfully_ReturnsTrue) + { + // Don't save to disk in test + EXPECT_TRUE(PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, true, /*saveToDisk*/ false)); + + bool buildResult = false; + EXPECT_TRUE(PMSettings::GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); + EXPECT_TRUE(buildResult); + } + + TEST_F(ProjectManagerSettingsTests, PMSettings_SetProjectBuiltUnsuccessfully_ReturnsFalse) + { + // Don't save to disk in test + EXPECT_TRUE(PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, true, /*saveToDisk*/ false)); + + bool buildResult = true; + EXPECT_TRUE(PMSettings::GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); + EXPECT_FALSE(buildResult); + } +} diff --git a/Templates/DefaultProject/Template/project.json b/Templates/DefaultProject/Template/project.json index b52b0baf27..f8d4643ce9 100644 --- a/Templates/DefaultProject/Template/project.json +++ b/Templates/DefaultProject/Template/project.json @@ -1,5 +1,6 @@ { "project_name": "${Name}", + "project_id": "${ProjectId}", "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT", "display_name": "${Name}", diff --git a/Templates/MinimalProject/Template/project.json b/Templates/MinimalProject/Template/project.json index b52b0baf27..f8d4643ce9 100644 --- a/Templates/MinimalProject/Template/project.json +++ b/Templates/MinimalProject/Template/project.json @@ -1,5 +1,6 @@ { "project_name": "${Name}", + "project_id": "${ProjectId}", "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT", "display_name": "${Name}", diff --git a/q b/q new file mode 100644 index 0000000000..fc1c268aef --- /dev/null +++ b/q @@ -0,0 +1,48 @@ + Prism/AddEditGemsButton + Prism/AddLicenseToGemCatalog + Prism/AddRemoveRepoWorkingUI + Prism/AddRepoDialog +* Prism/CmakeVariablesPerProject + Prism/CreateRepositoryScreen + Prism/CustomBuildParameters + Prism/CustomTabWidgetForEngine + Prism/DeleteUpdateGemsUI + Prism/DisplayAddGemInfo + Prism/EnterInFileDialog + Prism/ExternalLinkWarning + Prism/FasterBuildTimes + Prism/FixGemCart + Prism/FixGemCatalogHyperlinks + Prism/FixGemSelectedFilter + Prism/FixRemovedProjectStillShown + Prism/FixTabOverlayOnStartup + Prism/GemCatalogMenu + Prism/GemCatalogTests + Prism/GemCatalogWithoutProject + Prism/GemRepoInspector + Prism/RefreshAfterDownload + Prism/RefreshGemRepos + Prism/RefreshOnDownload + Prism/RefreshRepoButtonDisablesRepo + Prism/RemoteGemWarning + Prism/RemoveTabFocus + Prism/ResetBuildAndCacheAfterProjectMove + Prism/SearchForGemsFromTags + Prism/ShowGemDownloadStatus + Prism/ShowGemPreview + Prism/ShowGemRepoGems + Prism/ShowGemsInRepo + Prism/ShowRepoGems + Prism/ShowRepoList + Prism/UpdateTemplatePics + Prism/UseGemDisplayNames + Prism/VS2019InstallInstructions + Prism/WarnExternalLink + Prism/WarnVSNotInstalled + Prism/cherry-pick-gem-catalog-fix + Prism/gitRepos + development + new-feature + racoonteurs + stabilization/2110 + stabilization/2111RTE diff --git a/scripts/o3de/o3de/engine_template.py b/scripts/o3de/o3de/engine_template.py index e93f972301..963ee3eb84 100755 --- a/scripts/o3de/o3de/engine_template.py +++ b/scripts/o3de/o3de/engine_template.py @@ -1113,7 +1113,7 @@ def create_from_template(destination_path: pathlib.Path, try: template_json_data = json.load(s) except KeyError as e: - logger.error(f'Could read template json {template_json}: {str(e)}.') + logger.error(f'Could not read template json {template_json}: {str(e)}.') return 1 # read template name from the json @@ -1338,7 +1338,8 @@ def create_project(project_path: pathlib.Path, no_register: bool = False, system_component_class_id: str = None, editor_system_component_class_id: str = None, - module_id: str = None) -> int: + module_id: str = None, + project_id: str = None) -> int: """ Template instantiation specialization that makes all default assumptions for a Project template instantiation, reducing the effort needed in instancing a project @@ -1366,6 +1367,7 @@ def create_project(project_path: pathlib.Path, :param editor_system_component_class_id: optionally specify a uuid for the editor system component class, default is random uuid :param module_id: optionally specify a uuid for the module class, default is random uuid + :param project_id: optionally specify a str for the project id, default is random uuid :return: 0 for success or non 0 failure code """ if template_name and template_path: @@ -1405,7 +1407,7 @@ def create_project(project_path: pathlib.Path, try: template_json_data = json.load(s) except json.JSONDecodeError as e: - logger.error(f'Could read template json {template_json}: {str(e)}.') + logger.error(f'Could not read template json {template_json}: {str(e)}.') return 1 # read template name from the json @@ -1577,6 +1579,12 @@ def create_project(project_path: pathlib.Path, replacements.append(("${NameLower}", project_name.lower())) replacements.append(("${SanitizedCppName}", sanitized_cpp_name)) + # was a project id specified + if project_id: + replacements.append(("${ProjectId}", project_id)) + else: + replacements.append(("${ProjectId}", '{' + str(uuid.uuid4()) + '}')) + # module id is a uuid with { and - if module_id: replacements.append(("${ModuleClassId}", module_id)) @@ -1784,7 +1792,7 @@ def create_gem(gem_path: pathlib.Path, try: template_json_data = json.load(s) except json.JSONDecodeError as e: - logger.error(f'Could read template json {template_json}: {str(e)}.') + logger.error(f'Could not read template json {template_json}: {str(e)}.') return 1 # read template name from the json @@ -2123,7 +2131,8 @@ def _run_create_project(args: argparse) -> int: args.no_register, args.system_component_class_id, args.editor_system_component_class_id, - args.module_id) + args.module_id, + args.project_id) def _run_create_gem(args: argparse) -> int: @@ -2404,6 +2413,9 @@ def add_args(subparsers) -> None: create_project_subparser.add_argument('--module-id', type=uuid.UUID, required=False, help='The uuid you want to associate with the module, default is a random' ' uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') + create_project_subparser.add_argument('--project-id', type=str, required=False, + help='The str id you want to associate with the project, default is a random uuid' + ' Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') create_project_subparser.add_argument('-f', '--force', action='store_true', default=False, help='Copies over instantiated template directory even if it exist.') create_project_subparser.add_argument('--no-register', action='store_true', default=False, diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index 04731ad3de..88c05537e9 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -29,6 +29,7 @@ def get_project_props(name: str = None, path: pathlib.Path = None) -> dict: def edit_project_props(proj_path: pathlib.Path = None, proj_name: str = None, new_name: str = None, + new_id: str = None, new_origin: str = None, new_display: str = None, new_summary: str = None, @@ -40,14 +41,15 @@ def edit_project_props(proj_path: pathlib.Path = None, if not proj_json: return 1 - - if new_origin: - proj_json['origin'] = new_origin if new_name: if not utils.validate_identifier(new_name): logger.error(f'Project name must be fewer than 64 characters, contain only alphanumeric, "_" or "-" characters, and start with a letter. {new_name}') return 1 - proj_json['project_name'] = new_name + proj_json['project_name'] = new_name + if new_id: + proj_json['project_id'] = new_id + if new_origin: + proj_json['origin'] = new_origin if new_display: proj_json['display_name'] = new_display if new_summary: @@ -78,6 +80,7 @@ def _edit_project_props(args: argparse) -> int: return edit_project_props(args.project_path, args.project_name, args.project_new_name, + args.project_id, args.project_origin, args.project_display, args.project_summary, @@ -95,6 +98,8 @@ def add_parser_args(parser): group = parser.add_argument_group('properties', 'arguments for modifying individual project properties.') group.add_argument('-pnn', '--project-new-name', type=str, required=False, help='Sets the name for the project.') + group.add_argument('-pid', '--project-id', type=str, required=False, + help='Sets the ID for the project.') group.add_argument('-po', '--project-origin', type=str, required=False, help='Sets description or url for project origin (such as project host, repository, owner...etc).') group.add_argument('-pd', '--project-display', type=str, required=False, diff --git a/scripts/o3de/o3de/register.py b/scripts/o3de/o3de/register.py index 2500df1568..aaadfb5709 100644 --- a/scripts/o3de/o3de/register.py +++ b/scripts/o3de/o3de/register.py @@ -570,7 +570,7 @@ def remove_invalid_o3de_projects(manifest_path: pathlib.Path = None) -> int: result = 0 for project in json_data.get('projects', []): - if not validation.valid_o3de_project_json(pathlib.Path(project).resolve() / 'project.json'): + if not validation.valid_o3de_project_json(pathlib.Path(project).resolve() / 'project.json', generate_uuid=True): logger.warning(f"Project path {project} is invalid.") # Attempt to unregister all invalid projects even if previous projects failed to unregister # but combine the result codes of each command. diff --git a/scripts/o3de/o3de/validation.py b/scripts/o3de/o3de/validation.py index 5c683f0667..a671e88edf 100644 --- a/scripts/o3de/o3de/validation.py +++ b/scripts/o3de/o3de/validation.py @@ -10,6 +10,7 @@ This file validating o3de object json files """ import json import pathlib +import uuid def valid_o3de_json_dict(json_data: dict, key: str) -> bool: return key in json_data @@ -44,7 +45,7 @@ def valid_o3de_engine_json(file_name: str or pathlib.Path) -> bool: return True -def valid_o3de_project_json(file_name: str or pathlib.Path) -> bool: +def valid_o3de_project_json(file_name: str or pathlib.Path, generate_uuid: bool = True) -> bool: file_name = pathlib.Path(file_name).resolve() if not file_name.is_file(): return False @@ -53,8 +54,22 @@ def valid_o3de_project_json(file_name: str or pathlib.Path) -> bool: try: json_data = json.load(f) test = json_data['project_name'] + + if not generate_uuid: + test = json_data['project_id'] + else: + test = json_data.get('project_id', 'No ID') + generate_new_id = test == 'No ID' + except (json.JSONDecodeError, KeyError) as e: return False + + # Generate a random uuid for the project json if it is missing instead of failing if generate_uuid is true + if generate_uuid and generate_new_id: + with file_name.open('w') as f: + new_uuid = '{' + str(uuid.uuid4()) + '}' + json_data.update({'project_id': new_uuid}) + f.write(json.dumps(json_data, indent=4) + '\n') return True diff --git a/scripts/o3de/tests/unit_test_project_properties.py b/scripts/o3de/tests/unit_test_project_properties.py index 0236e6cf90..1bcc6dcef3 100644 --- a/scripts/o3de/tests/unit_test_project_properties.py +++ b/scripts/o3de/tests/unit_test_project_properties.py @@ -16,6 +16,7 @@ from o3de import project_properties TEST_PROJECT_JSON_PAYLOAD = ''' { "project_name": "TestProject", + "project_id": "{24114e69-306d-4de6-b3b4-4cb1a3eca58e}" "origin": "The primary repo for TestProject goes here: i.e. http://www.mydomain.com", "license": "What license TestProject uses goes here: i.e. https://opensource.org/licenses/MIT", "display_name": "TestProject", @@ -45,20 +46,20 @@ def init_project_json_data(request): @pytest.mark.usefixtures('init_project_json_data') class TestEditProjectProperties: - @pytest.mark.parametrize("project_path, project_name, project_new_name, project_origin, project_display,\ - project_summary, project_icon, add_tags, delete_tags,\ - replace_tags, expected_result", [ + @pytest.mark.parametrize("project_path, project_name, project_new_name, project_id, project_origin,\ + project_display, project_summary, project_icon,\ + add_tags, delete_tags, replace_tags, expected_result", [ pytest.param(pathlib.PurePath('E:/TestProject'), - 'test', 'test', 'editing by pytest', 'Unit Test', 'pyTest project', 'pytest.bmp', 'A B C', + 'test', 'test', 'editing by pytest', 'ID', 'Unit Test', 'pyTest project', 'pytest.bmp', 'A B C', 'B', 'D E F', 0), pytest.param('', - 'test', 'test', 'editing by pytest', 'Unit Test', 'pyTest project', 'pytest.bmp', 'A B C', + 'test', 'test', 'editing by pytest', 'ID', 'Unit Test', 'pyTest project', 'pytest.bmp', 'A B C', 'B', 'D E F', 1) ] ) - def test_edit_project_properties(self, project_path, project_name, project_new_name, project_origin, project_display, - project_summary, project_icon, add_tags, delete_tags, - replace_tags, expected_result): + def test_edit_project_properties(self, project_path, project_name, project_new_name, project_origin, project_id, + project_display,project_summary, project_icon, add_tags, + delete_tags, replace_tags, expected_result): def get_project_json_data(project_name: str, project_path) -> dict: if not project_path: @@ -72,12 +73,14 @@ class TestEditProjectProperties: with patch('o3de.manifest.get_project_json_data', side_effect=get_project_json_data) as get_project_json_data_patch, \ patch('o3de.manifest.save_o3de_manifest', side_effect=save_o3de_manifest) as save_o3de_manifest_patch: - result = project_properties.edit_project_props(project_path, project_name, project_new_name, project_origin, - project_display, project_summary, project_icon, - add_tags, delete_tags, replace_tags) + result = project_properties.edit_project_props(project_path, project_name, project_new_name, project_id, + project_origin, project_display, project_summary, project_icon, + add_tags, delete_tags, replace_tags) assert result == expected_result if project_path: assert self.project_json.data + assert self.project_json.data.get('project_name', '') == project_new_name + assert self.project_json.data.get('project_id', '') == project_id assert self.project_json.data.get('origin', '') == project_origin assert self.project_json.data.get('display_name', '') == project_display assert self.project_json.data.get('summary', '') == project_summary From 1348b6e8258aa02302f1cc872a1f46629c023819 Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Mon, 6 Dec 2021 09:52:52 -0800 Subject: [PATCH 02/12] Removed q file Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- Code/Tools/ProjectManager/CMakeLists.txt | 2 - q | 48 ------------------------ 2 files changed, 50 deletions(-) delete mode 100644 q diff --git a/Code/Tools/ProjectManager/CMakeLists.txt b/Code/Tools/ProjectManager/CMakeLists.txt index b0e7ee9697..e76547ab5d 100644 --- a/Code/Tools/ProjectManager/CMakeLists.txt +++ b/Code/Tools/ProjectManager/CMakeLists.txt @@ -90,8 +90,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) 3rdParty::Python 3rdParty::pybind11 AZ::AzCore - AZ::AzCoreTestCommon - AZ::AzTestShared AZ::AzTest AZ::AzFramework AZ::AzFrameworkTestShared diff --git a/q b/q deleted file mode 100644 index fc1c268aef..0000000000 --- a/q +++ /dev/null @@ -1,48 +0,0 @@ - Prism/AddEditGemsButton - Prism/AddLicenseToGemCatalog - Prism/AddRemoveRepoWorkingUI - Prism/AddRepoDialog -* Prism/CmakeVariablesPerProject - Prism/CreateRepositoryScreen - Prism/CustomBuildParameters - Prism/CustomTabWidgetForEngine - Prism/DeleteUpdateGemsUI - Prism/DisplayAddGemInfo - Prism/EnterInFileDialog - Prism/ExternalLinkWarning - Prism/FasterBuildTimes - Prism/FixGemCart - Prism/FixGemCatalogHyperlinks - Prism/FixGemSelectedFilter - Prism/FixRemovedProjectStillShown - Prism/FixTabOverlayOnStartup - Prism/GemCatalogMenu - Prism/GemCatalogTests - Prism/GemCatalogWithoutProject - Prism/GemRepoInspector - Prism/RefreshAfterDownload - Prism/RefreshGemRepos - Prism/RefreshOnDownload - Prism/RefreshRepoButtonDisablesRepo - Prism/RemoteGemWarning - Prism/RemoveTabFocus - Prism/ResetBuildAndCacheAfterProjectMove - Prism/SearchForGemsFromTags - Prism/ShowGemDownloadStatus - Prism/ShowGemPreview - Prism/ShowGemRepoGems - Prism/ShowGemsInRepo - Prism/ShowRepoGems - Prism/ShowRepoList - Prism/UpdateTemplatePics - Prism/UseGemDisplayNames - Prism/VS2019InstallInstructions - Prism/WarnExternalLink - Prism/WarnVSNotInstalled - Prism/cherry-pick-gem-catalog-fix - Prism/gitRepos - development - new-feature - racoonteurs - stabilization/2110 - stabilization/2111RTE From 28e5e8b217b4f59fcb4791800e1c59adb4f6cbcc Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Wed, 8 Dec 2021 05:43:10 -0800 Subject: [PATCH 03/12] Fix Project Built Tests Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- .../tests/ProjectManagerSettingsTests.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp b/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp index 7ab93f798c..ba0cebd035 100644 --- a/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp +++ b/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -40,11 +41,19 @@ namespace O3DE::ProjectManager m_registry->SetContext(m_serializeContext.get()); m_registry->SetContext(m_registrationContext.get()); + AZ::JsonSystemComponent::Reflect(m_registrationContext.get()); + + m_serializeContext->RegisterGenericType>(); + m_projectInfo.m_path = "Z:/ProjectTestPath"; } void TearDown() override { + m_registrationContext->EnableRemoveReflection(); + AZ::JsonSystemComponent::Reflect(m_registrationContext.get()); + m_registrationContext->DisableRemoveReflection(); + m_registrationContext.reset(); m_serializeContext.reset(); @@ -167,9 +176,9 @@ namespace O3DE::ProjectManager TEST_F(ProjectManagerSettingsTests, PMSettings_SetProjectBuiltUnsuccessfully_ReturnsFalse) { // Don't save to disk in test - EXPECT_TRUE(PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, true, /*saveToDisk*/ false)); + EXPECT_TRUE(PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, false, /*saveToDisk*/ false)); - bool buildResult = true; + bool buildResult = false; EXPECT_TRUE(PMSettings::GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); EXPECT_FALSE(buildResult); } From c7893e0386179b49c0011fe0f96492817cad016f Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Wed, 8 Dec 2021 05:54:41 -0800 Subject: [PATCH 04/12] Remove unecessary change to CMakeLists.txt Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- Code/Tools/ProjectManager/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Tools/ProjectManager/CMakeLists.txt b/Code/Tools/ProjectManager/CMakeLists.txt index e76547ab5d..9974125ffb 100644 --- a/Code/Tools/ProjectManager/CMakeLists.txt +++ b/Code/Tools/ProjectManager/CMakeLists.txt @@ -89,7 +89,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) 3rdParty::Qt::Widgets 3rdParty::Python 3rdParty::pybind11 - AZ::AzCore AZ::AzTest AZ::AzFramework AZ::AzFrameworkTestShared From d7a3d634572278a35d22f466d28dff32926d417a Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Thu, 9 Dec 2021 09:24:01 -0800 Subject: [PATCH 05/12] Change ProjectSettings to Singleton interface Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- .../ProjectManager/Source/Application.cpp | 8 + .../Tools/ProjectManager/Source/Application.h | 2 + .../Source/ExternalLinkDialog.cpp | 5 +- .../ProjectManager/Source/LinkWidget.cpp | 7 +- .../Source/ProjectBuilderController.cpp | 10 +- .../Source/ProjectManagerSettings.cpp | 248 ------------------ .../Source/ProjectManagerSettings.h | 37 --- .../ProjectManager/Source/ProjectsScreen.cpp | 4 +- Code/Tools/ProjectManager/Source/Settings.cpp | 201 ++++++++++++++ Code/Tools/ProjectManager/Source/Settings.h | 50 ++++ .../ProjectManager/Source/SettingsInterface.h | 57 ++++ .../Source/UpdateProjectCtrl.cpp | 7 +- .../project_manager_files.cmake | 5 +- .../project_manager_tests_files.cmake | 2 +- ...gerSettingsTests.cpp => SettingsTests.cpp} | 80 +++--- 15 files changed, 383 insertions(+), 340 deletions(-) delete mode 100644 Code/Tools/ProjectManager/Source/ProjectManagerSettings.cpp delete mode 100644 Code/Tools/ProjectManager/Source/ProjectManagerSettings.h create mode 100644 Code/Tools/ProjectManager/Source/Settings.cpp create mode 100644 Code/Tools/ProjectManager/Source/Settings.h create mode 100644 Code/Tools/ProjectManager/Source/SettingsInterface.h rename Code/Tools/ProjectManager/tests/{ProjectManagerSettingsTests.cpp => SettingsTests.cpp} (57%) diff --git a/Code/Tools/ProjectManager/Source/Application.cpp b/Code/Tools/ProjectManager/Source/Application.cpp index 29e0df3c3a..8ce8075988 100644 --- a/Code/Tools/ProjectManager/Source/Application.cpp +++ b/Code/Tools/ProjectManager/Source/Application.cpp @@ -111,6 +111,14 @@ namespace O3DE::ProjectManager } } + m_settings = AZStd::make_unique(); + AZ_Assert(m_settings, "Failed to create Settings"); + + if (!m_settings->IsInitialized()) + { + return false; + } + const AZ::CommandLine* commandLine = GetCommandLine(); AZ_Assert(commandLine, "Failed to get command line"); diff --git a/Code/Tools/ProjectManager/Source/Application.h b/Code/Tools/ProjectManager/Source/Application.h index ad55694b18..e95645d500 100644 --- a/Code/Tools/ProjectManager/Source/Application.h +++ b/Code/Tools/ProjectManager/Source/Application.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #endif @@ -36,6 +37,7 @@ namespace O3DE::ProjectManager bool InitLog(const char* logName); AZStd::unique_ptr m_pythonBindings; + AZStd::unique_ptr m_settings; QSharedPointer m_app; QSharedPointer m_mainWindow; diff --git a/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp b/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp index 2f3d615863..eada467b6a 100644 --- a/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp +++ b/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -85,6 +85,7 @@ namespace O3DE::ProjectManager void ExternalLinkDialog::SetSkipDialogSetting(bool state) { - PMSettings::SetProjectManagerKey(PMSettings::GetExternalLinkWarningKey(), state); + auto settings = SettingsInterface::Get(); + settings->Set(QString(settings->ExternalLinkWarningKey), state); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/LinkWidget.cpp b/Code/Tools/ProjectManager/Source/LinkWidget.cpp index 87ccdb9aed..7a940e135b 100644 --- a/Code/Tools/ProjectManager/Source/LinkWidget.cpp +++ b/Code/Tools/ProjectManager/Source/LinkWidget.cpp @@ -8,9 +8,7 @@ #include #include -#include - -#include +#include #include #include @@ -33,7 +31,8 @@ namespace O3DE::ProjectManager { // Check if user request not to be shown external link warning dialog bool skipDialog = false; - PMSettings::GetProjectManagerKey(skipDialog, PMSettings::GetExternalLinkWarningKey()); + auto settings = SettingsInterface::Get(); + settings->Get(skipDialog, QString(settings->ExternalLinkWarningKey)); if (!skipDialog) { diff --git a/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp b/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp index 4fc188b289..0af3bfc503 100644 --- a/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp @@ -9,9 +9,7 @@ #include #include #include -#include - -#include +#include #include #include @@ -30,7 +28,7 @@ namespace O3DE::ProjectManager m_worker->moveToThread(&m_workerThread); // Remove key here in case Project Manager crashing while building that causes HandleResults to not be called - PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, false); + SettingsInterface::Get()->SetProjectBuiltSuccessfully(m_projectInfo, false); connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater); connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject); @@ -114,7 +112,7 @@ namespace O3DE::ProjectManager emit NotifyBuildProject(m_projectInfo); } - PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, false); + SettingsInterface::Get()->SetProjectBuiltSuccessfully(m_projectInfo, false); emit Done(false); return; @@ -123,7 +121,7 @@ namespace O3DE::ProjectManager { m_projectInfo.m_buildFailed = false; - PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, true); + SettingsInterface::Get()->SetProjectBuiltSuccessfully(m_projectInfo, true); } emit Done(true); diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerSettings.cpp b/Code/Tools/ProjectManager/Source/ProjectManagerSettings.cpp deleted file mode 100644 index 12dd569ad5..0000000000 --- a/Code/Tools/ProjectManager/Source/ProjectManagerSettings.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include - -#include -#include -#include - -namespace O3DE::ProjectManager -{ - namespace PMSettings - { - bool SaveProjectManagerSettings() - { - auto settingsRegistry = AZ::SettingsRegistry::Get(); - AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; - dumperSettings.m_prettifyOutput = true; - dumperSettings.m_jsonPointerPrefix = ProjectManagerKeyPrefix; - - AZStd::string stringBuffer; - AZ::IO::ByteContainerStream stringStream(&stringBuffer); - if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream( - *settingsRegistry, ProjectManagerKeyPrefix, stringStream, dumperSettings)) - { - AZ_Warning("ProjectManager", false, "Could not save Project Manager settings to stream"); - return false; - } - - AZ::IO::FixedMaxPath o3deUserPath = AZ::Utils::GetO3deManifestDirectory(); - o3deUserPath /= AZ::SettingsRegistryInterface::RegistryFolder; - o3deUserPath /= "ProjectManager.setreg"; - - bool saved = false; - constexpr auto configurationMode = - AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY; - - AZ::IO::SystemFile outputFile; - if (outputFile.Open(o3deUserPath.c_str(), configurationMode)) - { - saved = outputFile.Write(stringBuffer.data(), stringBuffer.size()) == stringBuffer.size(); - } - - AZ_Warning("ProjectManager", saved, "Unable to save Project Manager registry file to path: %s", o3deUserPath.c_str()); - return saved; - } - - bool GetProjectManagerKey(QString& result, const QString& settingsKey) - { - bool success = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - AZStd::string settingsValue; - success = settingsRegistry->Get(settingsValue, settingsKey.toStdString().c_str()); - - result = settingsValue.c_str(); - } - - return success; - } - - bool GetProjectManagerKey(bool& result, const QString& settingsKey) - { - bool success = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - success = settingsRegistry->Get(result, settingsKey.toStdString().c_str()); - } - - return success; - } - - bool SetProjectManagerKey(const QString& settingsKey, const QString& settingsValue, bool saveToDisk) - { - bool success = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - success = settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue.toStdString().c_str()); - - if (saveToDisk) - { - SaveProjectManagerSettings(); - } - } - - return success; - } - - bool SetProjectManagerKey(const QString& settingsKey, bool settingsValue, bool saveToDisk) - { - bool success = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - success = settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue); - - if (saveToDisk) - { - SaveProjectManagerSettings(); - } - } - - return success; - } - - bool RemoveProjectManagerKey(const QString& settingsKey, bool saveToDisk) - { - bool success = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - success = settingsRegistry->Remove(settingsKey.toStdString().c_str()); - - if (saveToDisk) - { - SaveProjectManagerSettings(); - } - } - - return success; - } - - bool CopyProjectManagerKeyString(const QString& settingsKeyOrig, const QString& settingsKeyDest, bool removeOrig, bool saveToDisk) - { - bool success = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - AZStd::string settingsValue; - success = settingsRegistry->Get(settingsValue, settingsKeyOrig.toStdString().c_str()); - - if (success) - { - success = settingsRegistry->Set(settingsKeyDest.toStdString().c_str(), settingsValue); - if (success) - { - if (removeOrig) - { - success = settingsRegistry->Remove(settingsKeyOrig.toStdString().c_str()); - } - - if (saveToDisk) - { - SaveProjectManagerSettings(); - } - } - } - } - - return success; - } - - QString GetProjectKey(const ProjectInfo& projectInfo) - { - return QString("%1/Projects/%2/%3").arg(ProjectManagerKeyPrefix, projectInfo.m_id, projectInfo.m_projectName); - } - - QString GetExternalLinkWarningKey() - { - return QString("%1/SkipExternalLinkWarning").arg(ProjectManagerKeyPrefix); - } - - QString GetProjectsBuiltSuccessfullyKey() - { - return QString("%1/SuccessfulBuildPaths").arg(ProjectManagerKeyPrefix); - } - - bool GetBuiltSuccessfullyPaths(AZStd::set& result) - { - bool success = false; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - QString builtKey = GetProjectsBuiltSuccessfullyKey(); - success = settingsRegistry->GetObject>(result, builtKey.toStdString().c_str()); - } - - return success; - } - - bool GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo) - { - AZStd::set builtPathsResult; - bool success = GetBuiltSuccessfullyPaths(builtPathsResult); - if (success) - { - // Check if buildPath is listed as successfully built - AZStd::string projectPath = projectInfo.m_path.toStdString().c_str(); - if (builtPathsResult.contains(projectPath)) - { - result = true; - } - } - // No project built statuses known - else - { - result = false; - } - - return success; - } - - bool SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt, bool saveToDisk) - { - AZStd::set builtPathsResult; - bool success = GetBuiltSuccessfullyPaths(builtPathsResult); - - AZStd::string projectPath = projectInfo.m_path.toStdString().c_str(); - if (successfullyBuilt) - { - //Add successfully built path to set - builtPathsResult.insert(projectPath); - } - else - { - // Remove unsuccessfully built path from set - builtPathsResult.erase(projectPath); - } - - auto settingsRegistry = AZ::SettingsRegistry::Get(); - if (settingsRegistry) - { - QString builtKey = GetProjectsBuiltSuccessfullyKey(); - success = settingsRegistry->SetObject>(builtKey.toStdString().c_str(), builtPathsResult); - - if (saveToDisk) - { - SaveProjectManagerSettings(); - } - } - else - { - success = false; - } - - return success; - } - - } // namespace PMSettings -} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerSettings.h b/Code/Tools/ProjectManager/Source/ProjectManagerSettings.h deleted file mode 100644 index 2a92fcab0f..0000000000 --- a/Code/Tools/ProjectManager/Source/ProjectManagerSettings.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#include -#endif - -namespace O3DE::ProjectManager -{ - namespace PMSettings - { - static constexpr char ProjectManagerKeyPrefix[] = "/O3DE/ProjectManager"; - - bool SaveProjectManagerSettings(); - bool GetProjectManagerKey(QString& result, const QString& settingsKey); - bool GetProjectManagerKey(bool& result, const QString& settingsKey); - bool SetProjectManagerKey(const QString& settingsKey, const QString& settingsValue, bool saveToDisk = true); - bool SetProjectManagerKey(const QString& settingsKey, bool settingsValue, bool saveToDisk = true); - bool RemoveProjectManagerKey(const QString& settingsKey, bool saveToDisk = true); - bool CopyProjectManagerKeyString( - const QString& settingsKeyOrig, const QString& settingsKeyDest, bool removeOrig = false, bool saveToDisk = true); - - QString GetProjectKey(const ProjectInfo& projectInfo); - QString GetExternalLinkWarningKey(); - - bool GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo); - bool SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt, bool saveToDisk = true); - } // namespace PMSettings -} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp index 9816595548..90ded37991 100644 --- a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include @@ -292,7 +292,7 @@ namespace O3DE::ProjectManager if (currentButton) { bool projectBuiltSuccessfully = false; - PMSettings::GetProjectBuiltSuccessfully(projectBuiltSuccessfully, project); + SettingsInterface::Get()->GetProjectBuiltSuccessfully(projectBuiltSuccessfully, project); if (!projectBuiltSuccessfully) { diff --git a/Code/Tools/ProjectManager/Source/Settings.cpp b/Code/Tools/ProjectManager/Source/Settings.cpp new file mode 100644 index 0000000000..50081fbff3 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/Settings.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include +#include + +namespace O3DE::ProjectManager +{ + Settings::Settings(bool saveToDisk) + : m_saveToDisk(saveToDisk) + { + m_settingsRegistry = AZ::SettingsRegistry::Get(); + + AZ_Assert(m_settingsRegistry, "Failed to create Settings"); + } + + bool Settings::IsInitialized() + { + // Settings intialized correctly if it successfuly got the SettingsRegistry + return m_settingsRegistry; + } + + bool Settings::Save() + { + AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; + dumperSettings.m_prettifyOutput = true; + dumperSettings.m_jsonPointerPrefix = ProjectManagerKeyPrefix; + + AZStd::string stringBuffer; + AZ::IO::ByteContainerStream stringStream(&stringBuffer); + if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream( + *m_settingsRegistry, ProjectManagerKeyPrefix, stringStream, dumperSettings)) + { + AZ_Warning("ProjectManager", false, "Could not save Project Manager settings to stream"); + return false; + } + + AZ::IO::FixedMaxPath o3deUserPath = AZ::Utils::GetO3deManifestDirectory(); + o3deUserPath /= AZ::SettingsRegistryInterface::RegistryFolder; + o3deUserPath /= "ProjectManager.setreg"; + + bool saved = false; + constexpr auto configurationMode = + AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY; + + AZ::IO::SystemFile outputFile; + if (outputFile.Open(o3deUserPath.c_str(), configurationMode)) + { + saved = outputFile.Write(stringBuffer.data(), stringBuffer.size()) == stringBuffer.size(); + } + + AZ_Warning("ProjectManager", saved, "Unable to save Project Manager registry file to path: %s", o3deUserPath.c_str()); + return saved; + } + + bool Settings::Get(QString& result, const QString& settingsKey) + { + bool success = false; + + AZStd::string settingsValue; + success = m_settingsRegistry->Get(settingsValue, settingsKey.toStdString().c_str()); + + result = settingsValue.c_str(); + return success; + } + + bool Settings::Get(bool& result, const QString& settingsKey) + { + return m_settingsRegistry->Get(result, settingsKey.toStdString().c_str()); + } + + bool Settings::Set(const QString& settingsKey, const QString& settingsValue) + { + bool success = false; + + success = m_settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue.toStdString().c_str()); + if (m_saveToDisk) + { + Save(); + } + + return success; + } + + bool Settings::Set(const QString& settingsKey, bool settingsValue) + { + bool success = false; + + success = m_settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue); + if (m_saveToDisk) + { + Save(); + } + + return success; + } + + bool Settings::Remove(const QString& settingsKey) + { + bool success = false; + + success = m_settingsRegistry->Remove(settingsKey.toStdString().c_str()); + if (m_saveToDisk) + { + Save(); + } + + return success; + } + + bool Settings::Copy(const QString& settingsKeyOrig, const QString& settingsKeyDest, bool removeOrig) + { + bool success = false; + AZStd::string settingsValue; + + success = m_settingsRegistry->Get(settingsValue, settingsKeyOrig.toStdString().c_str()); + + if (success) + { + success = m_settingsRegistry->Set(settingsKeyDest.toStdString().c_str(), settingsValue); + if (success) + { + if (removeOrig) + { + success = m_settingsRegistry->Remove(settingsKeyOrig.toStdString().c_str()); + } + if (m_saveToDisk) + { + Save(); + } + } + } + + return success; + } + + QString Settings::GetProjectKey(const ProjectInfo& projectInfo) + { + return QString("%1/Projects/%2/%3").arg(ProjectManagerKeyPrefix, projectInfo.m_id, projectInfo.m_projectName); + } + + bool Settings::GetBuiltSuccessfullyPaths(AZStd::set& result) + { + return m_settingsRegistry->GetObject>(result, ProjectsBuiltSuccessfullyKey); + } + + bool Settings::GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo) + { + AZStd::set builtPathsResult; + bool success = GetBuiltSuccessfullyPaths(builtPathsResult); + + // Check if buildPath is listed as successfully built + AZStd::string projectPath = projectInfo.m_path.toStdString().c_str(); + if (builtPathsResult.contains(projectPath)) + { + result = true; + } + // No project built statuses known + else + { + result = false; + } + + return success; + } + + bool Settings::SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt) + { + AZStd::set builtPathsResult; + bool success = GetBuiltSuccessfullyPaths(builtPathsResult); + + AZStd::string projectPath = projectInfo.m_path.toStdString().c_str(); + if (successfullyBuilt) + { + //Add successfully built path to set + builtPathsResult.insert(projectPath); + } + else + { + // Remove unsuccessfully built path from set + builtPathsResult.erase(projectPath); + } + + success = m_settingsRegistry->SetObject>(ProjectsBuiltSuccessfullyKey, builtPathsResult); + if (m_saveToDisk) + { + Save(); + } + + return success; + } + +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/Settings.h b/Code/Tools/ProjectManager/Source/Settings.h new file mode 100644 index 0000000000..f30715dba9 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/Settings.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +#include + +namespace AZ +{ + class SettingsRegistryInterface; +} + +namespace O3DE::ProjectManager +{ + class Settings + : public SettingsInterface::Registrar + { + public: + Settings(bool saveToDisk = true); + + bool IsInitialized() override; + + bool Get(QString& result, const QString& settingsKey) override; + bool Get(bool& result, const QString& settingsKey) override; + bool Set(const QString& settingsKey, const QString& settingsValue) override; + bool Set(const QString& settingsKey, bool settingsValue) override; + bool Remove(const QString& settingsKey) override; + bool Copy(const QString& settingsKeyOrig, const QString& settingsKeyDest, bool removeOrig = false) override; + + QString GetProjectKey(const ProjectInfo& projectInfo) override; + + bool GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo) override; + bool SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt) override; + + private: + bool Save(); + + bool GetBuiltSuccessfullyPaths(AZStd::set& result); + + bool m_saveToDisk; + AZ::SettingsRegistryInterface* m_settingsRegistry = nullptr; + }; +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/SettingsInterface.h b/Code/Tools/ProjectManager/Source/SettingsInterface.h new file mode 100644 index 0000000000..a106dedefd --- /dev/null +++ b/Code/Tools/ProjectManager/Source/SettingsInterface.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include + +#include +#include + +namespace O3DE::ProjectManager +{ + //! Interface used to interact with the settings functions + class ISettings + { + public: + AZ_RTTI(O3DE::ProjectManager::ISettings, "{95D87D95-0E04-462F-8B0B-ED15C0A9F090}"); + AZ_DISABLE_COPY_MOVE(ISettings); + + static constexpr char ProjectManagerKeyPrefix[] = "/O3DE/ProjectManager"; + static constexpr char ExternalLinkWarningKey[] = "/O3DE/ProjectManager/SkipExternalLinkWarning"; + static constexpr char ProjectsBuiltSuccessfullyKey[] = "/O3DE/ProjectManager/SkipExternalLinkWarning"; + + ISettings() = default; + virtual ~ISettings() = default; + + /** + * This checks if Settings is in a usable state + * @return true Settings is ready to be used, false otherwise + */ + virtual bool IsInitialized() = 0; + + /** + * Get info about a Gem. + * @param path The absolute path to the Gem + * @param projectPath (Optional) The absolute path to the Gem project + * @return an outcome with GemInfo on success + */ + virtual bool Get(QString& result, const QString& settingsKey) = 0; + virtual bool Get(bool& result, const QString& settingsKey) = 0; + virtual bool Set(const QString& settingsKey, const QString& settingsValue) = 0; + virtual bool Set(const QString& settingsKey, bool settingsValue) = 0; + virtual bool Remove(const QString& settingsKey) = 0; + virtual bool Copy(const QString& settingsKeyOrig, const QString& settingsKeyDest, bool removeOrig = false) = 0; + + virtual QString GetProjectKey(const ProjectInfo& projectInfo) = 0; + + virtual bool GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo) = 0; + virtual bool SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt) = 0; + }; + + using SettingsInterface = AZ::Interface; +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 71dae91a81..0e5f6f3ca5 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include @@ -307,8 +307,9 @@ namespace O3DE::ProjectManager { // Remove project build successfully paths for both old and new project names // because a full rebuild is required when moving projects - PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, false); - PMSettings::SetProjectBuiltSuccessfully(newProjectSettings, false); + auto settings = SettingsInterface::Get(); + settings->SetProjectBuiltSuccessfully(m_projectInfo, false); + settings->SetProjectBuiltSuccessfully(newProjectSettings, false); } if (!newProjectSettings.m_newPreviewImagePath.isEmpty()) diff --git a/Code/Tools/ProjectManager/project_manager_files.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake index 468e8dcbc5..915b1a072f 100644 --- a/Code/Tools/ProjectManager/project_manager_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -58,8 +58,6 @@ set(FILES Source/CreateProjectCtrl.cpp Source/UpdateProjectCtrl.h Source/UpdateProjectCtrl.cpp - Source/ProjectManagerSettings.h - Source/ProjectManagerSettings.cpp Source/ProjectsScreen.h Source/ProjectsScreen.cpp Source/ProjectSettingsScreen.h @@ -72,6 +70,9 @@ set(FILES Source/ProjectButtonWidget.cpp Source/ScreenHeaderWidget.h Source/ScreenHeaderWidget.cpp + Source/Settings.h + Source/Settings.cpp + Source/SettingsInterface.h Source/LinkWidget.h Source/LinkWidget.cpp Source/TagWidget.h diff --git a/Code/Tools/ProjectManager/project_manager_tests_files.cmake b/Code/Tools/ProjectManager/project_manager_tests_files.cmake index df9a0070a1..012a27d13a 100644 --- a/Code/Tools/ProjectManager/project_manager_tests_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_tests_files.cmake @@ -11,7 +11,7 @@ set(FILES Resources/ProjectManager.qss tests/ApplicationTests.cpp tests/GemCatalogTests.cpp - tests/ProjectManagerSettingsTests.cpp + tests/SettingsTests.cpp tests/PythonBindingsTests.cpp tests/main.cpp tests/UtilsTests.cpp diff --git a/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp b/Code/Tools/ProjectManager/tests/SettingsTests.cpp similarity index 57% rename from Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp rename to Code/Tools/ProjectManager/tests/SettingsTests.cpp index ba0cebd035..6ced8ddc8e 100644 --- a/Code/Tools/ProjectManager/tests/ProjectManagerSettingsTests.cpp +++ b/Code/Tools/ProjectManager/tests/SettingsTests.cpp @@ -13,15 +13,15 @@ #include #include -#include +#include namespace O3DE::ProjectManager { - class ProjectManagerSettingsTests + class SettingsTests : public ::UnitTest::ScopedAllocatorSetupFixture { public: - ~ProjectManagerSettingsTests() override = default; + ~SettingsTests() override = default; void SetUp() override { UnitTest::ScopedAllocatorSetupFixture::SetUp(); @@ -45,11 +45,15 @@ namespace O3DE::ProjectManager m_serializeContext->RegisterGenericType>(); + m_settings = AZStd::make_unique(/*saveToDisk*/ false); + m_projectInfo.m_path = "Z:/ProjectTestPath"; } void TearDown() override { + m_settings.reset(); + m_registrationContext->EnableRemoveReflection(); AZ::JsonSystemComponent::Reflect(m_registrationContext.get()); m_registrationContext->DisableRemoveReflection(); @@ -70,6 +74,7 @@ namespace O3DE::ProjectManager } protected: + AZStd::unique_ptr m_settings; const QString m_settingsPath = "/Testing/TestKey"; const QString m_newSettingsPath = "/Testing/NewTestKey"; ProjectInfo m_projectInfo; @@ -81,105 +86,110 @@ namespace O3DE::ProjectManager AZStd::unique_ptr m_registrationContext; }; - TEST_F(ProjectManagerSettingsTests, PMSettings_GetUnsetPathBool_ReturnsFalse) + TEST_F(SettingsTests, Settings_IsIntialized_Success) + { + EXPECT_TRUE(m_settings->IsInitialized()); + } + + TEST_F(SettingsTests, Settings_GetUnsetPathBool_ReturnsFalse) { bool settingsResult = false; - EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath)); EXPECT_FALSE(settingsResult); } - TEST_F(ProjectManagerSettingsTests, PMSettings_SetAndGetValueBool_Success) + TEST_F(SettingsTests, Settings_SetAndGetValueBool_Success) { bool settingsResult = false; - EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath)); // Don't save to disk in test - EXPECT_TRUE(PMSettings::SetProjectManagerKey(m_settingsPath, true, /*saveToDisk*/ false)); + EXPECT_TRUE(m_settings->Set(m_settingsPath, true)); settingsResult = false; - EXPECT_TRUE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_TRUE(m_settings->Get(settingsResult, m_settingsPath)); EXPECT_TRUE(settingsResult); } - TEST_F(ProjectManagerSettingsTests, PMSettings_GetUnsetPathString_ReturnsFalse) + TEST_F(SettingsTests, Settings_GetUnsetPathString_ReturnsFalse) { QString settingsResult; - EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath)); EXPECT_TRUE(settingsResult.isEmpty()); } - TEST_F(ProjectManagerSettingsTests, PMSettings_SetAndGetValueString_Success) + TEST_F(SettingsTests, Settings_SetAndGetValueString_Success) { QString settingsResult; - EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath)); QString settingsValue = "TestValue"; // Don't save to disk in test - EXPECT_TRUE(PMSettings::SetProjectManagerKey(m_settingsPath, settingsValue, /*saveToDisk*/ false)); + EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue)); - EXPECT_TRUE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_TRUE(m_settings->Get(settingsResult, m_settingsPath)); EXPECT_TRUE(settingsResult == settingsValue); } - TEST_F(ProjectManagerSettingsTests, PMSettings_CopyStringRemoveOriginal_SuccessAndRemovesOriginal) + TEST_F(SettingsTests, Settings_CopyStringRemoveOriginal_SuccessAndRemovesOriginal) { QString settingsResult; - EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_newSettingsPath)); + EXPECT_FALSE(m_settings->Get(settingsResult, m_newSettingsPath)); QString settingsValue = "TestValue"; // Don't save to disk in test - EXPECT_TRUE(PMSettings::SetProjectManagerKey(m_settingsPath, settingsValue, /*saveToDisk*/ false)); + EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue)); - EXPECT_TRUE(PMSettings::CopyProjectManagerKeyString(m_settingsPath, m_newSettingsPath, /*removeOrig*/ true, /*saveToDisk*/ false)); + EXPECT_TRUE(m_settings->Copy(m_settingsPath, m_newSettingsPath, /*removeOrig*/ true)); // Check that old path value is removed - EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath)); - EXPECT_TRUE(PMSettings::GetProjectManagerKey(settingsResult, m_newSettingsPath)); + EXPECT_TRUE(m_settings->Get(settingsResult, m_newSettingsPath)); EXPECT_TRUE(settingsResult == settingsValue); } - TEST_F(ProjectManagerSettingsTests, PMSettings_RemoveProjectManagerKey_RemovesKey) + TEST_F(SettingsTests, Settings_RemoveProjectManagerKey_RemovesKey) { QString settingsResult; - EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath)); QString settingsValue = "TestValue"; // Don't save to disk in test - EXPECT_TRUE(PMSettings::SetProjectManagerKey(m_settingsPath, settingsValue, /*saveToDisk*/ false)); - EXPECT_TRUE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue)); + EXPECT_TRUE(m_settings->Get(settingsResult, m_settingsPath)); - EXPECT_TRUE(PMSettings::RemoveProjectManagerKey(m_settingsPath, /*saveToDisk*/ false)); - EXPECT_FALSE(PMSettings::GetProjectManagerKey(settingsResult, m_settingsPath)); + EXPECT_TRUE(m_settings->Remove(m_settingsPath)); + EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath)); } - TEST_F(ProjectManagerSettingsTests, PMSettings_GetUnsetBuildPath_ReturnsFalse) + TEST_F(SettingsTests, Settings_GetUnsetBuildPath_ReturnsFalse) { bool buildResult = true; - EXPECT_FALSE(PMSettings::GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); + EXPECT_FALSE(m_settings->GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); EXPECT_FALSE(buildResult); } - TEST_F(ProjectManagerSettingsTests, PMSettings_SetProjectBuiltSuccessfully_ReturnsTrue) + TEST_F(SettingsTests, Settings_SetProjectBuiltSuccessfully_ReturnsTrue) { // Don't save to disk in test - EXPECT_TRUE(PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, true, /*saveToDisk*/ false)); + EXPECT_TRUE(m_settings->SetProjectBuiltSuccessfully(m_projectInfo, true)); bool buildResult = false; - EXPECT_TRUE(PMSettings::GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); + EXPECT_TRUE(m_settings->GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); EXPECT_TRUE(buildResult); } - TEST_F(ProjectManagerSettingsTests, PMSettings_SetProjectBuiltUnsuccessfully_ReturnsFalse) + TEST_F(SettingsTests, Settings_SetProjectBuiltUnsuccessfully_ReturnsFalse) { // Don't save to disk in test - EXPECT_TRUE(PMSettings::SetProjectBuiltSuccessfully(m_projectInfo, false, /*saveToDisk*/ false)); + EXPECT_TRUE(m_settings->SetProjectBuiltSuccessfully(m_projectInfo, false)); bool buildResult = false; - EXPECT_TRUE(PMSettings::GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); + EXPECT_TRUE(m_settings->GetProjectBuiltSuccessfully(buildResult, m_projectInfo)); EXPECT_FALSE(buildResult); } } From c632fadb8f6fcdfa6c16ee04b43d0b4994eec7c9 Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Thu, 9 Dec 2021 10:25:04 -0800 Subject: [PATCH 06/12] Remove Project ID field from New Project settings Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- .../Source/NewProjectSettingsScreen.cpp | 10 ---- .../Source/NewProjectSettingsScreen.h | 1 - .../Source/ProjectSettingsScreen.cpp | 25 +------- .../Source/ProjectSettingsScreen.h | 3 - .../ProjectManager/Source/PythonBindings.cpp | 20 +------ .../ProjectManager/Source/SettingsInterface.h | 58 +++++++++++++++++-- .../Source/UpdateProjectSettingsScreen.cpp | 24 +++++++- .../Source/UpdateProjectSettingsScreen.h | 3 + 8 files changed, 83 insertions(+), 61 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp index 4c306fc715..f1f56993ca 100644 --- a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp @@ -43,11 +43,9 @@ namespace O3DE::ProjectManager { const QString defaultName = GetDefaultProjectName(); const QString defaultPath = QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + defaultName); - const QString randomUuid = GenerateNewProjectId(); m_projectName->lineEdit()->setText(defaultName); m_projectPath->lineEdit()->setText(defaultPath); - m_projectId->lineEdit()->setText(randomUuid); // if we don't use a QFrame we cannot "contain" the widgets inside and move them around // as a group @@ -177,14 +175,6 @@ namespace O3DE::ProjectManager return QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + projectName); } - QString NewProjectSettingsScreen::GenerateNewProjectId() - { - AZStd::string uuid; - AZ::Uuid::CreateRandom().ToString(uuid); - - return QString(uuid.c_str()); - } - ProjectManagerScreen NewProjectSettingsScreen::GetScreenEnum() { return ProjectManagerScreen::NewProjectSettings; diff --git a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h index cfb215ba0c..42c47cb1ff 100644 --- a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h @@ -47,7 +47,6 @@ namespace O3DE::ProjectManager private: QString GetDefaultProjectName(); QString GetDefaultProjectPath(); - QString GenerateNewProjectId(); QString GetProjectAutoPath(); QFrame* CreateTemplateDetails(int margin); void UpdateTemplateDetails(const ProjectTemplateInfo& templateInfo); diff --git a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp index cf15cb5bbc..45023d7f80 100644 --- a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp @@ -60,10 +60,6 @@ namespace O3DE::ProjectManager connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectPathUpdated); m_verticalLayout->addWidget(m_projectPath); - m_projectId = new FormLineEditWidget(tr("Project ID"), "", this); - connect(m_projectId->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectIdUpdated); - m_verticalLayout->addWidget(m_projectId); - projectSettingsFrame->setLayout(m_verticalLayout); m_horizontalLayout->addWidget(projectSettingsFrame); @@ -98,7 +94,6 @@ namespace O3DE::ProjectManager // currently we don't have separate fields for changing the project name and display name projectInfo.m_displayName = projectInfo.m_projectName; projectInfo.m_path = m_projectPath->lineEdit()->text(); - projectInfo.m_id = m_projectId->lineEdit()->text(); return projectInfo; } @@ -147,19 +142,6 @@ namespace O3DE::ProjectManager return projectPathIsValid; } - bool ProjectSettingsScreen::ValidateProjectId() - { - bool projectIdIsValid = true; - if (m_projectId->lineEdit()->text().isEmpty()) - { - projectIdIsValid = false; - m_projectId->setErrorLabelText(tr("Project ID cannot be empty.")); - } - - m_projectId->setErrorLabelVisible(!projectIdIsValid); - return projectIdIsValid; - } - void ProjectSettingsScreen::OnProjectNameUpdated() { ValidateProjectName(); @@ -170,13 +152,8 @@ namespace O3DE::ProjectManager ValidateProjectName() && ValidateProjectPath(); } - void ProjectSettingsScreen::OnProjectIdUpdated() - { - ValidateProjectId(); - } - bool ProjectSettingsScreen::Validate() { - return ValidateProjectName() && ValidateProjectPath() && ValidateProjectId(); + return ValidateProjectName() && ValidateProjectPath(); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h index 928cde833e..752e286ce1 100644 --- a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h @@ -35,12 +35,10 @@ namespace O3DE::ProjectManager protected slots: virtual void OnProjectNameUpdated(); virtual void OnProjectPathUpdated(); - virtual void OnProjectIdUpdated(); protected: bool ValidateProjectName(); virtual bool ValidateProjectPath(); - bool ValidateProjectId(); QString GetDefaultProjectPath(); @@ -48,7 +46,6 @@ namespace O3DE::ProjectManager QVBoxLayout* m_verticalLayout; FormLineEditWidget* m_projectName; FormBrowseEditWidget* m_projectPath; - FormLineEditWidget* m_projectId; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 8d11028af6..2ae0e3450c 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -688,24 +688,8 @@ namespace O3DE::ProjectManager auto createProjectResult = m_engineTemplate.attr("create_project")( projectPath, QString_To_Py_String(projectInfo.m_projectName), // project_path - QString_To_Py_Path(projectTemplatePath), // template_path - pybind11::none(), // template_name - pybind11::none(), // project_restricted_path - pybind11::none(), // project_restricted_name - pybind11::none(), // template_restricted_path - pybind11::none(), // template_restricted_name - pybind11::none(), // project_restricted_platform_relative_path - pybind11::none(), // template_restricted_platform_relative_path - pybind11::none(), // keep_restricted_in_project - pybind11::none(), // keep_license_text - pybind11::none(), // replace - pybind11::none(), // force - pybind11::none(), // no_register - pybind11::none(), // system_component_class_id - pybind11::none(), // editor_system_component_class_id - pybind11::none(), // module_id - QString_To_Py_String(projectInfo.m_id) // project_id - ); + QString_To_Py_Path(projectTemplatePath) // template_path + ); if (createProjectResult.cast() == 0) { createdProjectInfo = ProjectInfoFromPath(projectPath); diff --git a/Code/Tools/ProjectManager/Source/SettingsInterface.h b/Code/Tools/ProjectManager/Source/SettingsInterface.h index a106dedefd..e345886b9f 100644 --- a/Code/Tools/ProjectManager/Source/SettingsInterface.h +++ b/Code/Tools/ProjectManager/Source/SettingsInterface.h @@ -35,21 +35,71 @@ namespace O3DE::ProjectManager virtual bool IsInitialized() = 0; /** - * Get info about a Gem. - * @param path The absolute path to the Gem - * @param projectPath (Optional) The absolute path to the Gem project - * @return an outcome with GemInfo on success + * Get the value for a string settings key + * @param result Store string result in this variable + * @param settingsKey The key to get the value in + * @return true if all calls to settings registry were successful */ virtual bool Get(QString& result, const QString& settingsKey) = 0; + /** + * Get the value for a bool settings key + * @param result Store bool result in this variable + * @param settingsKey The key to get the value in + * @return true if all calls to settings registry were successful + */ virtual bool Get(bool& result, const QString& settingsKey) = 0; + + /** + * Set the value for a string settings key + * @param settingsKey The key to set the value in + * @param settingsValue String value to set key to + * @return true if all calls to settings registry were successful + */ virtual bool Set(const QString& settingsKey, const QString& settingsValue) = 0; + /** + * Set the value for a bool settings key + * @param settingsKey The key to set the value in + * @param settingsValue Bool value to set key to + * @return true if all calls to settings registry were successful + */ virtual bool Set(const QString& settingsKey, bool settingsValue) = 0; + + /** + * Remove settings key + * @param settingsKey The key to remove + * @return true if all calls to settings registry were successful + */ virtual bool Remove(const QString& settingsKey) = 0; + + /** + * Copy the string settings value from one key to another + * @param settingsKeyOrig The original key to copy from + * @param settingsKeyDest The destination key to copy to + * @param removeOrig(Optional) Delete the original key if true + * @return true if all calls to settings registry were successful + */ virtual bool Copy(const QString& settingsKeyOrig, const QString& settingsKeyDest, bool removeOrig = false) = 0; + /** + * Generate prefix for project settings key + * @param projectInfo Project for settings key + * @return QString Prefix for project specific settings key + */ virtual QString GetProjectKey(const ProjectInfo& projectInfo) = 0; + /** + * Get the build status for a project + * @param result Store bool build status in this variable + * @param projectInfo Project to check built status for + * @return true if all calls to settings registry were successful + */ virtual bool GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo) = 0; + /** + * Set the build status for a project + * @param projectInfo Project to set built status for + * @param successfullyBuilt Bool value to set build status to + * @return true if all calls to settings registry were successful + */ virtual bool SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt) = 0; }; diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp index 7c8f981f59..8ebda6a823 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp @@ -45,6 +45,10 @@ namespace O3DE::ProjectManager previewExtrasLayout->addWidget(m_projectPreviewImage); m_verticalLayout->addLayout(previewExtrasLayout); + + m_projectId = new FormLineEditWidget(tr("Project ID"), "", this); + connect(m_projectId->lineEdit(), &QLineEdit::textChanged, this, &UpdateProjectSettingsScreen::OnProjectIdUpdated); + m_verticalLayout->addWidget(m_projectId); } ProjectManagerScreen UpdateProjectSettingsScreen::GetScreenEnum() @@ -90,7 +94,7 @@ namespace O3DE::ProjectManager bool UpdateProjectSettingsScreen::Validate() { - return ProjectSettingsScreen::Validate() && ValidateProjectPreview(); + return ProjectSettingsScreen::Validate() && ValidateProjectPreview() && ValidateProjectId(); } void UpdateProjectSettingsScreen::ResetProjectPreviewPath() @@ -108,6 +112,11 @@ namespace O3DE::ProjectManager QPixmap(m_projectPreview->lineEdit()->text()).scaled(m_projectPreviewImage->size(), Qt::KeepAspectRatioByExpanding)); } + void UpdateProjectSettingsScreen::OnProjectIdUpdated() + { + ValidateProjectId(); + } + bool UpdateProjectSettingsScreen::ValidateProjectPath() { bool projectPathIsValid = true; @@ -157,4 +166,17 @@ namespace O3DE::ProjectManager return projectPreviewIsValid; } + bool UpdateProjectSettingsScreen::ValidateProjectId() + { + bool projectIdIsValid = true; + if (m_projectId->lineEdit()->text().isEmpty()) + { + projectIdIsValid = false; + m_projectId->setErrorLabelText(tr("Project ID cannot be empty.")); + } + + m_projectId->setErrorLabelVisible(!projectIdIsValid); + return projectIdIsValid; + } + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h index 22d7794de4..ba1a0a5794 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h @@ -33,13 +33,16 @@ namespace O3DE::ProjectManager public slots: void UpdateProjectPreviewPath(); void PreviewPathChanged(); + void OnProjectIdUpdated(); protected: bool ValidateProjectPath() override; virtual bool ValidateProjectPreview(); + bool ValidateProjectId(); FormBrowseEditWidget* m_projectPreview; QLabel* m_projectPreviewImage; + FormLineEditWidget* m_projectId; ProjectInfo m_projectInfo; bool m_userChangedPreview; //! Did the user change the project preview path From 5641bcd5f1ebddcbc0ab4536da92b1805b577dd5 Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:56:50 -0800 Subject: [PATCH 07/12] Update Update Project Settings UI to show advanced settings and move project preview to right side panel Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- .../Resources/ProjectManager.qss | 13 +++- .../ProjectManager/Source/SettingsInterface.h | 2 +- .../Source/UpdateProjectSettingsScreen.cpp | 76 ++++++++++++++++--- .../Source/UpdateProjectSettingsScreen.h | 7 ++ 4 files changed, 85 insertions(+), 13 deletions(-) diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index 1fc808b72c..fba3a77593 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -250,9 +250,6 @@ QTabBar::tab:focus { margin-top:30px; } -#projectPreviewLabel { - margin: 10px 0 5px 0; -} #projectTemplate { margin: 25px 0 0 50px; @@ -329,6 +326,16 @@ QTabBar::tab:focus { border:none; } +#projectSettingsSectionTitle +{ + font-size:18px; +} + +#projectSmallInfoLabel +{ + font-size:10px; +} + #projectSettingsTab::tab-bar { left: 60px; } diff --git a/Code/Tools/ProjectManager/Source/SettingsInterface.h b/Code/Tools/ProjectManager/Source/SettingsInterface.h index e345886b9f..e407767424 100644 --- a/Code/Tools/ProjectManager/Source/SettingsInterface.h +++ b/Code/Tools/ProjectManager/Source/SettingsInterface.h @@ -23,7 +23,7 @@ namespace O3DE::ProjectManager static constexpr char ProjectManagerKeyPrefix[] = "/O3DE/ProjectManager"; static constexpr char ExternalLinkWarningKey[] = "/O3DE/ProjectManager/SkipExternalLinkWarning"; - static constexpr char ProjectsBuiltSuccessfullyKey[] = "/O3DE/ProjectManager/SkipExternalLinkWarning"; + static constexpr char ProjectsBuiltSuccessfullyKey[] = "/O3DE/ProjectManager/SuccessfulBuildPaths"; ISettings() = default; virtual ~ISettings() = default; diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp index 8ebda6a823..e10f3a0590 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace O3DE::ProjectManager { @@ -31,12 +32,10 @@ namespace O3DE::ProjectManager m_verticalLayout->addWidget(m_projectPreview); QVBoxLayout* previewExtrasLayout = new QVBoxLayout(this); - previewExtrasLayout->setAlignment(Qt::AlignLeft); - previewExtrasLayout->setContentsMargins(50, 0, 0, 0); + previewExtrasLayout->setAlignment(Qt::AlignTop); + previewExtrasLayout->setContentsMargins(30, 45, 30, 0); - QLabel* projectPreviewLabel = new QLabel(tr("Select an image (PNG). Minimum %1 x %2 pixels.") - .arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight))); - projectPreviewLabel->setObjectName("projectPreviewLabel"); + QLabel* projectPreviewLabel = new QLabel(tr("Project Preview")); previewExtrasLayout->addWidget(projectPreviewLabel); m_projectPreviewImage = new QLabel(this); @@ -44,11 +43,56 @@ namespace O3DE::ProjectManager m_projectPreviewImage->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); previewExtrasLayout->addWidget(m_projectPreviewImage); - m_verticalLayout->addLayout(previewExtrasLayout); + QLabel* projectPreviewInfoLabel = new QLabel(tr("Select an image (PNG). Minimum %1 x %2 pixels.") + .arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight))); + projectPreviewInfoLabel->setObjectName("projectSmallInfoLabel"); + projectPreviewInfoLabel->setWordWrap(true); + previewExtrasLayout->addWidget(projectPreviewInfoLabel); + + m_horizontalLayout->addLayout(previewExtrasLayout); + + m_verticalLayout->addSpacing(10); + + // Collapse button + QHBoxLayout* advancedCollapseLayout = new QHBoxLayout(); + advancedCollapseLayout->setContentsMargins(50, 0, 0, 0); + + m_advancedSettingsCollapseButton = new QPushButton(); + m_advancedSettingsCollapseButton->setCheckable(true); + m_advancedSettingsCollapseButton->setChecked(true); + m_advancedSettingsCollapseButton->setFlat(true); + m_advancedSettingsCollapseButton->setFocusPolicy(Qt::NoFocus); + m_advancedSettingsCollapseButton->setFixedWidth(s_collapseButtonSize); + connect(m_advancedSettingsCollapseButton, &QPushButton::clicked, this, [=]() + { + UpdateAdvancedSettingsCollapseState(); + }); + advancedCollapseLayout->addWidget(m_advancedSettingsCollapseButton); + + // Category title + QLabel* advancedLabel = new QLabel("Advanced Settings"); + advancedLabel->setObjectName("p"); + advancedCollapseLayout->addWidget(advancedLabel); + m_verticalLayout->addLayout(advancedCollapseLayout); + + m_verticalLayout->addSpacing(5); + + // Everything in the advanced settings widget will be collapsed/uncollapsed + { + m_advancedSettingWidget = new QWidget(); + m_verticalLayout->addWidget(m_advancedSettingWidget); + + QVBoxLayout* advancedSettingsLayout = new QVBoxLayout(); + advancedSettingsLayout->setMargin(0); + advancedSettingsLayout->setAlignment(Qt::AlignTop); + m_advancedSettingWidget->setLayout(advancedSettingsLayout); + + m_projectId = new FormLineEditWidget(tr("Project ID"), "", this); + connect(m_projectId->lineEdit(), &QLineEdit::textChanged, this, &UpdateProjectSettingsScreen::OnProjectIdUpdated); + advancedSettingsLayout->addWidget(m_projectId); + } - m_projectId = new FormLineEditWidget(tr("Project ID"), "", this); - connect(m_projectId->lineEdit(), &QLineEdit::textChanged, this, &UpdateProjectSettingsScreen::OnProjectIdUpdated); - m_verticalLayout->addWidget(m_projectId); + UpdateAdvancedSettingsCollapseState(); } ProjectManagerScreen UpdateProjectSettingsScreen::GetScreenEnum() @@ -179,4 +223,18 @@ namespace O3DE::ProjectManager return projectIdIsValid; } + void UpdateProjectSettingsScreen::UpdateAdvancedSettingsCollapseState() + { + if (m_advancedSettingsCollapseButton->isChecked()) + { + m_advancedSettingsCollapseButton->setIcon(QIcon(":/ArrowDownLine.svg")); + m_advancedSettingWidget->hide(); + } + else + { + m_advancedSettingsCollapseButton->setIcon(QIcon(":/ArrowUpLine.svg")); + m_advancedSettingWidget->show(); + } + } + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h index ba1a0a5794..40d1ccb9af 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h @@ -12,6 +12,7 @@ #endif QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QPushButton) namespace O3DE::ProjectManager { @@ -39,11 +40,17 @@ namespace O3DE::ProjectManager bool ValidateProjectPath() override; virtual bool ValidateProjectPreview(); bool ValidateProjectId(); + void UpdateAdvancedSettingsCollapseState(); + + inline constexpr static int s_collapseButtonSize = 24; FormBrowseEditWidget* m_projectPreview; QLabel* m_projectPreviewImage; FormLineEditWidget* m_projectId; + QPushButton* m_advancedSettingsCollapseButton = nullptr; + QWidget* m_advancedSettingWidget = nullptr; + ProjectInfo m_projectInfo; bool m_userChangedPreview; //! Did the user change the project preview path }; From 9f4895aaeadee149c391e977460464b20da2d83e Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Thu, 9 Dec 2021 15:30:32 -0800 Subject: [PATCH 08/12] Addressed remaining PR feedback Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- .../Resources/ProjectManager.qss | 1 - .../ProjectManager/Source/Application.cpp | 5 --- .../Source/ExternalLinkDialog.cpp | 3 +- .../ProjectManager/Source/LinkWidget.cpp | 3 +- Code/Tools/ProjectManager/Source/Settings.cpp | 43 ++++++++----------- Code/Tools/ProjectManager/Source/Settings.h | 3 +- .../ProjectManager/Source/SettingsInterface.h | 6 --- .../Source/UpdateProjectSettingsScreen.cpp | 4 +- .../ProjectManager/tests/SettingsTests.cpp | 11 ----- 9 files changed, 22 insertions(+), 57 deletions(-) diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index fba3a77593..3d100ec170 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -250,7 +250,6 @@ QTabBar::tab:focus { margin-top:30px; } - #projectTemplate { margin: 25px 0 0 50px; } diff --git a/Code/Tools/ProjectManager/Source/Application.cpp b/Code/Tools/ProjectManager/Source/Application.cpp index 8ce8075988..49706d515a 100644 --- a/Code/Tools/ProjectManager/Source/Application.cpp +++ b/Code/Tools/ProjectManager/Source/Application.cpp @@ -114,11 +114,6 @@ namespace O3DE::ProjectManager m_settings = AZStd::make_unique(); AZ_Assert(m_settings, "Failed to create Settings"); - if (!m_settings->IsInitialized()) - { - return false; - } - const AZ::CommandLine* commandLine = GetCommandLine(); AZ_Assert(commandLine, "Failed to get command line"); diff --git a/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp b/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp index eada467b6a..726f4e5119 100644 --- a/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp +++ b/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp @@ -85,7 +85,6 @@ namespace O3DE::ProjectManager void ExternalLinkDialog::SetSkipDialogSetting(bool state) { - auto settings = SettingsInterface::Get(); - settings->Set(QString(settings->ExternalLinkWarningKey), state); + SettingsInterface::Get()->Set(QString(ISettings::ExternalLinkWarningKey), state); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/LinkWidget.cpp b/Code/Tools/ProjectManager/Source/LinkWidget.cpp index 7a940e135b..1872afe4be 100644 --- a/Code/Tools/ProjectManager/Source/LinkWidget.cpp +++ b/Code/Tools/ProjectManager/Source/LinkWidget.cpp @@ -31,8 +31,7 @@ namespace O3DE::ProjectManager { // Check if user request not to be shown external link warning dialog bool skipDialog = false; - auto settings = SettingsInterface::Get(); - settings->Get(skipDialog, QString(settings->ExternalLinkWarningKey)); + SettingsInterface::Get()->Get(skipDialog, QString(ISettings::ExternalLinkWarningKey)); if (!skipDialog) { diff --git a/Code/Tools/ProjectManager/Source/Settings.cpp b/Code/Tools/ProjectManager/Source/Settings.cpp index 50081fbff3..e6adc5069c 100644 --- a/Code/Tools/ProjectManager/Source/Settings.cpp +++ b/Code/Tools/ProjectManager/Source/Settings.cpp @@ -22,12 +22,6 @@ namespace O3DE::ProjectManager AZ_Assert(m_settingsRegistry, "Failed to create Settings"); } - bool Settings::IsInitialized() - { - // Settings intialized correctly if it successfuly got the SettingsRegistry - return m_settingsRegistry; - } - bool Settings::Save() { AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; @@ -61,6 +55,18 @@ namespace O3DE::ProjectManager return saved; } + bool Settings::OnSettingsChanged() + { + if (m_saveToDisk) + { + return Save(); + } + else + { + return true; + } + } + bool Settings::Get(QString& result, const QString& settingsKey) { bool success = false; @@ -82,10 +88,7 @@ namespace O3DE::ProjectManager bool success = false; success = m_settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue.toStdString().c_str()); - if (m_saveToDisk) - { - Save(); - } + OnSettingsChanged(); return success; } @@ -95,10 +98,7 @@ namespace O3DE::ProjectManager bool success = false; success = m_settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue); - if (m_saveToDisk) - { - Save(); - } + OnSettingsChanged(); return success; } @@ -108,10 +108,7 @@ namespace O3DE::ProjectManager bool success = false; success = m_settingsRegistry->Remove(settingsKey.toStdString().c_str()); - if (m_saveToDisk) - { - Save(); - } + OnSettingsChanged(); return success; } @@ -132,10 +129,7 @@ namespace O3DE::ProjectManager { success = m_settingsRegistry->Remove(settingsKeyOrig.toStdString().c_str()); } - if (m_saveToDisk) - { - Save(); - } + OnSettingsChanged(); } } @@ -190,10 +184,7 @@ namespace O3DE::ProjectManager } success = m_settingsRegistry->SetObject>(ProjectsBuiltSuccessfullyKey, builtPathsResult); - if (m_saveToDisk) - { - Save(); - } + OnSettingsChanged(); return success; } diff --git a/Code/Tools/ProjectManager/Source/Settings.h b/Code/Tools/ProjectManager/Source/Settings.h index f30715dba9..fb6087358b 100644 --- a/Code/Tools/ProjectManager/Source/Settings.h +++ b/Code/Tools/ProjectManager/Source/Settings.h @@ -25,8 +25,6 @@ namespace O3DE::ProjectManager public: Settings(bool saveToDisk = true); - bool IsInitialized() override; - bool Get(QString& result, const QString& settingsKey) override; bool Get(bool& result, const QString& settingsKey) override; bool Set(const QString& settingsKey, const QString& settingsValue) override; @@ -41,6 +39,7 @@ namespace O3DE::ProjectManager private: bool Save(); + bool OnSettingsChanged(); bool GetBuiltSuccessfullyPaths(AZStd::set& result); diff --git a/Code/Tools/ProjectManager/Source/SettingsInterface.h b/Code/Tools/ProjectManager/Source/SettingsInterface.h index e407767424..da1363dee5 100644 --- a/Code/Tools/ProjectManager/Source/SettingsInterface.h +++ b/Code/Tools/ProjectManager/Source/SettingsInterface.h @@ -28,12 +28,6 @@ namespace O3DE::ProjectManager ISettings() = default; virtual ~ISettings() = default; - /** - * This checks if Settings is in a usable state - * @return true Settings is ready to be used, false otherwise - */ - virtual bool IsInitialized() = 0; - /** * Get the value for a string settings key * @param result Store string result in this variable diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp index e10f3a0590..6589ee25e6 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp @@ -70,8 +70,8 @@ namespace O3DE::ProjectManager advancedCollapseLayout->addWidget(m_advancedSettingsCollapseButton); // Category title - QLabel* advancedLabel = new QLabel("Advanced Settings"); - advancedLabel->setObjectName("p"); + QLabel* advancedLabel = new QLabel(tr("Advanced Settings")); + advancedLabel->setObjectName("projectSettingsSectionTitle"); advancedCollapseLayout->addWidget(advancedLabel); m_verticalLayout->addLayout(advancedCollapseLayout); diff --git a/Code/Tools/ProjectManager/tests/SettingsTests.cpp b/Code/Tools/ProjectManager/tests/SettingsTests.cpp index 6ced8ddc8e..d994a59737 100644 --- a/Code/Tools/ProjectManager/tests/SettingsTests.cpp +++ b/Code/Tools/ProjectManager/tests/SettingsTests.cpp @@ -86,11 +86,6 @@ namespace O3DE::ProjectManager AZStd::unique_ptr m_registrationContext; }; - TEST_F(SettingsTests, Settings_IsIntialized_Success) - { - EXPECT_TRUE(m_settings->IsInitialized()); - } - TEST_F(SettingsTests, Settings_GetUnsetPathBool_ReturnsFalse) { bool settingsResult = false; @@ -103,7 +98,6 @@ namespace O3DE::ProjectManager bool settingsResult = false; EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath)); - // Don't save to disk in test EXPECT_TRUE(m_settings->Set(m_settingsPath, true)); settingsResult = false; @@ -125,7 +119,6 @@ namespace O3DE::ProjectManager QString settingsValue = "TestValue"; - // Don't save to disk in test EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue)); EXPECT_TRUE(m_settings->Get(settingsResult, m_settingsPath)); @@ -139,7 +132,6 @@ namespace O3DE::ProjectManager QString settingsValue = "TestValue"; - // Don't save to disk in test EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue)); EXPECT_TRUE(m_settings->Copy(m_settingsPath, m_newSettingsPath, /*removeOrig*/ true)); @@ -158,7 +150,6 @@ namespace O3DE::ProjectManager QString settingsValue = "TestValue"; - // Don't save to disk in test EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue)); EXPECT_TRUE(m_settings->Get(settingsResult, m_settingsPath)); @@ -175,7 +166,6 @@ namespace O3DE::ProjectManager TEST_F(SettingsTests, Settings_SetProjectBuiltSuccessfully_ReturnsTrue) { - // Don't save to disk in test EXPECT_TRUE(m_settings->SetProjectBuiltSuccessfully(m_projectInfo, true)); bool buildResult = false; @@ -185,7 +175,6 @@ namespace O3DE::ProjectManager TEST_F(SettingsTests, Settings_SetProjectBuiltUnsuccessfully_ReturnsFalse) { - // Don't save to disk in test EXPECT_TRUE(m_settings->SetProjectBuiltSuccessfully(m_projectInfo, false)); bool buildResult = false; From af9e75da66bf4742a934152aa9506ab2ce1f83fe Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Fri, 10 Dec 2021 06:19:28 -0800 Subject: [PATCH 09/12] Minor PR feedback changes Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- .../ProjectManager/Source/ExternalLinkDialog.cpp | 2 +- Code/Tools/ProjectManager/Source/LinkWidget.cpp | 2 +- Code/Tools/ProjectManager/Source/Settings.cpp | 13 ++++--------- Code/Tools/ProjectManager/Source/Settings.h | 4 ++-- .../Source/UpdateProjectSettingsScreen.cpp | 5 +---- .../Source/UpdateProjectSettingsScreen.h | 4 +++- 6 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp b/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp index 726f4e5119..2d24913b5d 100644 --- a/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp +++ b/Code/Tools/ProjectManager/Source/ExternalLinkDialog.cpp @@ -85,6 +85,6 @@ namespace O3DE::ProjectManager void ExternalLinkDialog::SetSkipDialogSetting(bool state) { - SettingsInterface::Get()->Set(QString(ISettings::ExternalLinkWarningKey), state); + SettingsInterface::Get()->Set(ISettings::ExternalLinkWarningKey, state); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/LinkWidget.cpp b/Code/Tools/ProjectManager/Source/LinkWidget.cpp index 1872afe4be..bdafec24d8 100644 --- a/Code/Tools/ProjectManager/Source/LinkWidget.cpp +++ b/Code/Tools/ProjectManager/Source/LinkWidget.cpp @@ -31,7 +31,7 @@ namespace O3DE::ProjectManager { // Check if user request not to be shown external link warning dialog bool skipDialog = false; - SettingsInterface::Get()->Get(skipDialog, QString(ISettings::ExternalLinkWarningKey)); + SettingsInterface::Get()->Get(skipDialog, ISettings::ExternalLinkWarningKey); if (!skipDialog) { diff --git a/Code/Tools/ProjectManager/Source/Settings.cpp b/Code/Tools/ProjectManager/Source/Settings.cpp index e6adc5069c..0a8b600dd9 100644 --- a/Code/Tools/ProjectManager/Source/Settings.cpp +++ b/Code/Tools/ProjectManager/Source/Settings.cpp @@ -22,7 +22,7 @@ namespace O3DE::ProjectManager AZ_Assert(m_settingsRegistry, "Failed to create Settings"); } - bool Settings::Save() + void Settings::Save() { AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; dumperSettings.m_prettifyOutput = true; @@ -34,7 +34,7 @@ namespace O3DE::ProjectManager *m_settingsRegistry, ProjectManagerKeyPrefix, stringStream, dumperSettings)) { AZ_Warning("ProjectManager", false, "Could not save Project Manager settings to stream"); - return false; + return; } AZ::IO::FixedMaxPath o3deUserPath = AZ::Utils::GetO3deManifestDirectory(); @@ -52,18 +52,13 @@ namespace O3DE::ProjectManager } AZ_Warning("ProjectManager", saved, "Unable to save Project Manager registry file to path: %s", o3deUserPath.c_str()); - return saved; } - bool Settings::OnSettingsChanged() + void Settings::OnSettingsChanged() { if (m_saveToDisk) { - return Save(); - } - else - { - return true; + Save(); } } diff --git a/Code/Tools/ProjectManager/Source/Settings.h b/Code/Tools/ProjectManager/Source/Settings.h index fb6087358b..a3b2a7212e 100644 --- a/Code/Tools/ProjectManager/Source/Settings.h +++ b/Code/Tools/ProjectManager/Source/Settings.h @@ -38,8 +38,8 @@ namespace O3DE::ProjectManager bool SetProjectBuiltSuccessfully(const ProjectInfo& projectInfo, bool successfullyBuilt) override; private: - bool Save(); - bool OnSettingsChanged(); + void Save(); + void OnSettingsChanged(); bool GetBuiltSuccessfullyPaths(AZStd::set& result); diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp index 6589ee25e6..30735dcc97 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp @@ -63,10 +63,7 @@ namespace O3DE::ProjectManager m_advancedSettingsCollapseButton->setFlat(true); m_advancedSettingsCollapseButton->setFocusPolicy(Qt::NoFocus); m_advancedSettingsCollapseButton->setFixedWidth(s_collapseButtonSize); - connect(m_advancedSettingsCollapseButton, &QPushButton::clicked, this, [=]() - { - UpdateAdvancedSettingsCollapseState(); - }); + connect(m_advancedSettingsCollapseButton, &QPushButton::clicked, this, &UpdateProjectSettingsScreen::UpdateAdvancedSettingsCollapseState); advancedCollapseLayout->addWidget(m_advancedSettingsCollapseButton); // Category title diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h index 40d1ccb9af..28ea032985 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.h @@ -40,7 +40,6 @@ namespace O3DE::ProjectManager bool ValidateProjectPath() override; virtual bool ValidateProjectPreview(); bool ValidateProjectId(); - void UpdateAdvancedSettingsCollapseState(); inline constexpr static int s_collapseButtonSize = 24; @@ -53,6 +52,9 @@ namespace O3DE::ProjectManager ProjectInfo m_projectInfo; bool m_userChangedPreview; //! Did the user change the project preview path + + protected slots: + void UpdateAdvancedSettingsCollapseState(); }; } // namespace O3DE::ProjectManager From 214716dafc6d4291a0465e58c2f172f9ff5f3520 Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Fri, 10 Dec 2021 07:48:41 -0800 Subject: [PATCH 10/12] Add AZStd string header for linux Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- Code/Tools/ProjectManager/Source/Settings.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Tools/ProjectManager/Source/Settings.h b/Code/Tools/ProjectManager/Source/Settings.h index a3b2a7212e..416d17b53b 100644 --- a/Code/Tools/ProjectManager/Source/Settings.h +++ b/Code/Tools/ProjectManager/Source/Settings.h @@ -10,6 +10,7 @@ #include +#include #include namespace AZ From e9db0bca6ac362cf77bd247d127c1b3bc2101a4b Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:42:18 -0800 Subject: [PATCH 11/12] Fix typo, add missing header, remove unecessary asserts Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- Code/Tools/ProjectManager/Source/Application.cpp | 3 +-- .../Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp | 3 +++ Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/Application.cpp b/Code/Tools/ProjectManager/Source/Application.cpp index abc992bd02..a9ab59a991 100644 --- a/Code/Tools/ProjectManager/Source/Application.cpp +++ b/Code/Tools/ProjectManager/Source/Application.cpp @@ -70,7 +70,7 @@ namespace O3DE::ProjectManager } m_pythonBindings = AZStd::make_unique(GetEngineRoot()); - AZ_Assert(m_pythonBindings, "Failed to create PythonBindings"); + if (!m_pythonBindings->PythonStarted()) { if (!interactive) @@ -113,7 +113,6 @@ namespace O3DE::ProjectManager } m_settings = AZStd::make_unique(); - AZ_Assert(m_settings, "Failed to create Settings"); if (!RegisterEngine(interactive)) { diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp index acea6ce378..d960145057 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp @@ -7,6 +7,9 @@ */ #include + +#include + #include #include #include diff --git a/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp b/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp index 0af3bfc503..e2c54f622d 100644 --- a/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectBuilderController.cpp @@ -27,7 +27,7 @@ namespace O3DE::ProjectManager m_worker = new ProjectBuilderWorker(m_projectInfo); m_worker->moveToThread(&m_workerThread); - // Remove key here in case Project Manager crashing while building that causes HandleResults to not be called + // Remove key here in case Project Manager crashed while building because that causes HandleResults to not be called SettingsInterface::Get()->SetProjectBuiltSuccessfully(m_projectInfo, false); connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater); From 3cf85bb5624fdfc53fef41cc1ee8a26681402d3f Mon Sep 17 00:00:00 2001 From: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Fri, 10 Dec 2021 14:12:14 -0800 Subject: [PATCH 12/12] Fix project properties test Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com> --- engine.json | 1 - scripts/o3de/tests/unit_test_project_properties.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/engine.json b/engine.json index 0aa3238f49..737ac24fea 100644 --- a/engine.json +++ b/engine.json @@ -86,7 +86,6 @@ "Gems/WhiteBox" ], "projects": [ - "AtomTest", "AutomatedTesting" ], "templates": [ diff --git a/scripts/o3de/tests/unit_test_project_properties.py b/scripts/o3de/tests/unit_test_project_properties.py index 1bcc6dcef3..dcf736f016 100644 --- a/scripts/o3de/tests/unit_test_project_properties.py +++ b/scripts/o3de/tests/unit_test_project_properties.py @@ -16,7 +16,7 @@ from o3de import project_properties TEST_PROJECT_JSON_PAYLOAD = ''' { "project_name": "TestProject", - "project_id": "{24114e69-306d-4de6-b3b4-4cb1a3eca58e}" + "project_id": "{24114e69-306d-4de6-b3b4-4cb1a3eca58e}", "origin": "The primary repo for TestProject goes here: i.e. http://www.mydomain.com", "license": "What license TestProject uses goes here: i.e. https://opensource.org/licenses/MIT", "display_name": "TestProject", @@ -57,8 +57,8 @@ class TestEditProjectProperties: 'B', 'D E F', 1) ] ) - def test_edit_project_properties(self, project_path, project_name, project_new_name, project_origin, project_id, - project_display,project_summary, project_icon, add_tags, + def test_edit_project_properties(self, project_path, project_name, project_new_name, project_id, project_origin, + project_display, project_summary, project_icon, add_tags, delete_tags, replace_tags, expected_result): def get_project_json_data(project_name: str, project_path) -> dict: