Merge pull request #6172 from aws-lumberyard-dev/Prism/RefactorProjectSettings
Refactor Project Manager Settings
This commit is contained in:
@@ -10,5 +10,7 @@
|
|||||||
"version_name": "1.0.0.0",
|
"version_name": "1.0.0.0",
|
||||||
"orientation": "landscape"
|
"orientation": "landscape"
|
||||||
},
|
},
|
||||||
"engine": "o3de"
|
"engine": "o3de",
|
||||||
}
|
"display_name": "AutomatedTesting",
|
||||||
|
"icon_path": "preview.png"
|
||||||
|
}
|
||||||
|
|||||||
@@ -250,10 +250,6 @@ QTabBar::tab:focus {
|
|||||||
margin-top:30px;
|
margin-top:30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#projectPreviewLabel {
|
|
||||||
margin: 10px 0 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#projectTemplate {
|
#projectTemplate {
|
||||||
margin: 25px 0 0 50px;
|
margin: 25px 0 0 50px;
|
||||||
}
|
}
|
||||||
@@ -329,6 +325,16 @@ QTabBar::tab:focus {
|
|||||||
border:none;
|
border:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#projectSettingsSectionTitle
|
||||||
|
{
|
||||||
|
font-size:18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#projectSmallInfoLabel
|
||||||
|
{
|
||||||
|
font-size:10px;
|
||||||
|
}
|
||||||
|
|
||||||
#projectSettingsTab::tab-bar {
|
#projectSettingsTab::tab-bar {
|
||||||
left: 60px;
|
left: 60px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace O3DE::ProjectManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_pythonBindings = AZStd::make_unique<PythonBindings>(GetEngineRoot());
|
m_pythonBindings = AZStd::make_unique<PythonBindings>(GetEngineRoot());
|
||||||
AZ_Assert(m_pythonBindings, "Failed to create PythonBindings");
|
|
||||||
if (!m_pythonBindings->PythonStarted())
|
if (!m_pythonBindings->PythonStarted())
|
||||||
{
|
{
|
||||||
if (!interactive)
|
if (!interactive)
|
||||||
@@ -112,6 +112,8 @@ namespace O3DE::ProjectManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_settings = AZStd::make_unique<Settings>();
|
||||||
|
|
||||||
if (!RegisterEngine(interactive))
|
if (!RegisterEngine(interactive))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <AzFramework/Application/Application.h>
|
#include <AzFramework/Application/Application.h>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <PythonBindings.h>
|
#include <PythonBindings.h>
|
||||||
|
#include <Settings.h>
|
||||||
#include <ProjectManagerWindow.h>
|
#include <ProjectManagerWindow.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ namespace O3DE::ProjectManager
|
|||||||
bool RegisterEngine(bool interactive);
|
bool RegisterEngine(bool interactive);
|
||||||
|
|
||||||
AZStd::unique_ptr<PythonBindings> m_pythonBindings;
|
AZStd::unique_ptr<PythonBindings> m_pythonBindings;
|
||||||
|
AZStd::unique_ptr<Settings> m_settings;
|
||||||
QSharedPointer<QCoreApplication> m_app;
|
QSharedPointer<QCoreApplication> m_app;
|
||||||
QSharedPointer<ProjectManagerWindow> m_mainWindow;
|
QSharedPointer<ProjectManagerWindow> m_mainWindow;
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,7 @@
|
|||||||
|
|
||||||
#include <ExternalLinkDialog.h>
|
#include <ExternalLinkDialog.h>
|
||||||
#include <LinkWidget.h>
|
#include <LinkWidget.h>
|
||||||
#include <ProjectManagerSettings.h>
|
#include <SettingsInterface.h>
|
||||||
|
|
||||||
#include <AzCore/Settings/SettingsRegistry.h>
|
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
@@ -87,12 +85,6 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
void ExternalLinkDialog::SetSkipDialogSetting(bool state)
|
void ExternalLinkDialog::SetSkipDialogSetting(bool state)
|
||||||
{
|
{
|
||||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
SettingsInterface::Get()->Set(ISettings::ExternalLinkWarningKey, state);
|
||||||
if (settingsRegistry)
|
|
||||||
{
|
|
||||||
QString settingsKey = GetExternalLinkWarningKey();
|
|
||||||
settingsRegistry->Set(settingsKey.toStdString().c_str(), state);
|
|
||||||
SaveProjectManagerSettings();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace O3DE::ProjectManager
|
} // namespace O3DE::ProjectManager
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <GemCatalog/GemFilterWidget.h>
|
#include <GemCatalog/GemFilterWidget.h>
|
||||||
|
|
||||||
|
#include <AzCore/Math/MathUtils.h>
|
||||||
|
|
||||||
#include <QButtonGroup>
|
#include <QButtonGroup>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if !defined(Q_MOC_RUN)
|
#if !defined(Q_MOC_RUN)
|
||||||
#include <AzCore/Math/Uuid.h>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|||||||
@@ -8,9 +8,7 @@
|
|||||||
|
|
||||||
#include <LinkWidget.h>
|
#include <LinkWidget.h>
|
||||||
#include <ExternalLinkDialog.h>
|
#include <ExternalLinkDialog.h>
|
||||||
#include <ProjectManagerSettings.h>
|
#include <SettingsInterface.h>
|
||||||
|
|
||||||
#include <AzCore/Settings/SettingsRegistry.h>
|
|
||||||
|
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
@@ -33,13 +31,7 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
// Check if user request not to be shown external link warning dialog
|
// Check if user request not to be shown external link warning dialog
|
||||||
bool skipDialog = false;
|
bool skipDialog = false;
|
||||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
SettingsInterface::Get()->Get(skipDialog, ISettings::ExternalLinkWarningKey);
|
||||||
|
|
||||||
if (settingsRegistry)
|
|
||||||
{
|
|
||||||
QString settingsKey = GetExternalLinkWarningKey();
|
|
||||||
settingsRegistry->Get(skipDialog, settingsKey.toStdString().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skipDialog)
|
if (!skipDialog)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#include <EngineInfo.h>
|
#include <EngineInfo.h>
|
||||||
#include <CreateProjectCtrl.h>
|
#include <CreateProjectCtrl.h>
|
||||||
#include <TagWidget.h>
|
#include <TagWidget.h>
|
||||||
|
|
||||||
|
#include <AzCore/Math/Uuid.h>
|
||||||
#include <AzQtComponents/Components/FlowLayout.h>
|
#include <AzQtComponents/Components/FlowLayout.h>
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
@@ -225,7 +227,7 @@ namespace O3DE::ProjectManager
|
|||||||
moreGemsLabel->setObjectName("moreGems");
|
moreGemsLabel->setObjectName("moreGems");
|
||||||
templateDetailsLayout->addWidget(moreGemsLabel);
|
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->setObjectName("browseCatalog");
|
||||||
browseCatalogLabel->setWordWrap(true);
|
browseCatalogLabel->setWordWrap(true);
|
||||||
templateDetailsLayout->addWidget(browseCatalogLabel);
|
templateDetailsLayout->addWidget(browseCatalogLabel);
|
||||||
|
|||||||
@@ -9,9 +9,7 @@
|
|||||||
#include <ProjectBuilderController.h>
|
#include <ProjectBuilderController.h>
|
||||||
#include <ProjectBuilderWorker.h>
|
#include <ProjectBuilderWorker.h>
|
||||||
#include <ProjectButtonWidget.h>
|
#include <ProjectButtonWidget.h>
|
||||||
#include <ProjectManagerSettings.h>
|
#include <SettingsInterface.h>
|
||||||
|
|
||||||
#include <AzCore/Settings/SettingsRegistry.h>
|
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
@@ -29,14 +27,8 @@ namespace O3DE::ProjectManager
|
|||||||
m_worker = new ProjectBuilderWorker(m_projectInfo);
|
m_worker = new ProjectBuilderWorker(m_projectInfo);
|
||||||
m_worker->moveToThread(&m_workerThread);
|
m_worker->moveToThread(&m_workerThread);
|
||||||
|
|
||||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
// Remove key here in case Project Manager crashed while building because that causes HandleResults to not be called
|
||||||
if (settingsRegistry)
|
SettingsInterface::Get()->SetProjectBuiltSuccessfully(m_projectInfo, false);
|
||||||
{
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater);
|
connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater);
|
||||||
connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject);
|
connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject);
|
||||||
@@ -91,8 +83,6 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
void ProjectBuilderController::HandleResults(const QString& result)
|
void ProjectBuilderController::HandleResults(const QString& result)
|
||||||
{
|
{
|
||||||
QString settingsKey = GetProjectBuiltSuccessfullyKey(m_projectInfo.m_projectName);
|
|
||||||
|
|
||||||
if (!result.isEmpty())
|
if (!result.isEmpty())
|
||||||
{
|
{
|
||||||
if (result.contains(tr("log")))
|
if (result.contains(tr("log")))
|
||||||
@@ -122,12 +112,7 @@ namespace O3DE::ProjectManager
|
|||||||
emit NotifyBuildProject(m_projectInfo);
|
emit NotifyBuildProject(m_projectInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
SettingsInterface::Get()->SetProjectBuiltSuccessfully(m_projectInfo, false);
|
||||||
if (settingsRegistry)
|
|
||||||
{
|
|
||||||
settingsRegistry->Remove(settingsKey.toStdString().c_str());
|
|
||||||
SaveProjectManagerSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
emit Done(false);
|
emit Done(false);
|
||||||
return;
|
return;
|
||||||
@@ -136,12 +121,7 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
m_projectInfo.m_buildFailed = false;
|
m_projectInfo.m_buildFailed = false;
|
||||||
|
|
||||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
SettingsInterface::Get()->SetProjectBuiltSuccessfully(m_projectInfo, true);
|
||||||
if (settingsRegistry)
|
|
||||||
{
|
|
||||||
settingsRegistry->Set(settingsKey.toStdString().c_str(), true);
|
|
||||||
SaveProjectManagerSettings();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit Done(true);
|
emit Done(true);
|
||||||
|
|||||||
@@ -9,14 +9,13 @@
|
|||||||
#include <ProjectInfo.h>
|
#include <ProjectInfo.h>
|
||||||
#include <ProjectManagerDefs.h>
|
#include <ProjectManagerDefs.h>
|
||||||
|
|
||||||
#include <QDir>
|
|
||||||
|
|
||||||
namespace O3DE::ProjectManager
|
namespace O3DE::ProjectManager
|
||||||
{
|
{
|
||||||
ProjectInfo::ProjectInfo(
|
ProjectInfo::ProjectInfo(
|
||||||
const QString& path,
|
const QString& path,
|
||||||
const QString& projectName,
|
const QString& projectName,
|
||||||
const QString& displayName,
|
const QString& displayName,
|
||||||
|
const QString& id,
|
||||||
const QString& origin,
|
const QString& origin,
|
||||||
const QString& summary,
|
const QString& summary,
|
||||||
const QString& iconPath,
|
const QString& iconPath,
|
||||||
@@ -26,6 +25,7 @@ namespace O3DE::ProjectManager
|
|||||||
: m_path(path)
|
: m_path(path)
|
||||||
, m_projectName(projectName)
|
, m_projectName(projectName)
|
||||||
, m_displayName(displayName)
|
, m_displayName(displayName)
|
||||||
|
, m_id(id)
|
||||||
, m_origin(origin)
|
, m_origin(origin)
|
||||||
, m_summary(summary)
|
, m_summary(summary)
|
||||||
, m_iconPath(iconPath)
|
, m_iconPath(iconPath)
|
||||||
@@ -49,6 +49,10 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (m_id != rhs.m_id)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (m_origin != rhs.m_origin)
|
if (m_origin != rhs.m_origin)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -80,7 +84,7 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
bool ProjectInfo::IsValid() const
|
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
|
const QString& ProjectInfo::GetProjectDisplayName() const
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if !defined(Q_MOC_RUN)
|
#if !defined(Q_MOC_RUN)
|
||||||
#include <AzCore/Math/Uuid.h>
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@@ -26,6 +25,7 @@ namespace O3DE::ProjectManager
|
|||||||
const QString& path,
|
const QString& path,
|
||||||
const QString& projectName,
|
const QString& projectName,
|
||||||
const QString& displayName,
|
const QString& displayName,
|
||||||
|
const QString& id,
|
||||||
const QString& origin,
|
const QString& origin,
|
||||||
const QString& summary,
|
const QString& summary,
|
||||||
const QString& iconPath,
|
const QString& iconPath,
|
||||||
@@ -45,6 +45,7 @@ namespace O3DE::ProjectManager
|
|||||||
// From project.json
|
// From project.json
|
||||||
QString m_projectName;
|
QString m_projectName;
|
||||||
QString m_displayName;
|
QString m_displayName;
|
||||||
|
QString m_id;
|
||||||
QString m_origin;
|
QString m_origin;
|
||||||
QString m_summary;
|
QString m_summary;
|
||||||
QString m_iconPath;
|
QString m_iconPath;
|
||||||
|
|||||||
@@ -1,59 +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 <ProjectManagerSettings.h>
|
|
||||||
|
|
||||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
|
||||||
#include <AzCore/IO/ByteContainerStream.h>
|
|
||||||
#include <AzCore/Utils/Utils.h>
|
|
||||||
|
|
||||||
namespace O3DE::ProjectManager
|
|
||||||
{
|
|
||||||
void 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
QString GetProjectBuiltSuccessfullyKey(const QString& projectName)
|
|
||||||
{
|
|
||||||
return QString("%1/Projects/%2/BuiltSuccessfully").arg(ProjectManagerKeyPrefix).arg(projectName);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString GetExternalLinkWarningKey()
|
|
||||||
{
|
|
||||||
return QString("%1/SkipExternalLinkWarning").arg(ProjectManagerKeyPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +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 <QString>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace O3DE::ProjectManager
|
|
||||||
{
|
|
||||||
static constexpr char ProjectManagerKeyPrefix[] = "/O3DE/ProjectManager";
|
|
||||||
|
|
||||||
void SaveProjectManagerSettings();
|
|
||||||
QString GetProjectBuiltSuccessfullyKey(const QString& projectName);
|
|
||||||
QString GetExternalLinkWarningKey();
|
|
||||||
}
|
|
||||||
@@ -149,7 +149,7 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
void ProjectSettingsScreen::OnProjectPathUpdated()
|
void ProjectSettingsScreen::OnProjectPathUpdated()
|
||||||
{
|
{
|
||||||
Validate();
|
ValidateProjectName() && ValidateProjectPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProjectSettingsScreen::Validate()
|
bool ProjectSettingsScreen::Validate()
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <ProjectUtils.h>
|
#include <ProjectUtils.h>
|
||||||
#include <ProjectBuilderController.h>
|
#include <ProjectBuilderController.h>
|
||||||
#include <ScreensCtrl.h>
|
#include <ScreensCtrl.h>
|
||||||
#include <ProjectManagerSettings.h>
|
#include <SettingsInterface.h>
|
||||||
|
|
||||||
#include <AzQtComponents/Components/FlowLayout.h>
|
#include <AzQtComponents/Components/FlowLayout.h>
|
||||||
#include <AzCore/Platform.h>
|
#include <AzCore/Platform.h>
|
||||||
@@ -291,13 +291,9 @@ namespace O3DE::ProjectManager
|
|||||||
// Check whether project manager has successfully built the project
|
// Check whether project manager has successfully built the project
|
||||||
if (currentButton)
|
if (currentButton)
|
||||||
{
|
{
|
||||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
|
||||||
bool projectBuiltSuccessfully = false;
|
bool projectBuiltSuccessfully = false;
|
||||||
if (settingsRegistry)
|
SettingsInterface::Get()->GetProjectBuiltSuccessfully(projectBuiltSuccessfully, project);
|
||||||
{
|
|
||||||
QString settingsKey = GetProjectBuiltSuccessfullyKey(project.m_projectName);
|
|
||||||
settingsRegistry->Get(projectBuiltSuccessfully, settingsKey.toStdString().c_str());
|
|
||||||
}
|
|
||||||
if (!projectBuiltSuccessfully)
|
if (!projectBuiltSuccessfully)
|
||||||
{
|
{
|
||||||
currentButton->ShowBuildRequired();
|
currentButton->ShowBuildRequired();
|
||||||
|
|||||||
@@ -729,9 +729,9 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
auto createProjectResult = m_engineTemplate.attr("create_project")(
|
auto createProjectResult = m_engineTemplate.attr("create_project")(
|
||||||
projectPath,
|
projectPath,
|
||||||
QString_To_Py_String(projectInfo.m_projectName),
|
QString_To_Py_String(projectInfo.m_projectName), // project_path
|
||||||
QString_To_Py_Path(projectTemplatePath)
|
QString_To_Py_Path(projectTemplatePath) // template_path
|
||||||
);
|
);
|
||||||
if (createProjectResult.cast<int>() == 0)
|
if (createProjectResult.cast<int>() == 0)
|
||||||
{
|
{
|
||||||
createdProjectInfo = ProjectInfoFromPath(projectPath);
|
createdProjectInfo = ProjectInfoFromPath(projectPath);
|
||||||
@@ -864,6 +864,7 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
projectInfo.m_projectName = Py_To_String(projectData["project_name"]);
|
projectInfo.m_projectName = Py_To_String(projectData["project_name"]);
|
||||||
projectInfo.m_displayName = Py_To_String_Optional(projectData, "display_name", projectInfo.m_projectName);
|
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_origin = Py_To_String_Optional(projectData, "origin", projectInfo.m_origin);
|
||||||
projectInfo.m_summary = Py_To_String_Optional(projectData, "summary", projectInfo.m_summary);
|
projectInfo.m_summary = Py_To_String_Optional(projectData, "summary", projectInfo.m_summary);
|
||||||
projectInfo.m_iconPath = Py_To_String_Optional(projectData, "icon", ProjectPreviewImagePath);
|
projectInfo.m_iconPath = Py_To_String_Optional(projectData, "icon", ProjectPreviewImagePath);
|
||||||
@@ -968,6 +969,7 @@ namespace O3DE::ProjectManager
|
|||||||
QString_To_Py_Path(projectInfo.m_path),
|
QString_To_Py_Path(projectInfo.m_path),
|
||||||
pybind11::none(), // proj_name not used
|
pybind11::none(), // proj_name not used
|
||||||
QString_To_Py_String(projectInfo.m_projectName),
|
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_origin),
|
||||||
QString_To_Py_String(projectInfo.m_displayName),
|
QString_To_Py_String(projectInfo.m_displayName),
|
||||||
QString_To_Py_String(projectInfo.m_summary),
|
QString_To_Py_String(projectInfo.m_summary),
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* 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 <Settings.h>
|
||||||
|
|
||||||
|
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||||
|
#include <AzCore/IO/ByteContainerStream.h>
|
||||||
|
#include <AzCore/Utils/Utils.h>
|
||||||
|
|
||||||
|
namespace O3DE::ProjectManager
|
||||||
|
{
|
||||||
|
Settings::Settings(bool saveToDisk)
|
||||||
|
: m_saveToDisk(saveToDisk)
|
||||||
|
{
|
||||||
|
m_settingsRegistry = AZ::SettingsRegistry::Get();
|
||||||
|
|
||||||
|
AZ_Assert(m_settingsRegistry, "Failed to create Settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::OnSettingsChanged()
|
||||||
|
{
|
||||||
|
if (m_saveToDisk)
|
||||||
|
{
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
OnSettingsChanged();
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Settings::Set(const QString& settingsKey, bool settingsValue)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
success = m_settingsRegistry->Set(settingsKey.toStdString().c_str(), settingsValue);
|
||||||
|
OnSettingsChanged();
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Settings::Remove(const QString& settingsKey)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
success = m_settingsRegistry->Remove(settingsKey.toStdString().c_str());
|
||||||
|
OnSettingsChanged();
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
OnSettingsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<AZStd::string>& result)
|
||||||
|
{
|
||||||
|
return m_settingsRegistry->GetObject<AZStd::set<AZStd::string>>(result, ProjectsBuiltSuccessfullyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Settings::GetProjectBuiltSuccessfully(bool& result, const ProjectInfo& projectInfo)
|
||||||
|
{
|
||||||
|
AZStd::set<AZStd::string> 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<AZStd::string> 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<AZStd::set<AZStd::string>>(ProjectsBuiltSuccessfullyKey, builtPathsResult);
|
||||||
|
OnSettingsChanged();
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace O3DE::ProjectManager
|
||||||
@@ -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 <SettingsInterface.h>
|
||||||
|
|
||||||
|
#include <AzCore/std/string/string.h>
|
||||||
|
#include <AzCore/std/containers/set.h>
|
||||||
|
|
||||||
|
namespace AZ
|
||||||
|
{
|
||||||
|
class SettingsRegistryInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace O3DE::ProjectManager
|
||||||
|
{
|
||||||
|
class Settings
|
||||||
|
: public SettingsInterface::Registrar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Settings(bool saveToDisk = true);
|
||||||
|
|
||||||
|
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:
|
||||||
|
void Save();
|
||||||
|
void OnSettingsChanged();
|
||||||
|
|
||||||
|
bool GetBuiltSuccessfullyPaths(AZStd::set<AZStd::string>& result);
|
||||||
|
|
||||||
|
bool m_saveToDisk;
|
||||||
|
AZ::SettingsRegistryInterface* m_settingsRegistry = nullptr;
|
||||||
|
};
|
||||||
|
} // namespace O3DE::ProjectManager
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* 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 <ProjectInfo.h>
|
||||||
|
|
||||||
|
#include <AzCore/EBus/EBus.h>
|
||||||
|
#include <AzCore/Interface/Interface.h>
|
||||||
|
|
||||||
|
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/SuccessfulBuildPaths";
|
||||||
|
|
||||||
|
ISettings() = default;
|
||||||
|
virtual ~ISettings() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
using SettingsInterface = AZ::Interface<ISettings>;
|
||||||
|
} // namespace O3DE::ProjectManager
|
||||||
@@ -16,8 +16,7 @@
|
|||||||
#include <UpdateProjectSettingsScreen.h>
|
#include <UpdateProjectSettingsScreen.h>
|
||||||
#include <ProjectUtils.h>
|
#include <ProjectUtils.h>
|
||||||
#include <DownloadController.h>
|
#include <DownloadController.h>
|
||||||
#include <ProjectManagerSettings.h>
|
#include <SettingsInterface.h>
|
||||||
#include <AzCore/Settings/SettingsRegistry.h>
|
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
@@ -306,17 +305,11 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
if (newProjectSettings.m_projectName != m_projectInfo.m_projectName)
|
if (newProjectSettings.m_projectName != m_projectInfo.m_projectName)
|
||||||
{
|
{
|
||||||
// update reg key
|
// Remove project build successfully paths for both old and new project names
|
||||||
QString oldSettingsKey = GetProjectBuiltSuccessfullyKey(m_projectInfo.m_projectName);
|
// because a full rebuild is required when moving projects
|
||||||
QString newSettingsKey = GetProjectBuiltSuccessfullyKey(newProjectSettings.m_projectName);
|
auto settings = SettingsInterface::Get();
|
||||||
|
settings->SetProjectBuiltSuccessfully(m_projectInfo, false);
|
||||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
settings->SetProjectBuiltSuccessfully(newProjectSettings, false);
|
||||||
bool projectBuiltSuccessfully = false;
|
|
||||||
if (settingsRegistry && settingsRegistry->Get(projectBuiltSuccessfully, oldSettingsKey.toStdString().c_str()))
|
|
||||||
{
|
|
||||||
settingsRegistry->Set(newSettingsKey.toStdString().c_str(), projectBuiltSuccessfully);
|
|
||||||
SaveProjectManagerSettings();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newProjectSettings.m_newPreviewImagePath.isEmpty())
|
if (!newProjectSettings.m_newPreviewImagePath.isEmpty())
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
namespace O3DE::ProjectManager
|
namespace O3DE::ProjectManager
|
||||||
{
|
{
|
||||||
@@ -31,12 +32,10 @@ namespace O3DE::ProjectManager
|
|||||||
m_verticalLayout->addWidget(m_projectPreview);
|
m_verticalLayout->addWidget(m_projectPreview);
|
||||||
|
|
||||||
QVBoxLayout* previewExtrasLayout = new QVBoxLayout(this);
|
QVBoxLayout* previewExtrasLayout = new QVBoxLayout(this);
|
||||||
previewExtrasLayout->setAlignment(Qt::AlignLeft);
|
previewExtrasLayout->setAlignment(Qt::AlignTop);
|
||||||
previewExtrasLayout->setContentsMargins(50, 0, 0, 0);
|
previewExtrasLayout->setContentsMargins(30, 45, 30, 0);
|
||||||
|
|
||||||
QLabel* projectPreviewLabel = new QLabel(tr("Select an image (PNG). Minimum %1 x %2 pixels.")
|
QLabel* projectPreviewLabel = new QLabel(tr("Project Preview"));
|
||||||
.arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight)));
|
|
||||||
projectPreviewLabel->setObjectName("projectPreviewLabel");
|
|
||||||
previewExtrasLayout->addWidget(projectPreviewLabel);
|
previewExtrasLayout->addWidget(projectPreviewLabel);
|
||||||
|
|
||||||
m_projectPreviewImage = new QLabel(this);
|
m_projectPreviewImage = new QLabel(this);
|
||||||
@@ -44,7 +43,53 @@ namespace O3DE::ProjectManager
|
|||||||
m_projectPreviewImage->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
m_projectPreviewImage->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||||
previewExtrasLayout->addWidget(m_projectPreviewImage);
|
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, &UpdateProjectSettingsScreen::UpdateAdvancedSettingsCollapseState);
|
||||||
|
advancedCollapseLayout->addWidget(m_advancedSettingsCollapseButton);
|
||||||
|
|
||||||
|
// Category title
|
||||||
|
QLabel* advancedLabel = new QLabel(tr("Advanced Settings"));
|
||||||
|
advancedLabel->setObjectName("projectSettingsSectionTitle");
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateAdvancedSettingsCollapseState();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectManagerScreen UpdateProjectSettingsScreen::GetScreenEnum()
|
ProjectManagerScreen UpdateProjectSettingsScreen::GetScreenEnum()
|
||||||
@@ -56,6 +101,7 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
m_projectInfo.m_displayName = m_projectName->lineEdit()->text();
|
m_projectInfo.m_displayName = m_projectName->lineEdit()->text();
|
||||||
m_projectInfo.m_path = m_projectPath->lineEdit()->text();
|
m_projectInfo.m_path = m_projectPath->lineEdit()->text();
|
||||||
|
m_projectInfo.m_id = m_projectId->lineEdit()->text();
|
||||||
|
|
||||||
if (m_userChangedPreview)
|
if (m_userChangedPreview)
|
||||||
{
|
{
|
||||||
@@ -70,8 +116,9 @@ namespace O3DE::ProjectManager
|
|||||||
m_projectInfo = projectInfo;
|
m_projectInfo = projectInfo;
|
||||||
|
|
||||||
m_projectName->lineEdit()->setText(projectInfo.GetProjectDisplayName());
|
m_projectName->lineEdit()->setText(projectInfo.GetProjectDisplayName());
|
||||||
|
|
||||||
m_projectPath->lineEdit()->setText(projectInfo.m_path);
|
m_projectPath->lineEdit()->setText(projectInfo.m_path);
|
||||||
|
m_projectId->lineEdit()->setText(projectInfo.m_id);
|
||||||
|
|
||||||
UpdateProjectPreviewPath();
|
UpdateProjectPreviewPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +135,7 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
bool UpdateProjectSettingsScreen::Validate()
|
bool UpdateProjectSettingsScreen::Validate()
|
||||||
{
|
{
|
||||||
return ProjectSettingsScreen::Validate() && ValidateProjectPreview();
|
return ProjectSettingsScreen::Validate() && ValidateProjectPreview() && ValidateProjectId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateProjectSettingsScreen::ResetProjectPreviewPath()
|
void UpdateProjectSettingsScreen::ResetProjectPreviewPath()
|
||||||
@@ -106,6 +153,11 @@ namespace O3DE::ProjectManager
|
|||||||
QPixmap(m_projectPreview->lineEdit()->text()).scaled(m_projectPreviewImage->size(), Qt::KeepAspectRatioByExpanding));
|
QPixmap(m_projectPreview->lineEdit()->text()).scaled(m_projectPreviewImage->size(), Qt::KeepAspectRatioByExpanding));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateProjectSettingsScreen::OnProjectIdUpdated()
|
||||||
|
{
|
||||||
|
ValidateProjectId();
|
||||||
|
}
|
||||||
|
|
||||||
bool UpdateProjectSettingsScreen::ValidateProjectPath()
|
bool UpdateProjectSettingsScreen::ValidateProjectPath()
|
||||||
{
|
{
|
||||||
bool projectPathIsValid = true;
|
bool projectPathIsValid = true;
|
||||||
@@ -155,4 +207,31 @@ namespace O3DE::ProjectManager
|
|||||||
return projectPreviewIsValid;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
} // namespace O3DE::ProjectManager
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||||
|
|
||||||
namespace O3DE::ProjectManager
|
namespace O3DE::ProjectManager
|
||||||
{
|
{
|
||||||
@@ -33,16 +34,27 @@ namespace O3DE::ProjectManager
|
|||||||
public slots:
|
public slots:
|
||||||
void UpdateProjectPreviewPath();
|
void UpdateProjectPreviewPath();
|
||||||
void PreviewPathChanged();
|
void PreviewPathChanged();
|
||||||
|
void OnProjectIdUpdated();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ValidateProjectPath() override;
|
bool ValidateProjectPath() override;
|
||||||
virtual bool ValidateProjectPreview();
|
virtual bool ValidateProjectPreview();
|
||||||
|
bool ValidateProjectId();
|
||||||
|
|
||||||
|
inline constexpr static int s_collapseButtonSize = 24;
|
||||||
|
|
||||||
FormBrowseEditWidget* m_projectPreview;
|
FormBrowseEditWidget* m_projectPreview;
|
||||||
QLabel* m_projectPreviewImage;
|
QLabel* m_projectPreviewImage;
|
||||||
|
FormLineEditWidget* m_projectId;
|
||||||
|
|
||||||
|
QPushButton* m_advancedSettingsCollapseButton = nullptr;
|
||||||
|
QWidget* m_advancedSettingWidget = nullptr;
|
||||||
|
|
||||||
ProjectInfo m_projectInfo;
|
ProjectInfo m_projectInfo;
|
||||||
bool m_userChangedPreview; //! Did the user change the project preview path
|
bool m_userChangedPreview; //! Did the user change the project preview path
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void UpdateAdvancedSettingsCollapseState();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace O3DE::ProjectManager
|
} // namespace O3DE::ProjectManager
|
||||||
|
|||||||
@@ -58,8 +58,6 @@ set(FILES
|
|||||||
Source/CreateProjectCtrl.cpp
|
Source/CreateProjectCtrl.cpp
|
||||||
Source/UpdateProjectCtrl.h
|
Source/UpdateProjectCtrl.h
|
||||||
Source/UpdateProjectCtrl.cpp
|
Source/UpdateProjectCtrl.cpp
|
||||||
Source/ProjectManagerSettings.h
|
|
||||||
Source/ProjectManagerSettings.cpp
|
|
||||||
Source/ProjectsScreen.h
|
Source/ProjectsScreen.h
|
||||||
Source/ProjectsScreen.cpp
|
Source/ProjectsScreen.cpp
|
||||||
Source/ProjectSettingsScreen.h
|
Source/ProjectSettingsScreen.h
|
||||||
@@ -72,6 +70,9 @@ set(FILES
|
|||||||
Source/ProjectButtonWidget.cpp
|
Source/ProjectButtonWidget.cpp
|
||||||
Source/ScreenHeaderWidget.h
|
Source/ScreenHeaderWidget.h
|
||||||
Source/ScreenHeaderWidget.cpp
|
Source/ScreenHeaderWidget.cpp
|
||||||
|
Source/Settings.h
|
||||||
|
Source/Settings.cpp
|
||||||
|
Source/SettingsInterface.h
|
||||||
Source/LinkWidget.h
|
Source/LinkWidget.h
|
||||||
Source/LinkWidget.cpp
|
Source/LinkWidget.cpp
|
||||||
Source/TagWidget.h
|
Source/TagWidget.h
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ set(FILES
|
|||||||
Resources/ProjectManager.qrc
|
Resources/ProjectManager.qrc
|
||||||
Resources/ProjectManager.qss
|
Resources/ProjectManager.qss
|
||||||
tests/ApplicationTests.cpp
|
tests/ApplicationTests.cpp
|
||||||
tests/PythonBindingsTests.cpp
|
|
||||||
tests/GemCatalogTests.cpp
|
tests/GemCatalogTests.cpp
|
||||||
|
tests/SettingsTests.cpp
|
||||||
|
tests/PythonBindingsTests.cpp
|
||||||
tests/main.cpp
|
tests/main.cpp
|
||||||
tests/UtilsTests.cpp
|
tests/UtilsTests.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* 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 <AzCore/Serialization/SerializeContext.h>
|
||||||
|
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||||
|
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
||||||
|
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
|
||||||
|
#include <AzCore/UnitTest/TestTypes.h>
|
||||||
|
#include <AzTest/Utils.h>
|
||||||
|
|
||||||
|
#include <Settings.h>
|
||||||
|
|
||||||
|
namespace O3DE::ProjectManager
|
||||||
|
{
|
||||||
|
class SettingsTests
|
||||||
|
: public ::UnitTest::ScopedAllocatorSetupFixture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~SettingsTests() override = default;
|
||||||
|
void SetUp() override
|
||||||
|
{
|
||||||
|
UnitTest::ScopedAllocatorSetupFixture::SetUp();
|
||||||
|
|
||||||
|
m_registry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
|
||||||
|
// 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<AZ::SerializeContext>();
|
||||||
|
m_registrationContext = AZStd::make_unique<AZ::JsonRegistrationContext>();
|
||||||
|
|
||||||
|
m_registry->SetContext(m_serializeContext.get());
|
||||||
|
m_registry->SetContext(m_registrationContext.get());
|
||||||
|
|
||||||
|
AZ::JsonSystemComponent::Reflect(m_registrationContext.get());
|
||||||
|
|
||||||
|
m_serializeContext->RegisterGenericType<AZStd::set<AZStd::string>>();
|
||||||
|
|
||||||
|
m_settings = AZStd::make_unique<Settings>(/*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();
|
||||||
|
|
||||||
|
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:
|
||||||
|
AZStd::unique_ptr<Settings> m_settings;
|
||||||
|
const QString m_settingsPath = "/Testing/TestKey";
|
||||||
|
const QString m_newSettingsPath = "/Testing/NewTestKey";
|
||||||
|
ProjectInfo m_projectInfo;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AZ::SettingsRegistryInterface* m_oldSettingsRegistry = nullptr;
|
||||||
|
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_registry;
|
||||||
|
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
|
||||||
|
AZStd::unique_ptr<AZ::JsonRegistrationContext> m_registrationContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_GetUnsetPathBool_ReturnsFalse)
|
||||||
|
{
|
||||||
|
bool settingsResult = false;
|
||||||
|
EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
EXPECT_FALSE(settingsResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_SetAndGetValueBool_Success)
|
||||||
|
{
|
||||||
|
bool settingsResult = false;
|
||||||
|
EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_settings->Set(m_settingsPath, true));
|
||||||
|
|
||||||
|
settingsResult = false;
|
||||||
|
EXPECT_TRUE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
EXPECT_TRUE(settingsResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_GetUnsetPathString_ReturnsFalse)
|
||||||
|
{
|
||||||
|
QString settingsResult;
|
||||||
|
EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
EXPECT_TRUE(settingsResult.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_SetAndGetValueString_Success)
|
||||||
|
{
|
||||||
|
QString settingsResult;
|
||||||
|
EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
|
||||||
|
QString settingsValue = "TestValue";
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue));
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
EXPECT_TRUE(settingsResult == settingsValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_CopyStringRemoveOriginal_SuccessAndRemovesOriginal)
|
||||||
|
{
|
||||||
|
QString settingsResult;
|
||||||
|
EXPECT_FALSE(m_settings->Get(settingsResult, m_newSettingsPath));
|
||||||
|
|
||||||
|
QString settingsValue = "TestValue";
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue));
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_settings->Copy(m_settingsPath, m_newSettingsPath, /*removeOrig*/ true));
|
||||||
|
|
||||||
|
// Check that old path value is removed
|
||||||
|
EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_settings->Get(settingsResult, m_newSettingsPath));
|
||||||
|
EXPECT_TRUE(settingsResult == settingsValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_RemoveProjectManagerKey_RemovesKey)
|
||||||
|
{
|
||||||
|
QString settingsResult;
|
||||||
|
EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
|
||||||
|
QString settingsValue = "TestValue";
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_settings->Set(m_settingsPath, settingsValue));
|
||||||
|
EXPECT_TRUE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_settings->Remove(m_settingsPath));
|
||||||
|
EXPECT_FALSE(m_settings->Get(settingsResult, m_settingsPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_GetUnsetBuildPath_ReturnsFalse)
|
||||||
|
{
|
||||||
|
bool buildResult = true;
|
||||||
|
EXPECT_FALSE(m_settings->GetProjectBuiltSuccessfully(buildResult, m_projectInfo));
|
||||||
|
EXPECT_FALSE(buildResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_SetProjectBuiltSuccessfully_ReturnsTrue)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(m_settings->SetProjectBuiltSuccessfully(m_projectInfo, true));
|
||||||
|
|
||||||
|
bool buildResult = false;
|
||||||
|
EXPECT_TRUE(m_settings->GetProjectBuiltSuccessfully(buildResult, m_projectInfo));
|
||||||
|
EXPECT_TRUE(buildResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTests, Settings_SetProjectBuiltUnsuccessfully_ReturnsFalse)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(m_settings->SetProjectBuiltSuccessfully(m_projectInfo, false));
|
||||||
|
|
||||||
|
bool buildResult = false;
|
||||||
|
EXPECT_TRUE(m_settings->GetProjectBuiltSuccessfully(buildResult, m_projectInfo));
|
||||||
|
EXPECT_FALSE(buildResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"project_name": "${Name}",
|
"project_name": "${Name}",
|
||||||
|
"project_id": "${ProjectId}",
|
||||||
"origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com",
|
"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",
|
"license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT",
|
||||||
"display_name": "${Name}",
|
"display_name": "${Name}",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"project_name": "${Name}",
|
"project_name": "${Name}",
|
||||||
|
"project_id": "${ProjectId}",
|
||||||
"origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com",
|
"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",
|
"license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT",
|
||||||
"display_name": "${Name}",
|
"display_name": "${Name}",
|
||||||
|
|||||||
@@ -86,7 +86,6 @@
|
|||||||
"Gems/WhiteBox"
|
"Gems/WhiteBox"
|
||||||
],
|
],
|
||||||
"projects": [
|
"projects": [
|
||||||
"AtomTest",
|
|
||||||
"AutomatedTesting"
|
"AutomatedTesting"
|
||||||
],
|
],
|
||||||
"templates": [
|
"templates": [
|
||||||
|
|||||||
@@ -1114,7 +1114,7 @@ def create_from_template(destination_path: pathlib.Path,
|
|||||||
try:
|
try:
|
||||||
template_json_data = json.load(s)
|
template_json_data = json.load(s)
|
||||||
except KeyError as e:
|
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
|
return 1
|
||||||
|
|
||||||
# read template name from the json
|
# read template name from the json
|
||||||
@@ -1339,7 +1339,8 @@ def create_project(project_path: pathlib.Path,
|
|||||||
no_register: bool = False,
|
no_register: bool = False,
|
||||||
system_component_class_id: str = None,
|
system_component_class_id: str = None,
|
||||||
editor_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,
|
Template instantiation specialization that makes all default assumptions for a Project template instantiation,
|
||||||
reducing the effort needed in instancing a project
|
reducing the effort needed in instancing a project
|
||||||
@@ -1367,6 +1368,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
|
:param editor_system_component_class_id: optionally specify a uuid for the editor system component class, default is
|
||||||
random uuid
|
random uuid
|
||||||
:param module_id: optionally specify a uuid for the module 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
|
:return: 0 for success or non 0 failure code
|
||||||
"""
|
"""
|
||||||
if template_name and template_path:
|
if template_name and template_path:
|
||||||
@@ -1406,7 +1408,7 @@ def create_project(project_path: pathlib.Path,
|
|||||||
try:
|
try:
|
||||||
template_json_data = json.load(s)
|
template_json_data = json.load(s)
|
||||||
except json.JSONDecodeError as e:
|
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
|
return 1
|
||||||
|
|
||||||
# read template name from the json
|
# read template name from the json
|
||||||
@@ -1578,6 +1580,12 @@ def create_project(project_path: pathlib.Path,
|
|||||||
replacements.append(("${NameLower}", project_name.lower()))
|
replacements.append(("${NameLower}", project_name.lower()))
|
||||||
replacements.append(("${SanitizedCppName}", sanitized_cpp_name))
|
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 -
|
# module id is a uuid with { and -
|
||||||
if module_id:
|
if module_id:
|
||||||
replacements.append(("${ModuleClassId}", module_id))
|
replacements.append(("${ModuleClassId}", module_id))
|
||||||
@@ -1785,7 +1793,7 @@ def create_gem(gem_path: pathlib.Path,
|
|||||||
try:
|
try:
|
||||||
template_json_data = json.load(s)
|
template_json_data = json.load(s)
|
||||||
except json.JSONDecodeError as e:
|
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
|
return 1
|
||||||
|
|
||||||
# read template name from the json
|
# read template name from the json
|
||||||
@@ -2123,7 +2131,8 @@ def _run_create_project(args: argparse) -> int:
|
|||||||
args.no_register,
|
args.no_register,
|
||||||
args.system_component_class_id,
|
args.system_component_class_id,
|
||||||
args.editor_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:
|
def _run_create_gem(args: argparse) -> int:
|
||||||
@@ -2417,6 +2426,9 @@ def add_args(subparsers) -> None:
|
|||||||
create_project_subparser.add_argument('--module-id', type=uuid.UUID, required=False,
|
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'
|
help='The uuid you want to associate with the module, default is a random'
|
||||||
' uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}')
|
' 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,
|
create_project_subparser.add_argument('-f', '--force', action='store_true', default=False,
|
||||||
help='Copies over instantiated template directory even if it exist.')
|
help='Copies over instantiated template directory even if it exist.')
|
||||||
create_project_subparser.add_argument('--no-register', action='store_true', default=False,
|
create_project_subparser.add_argument('--no-register', action='store_true', default=False,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ def get_project_props(name: str = None, path: pathlib.Path = None) -> dict:
|
|||||||
def edit_project_props(proj_path: pathlib.Path = None,
|
def edit_project_props(proj_path: pathlib.Path = None,
|
||||||
proj_name: str = None,
|
proj_name: str = None,
|
||||||
new_name: str = None,
|
new_name: str = None,
|
||||||
|
new_id: str = None,
|
||||||
new_origin: str = None,
|
new_origin: str = None,
|
||||||
new_display: str = None,
|
new_display: str = None,
|
||||||
new_summary: str = None,
|
new_summary: str = None,
|
||||||
@@ -42,14 +43,15 @@ def edit_project_props(proj_path: pathlib.Path = None,
|
|||||||
|
|
||||||
if not proj_json:
|
if not proj_json:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if new_origin:
|
|
||||||
proj_json['origin'] = new_origin
|
|
||||||
if new_name:
|
if new_name:
|
||||||
if not utils.validate_identifier(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}')
|
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
|
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:
|
if new_display:
|
||||||
proj_json['display_name'] = new_display
|
proj_json['display_name'] = new_display
|
||||||
if new_summary:
|
if new_summary:
|
||||||
@@ -80,6 +82,7 @@ def _edit_project_props(args: argparse) -> int:
|
|||||||
return edit_project_props(args.project_path,
|
return edit_project_props(args.project_path,
|
||||||
args.project_name,
|
args.project_name,
|
||||||
args.project_new_name,
|
args.project_new_name,
|
||||||
|
args.project_id,
|
||||||
args.project_origin,
|
args.project_origin,
|
||||||
args.project_display,
|
args.project_display,
|
||||||
args.project_summary,
|
args.project_summary,
|
||||||
@@ -98,6 +101,8 @@ def add_parser_args(parser):
|
|||||||
group = parser.add_argument_group('properties', 'arguments for modifying individual project properties.')
|
group = parser.add_argument_group('properties', 'arguments for modifying individual project properties.')
|
||||||
group.add_argument('-pnn', '--project-new-name', type=str, required=False,
|
group.add_argument('-pnn', '--project-new-name', type=str, required=False,
|
||||||
help='Sets the name for the project.')
|
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,
|
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).')
|
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,
|
group.add_argument('-pd', '--project-display', type=str, required=False,
|
||||||
|
|||||||
@@ -570,7 +570,7 @@ def remove_invalid_o3de_projects(manifest_path: pathlib.Path = None) -> int:
|
|||||||
result = 0
|
result = 0
|
||||||
|
|
||||||
for project in json_data.get('projects', []):
|
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.")
|
logger.warning(f"Project path {project} is invalid.")
|
||||||
# Attempt to unregister all invalid projects even if previous projects failed to unregister
|
# Attempt to unregister all invalid projects even if previous projects failed to unregister
|
||||||
# but combine the result codes of each command.
|
# but combine the result codes of each command.
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ This file validating o3de object json files
|
|||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
def valid_o3de_json_dict(json_data: dict, key: str) -> bool:
|
def valid_o3de_json_dict(json_data: dict, key: str) -> bool:
|
||||||
@@ -45,7 +46,7 @@ def valid_o3de_engine_json(file_name: str or pathlib.Path) -> bool:
|
|||||||
return True
|
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()
|
file_name = pathlib.Path(file_name).resolve()
|
||||||
if not file_name.is_file():
|
if not file_name.is_file():
|
||||||
return False
|
return False
|
||||||
@@ -54,8 +55,22 @@ def valid_o3de_project_json(file_name: str or pathlib.Path) -> bool:
|
|||||||
try:
|
try:
|
||||||
json_data = json.load(f)
|
json_data = json.load(f)
|
||||||
_ = json_data['project_name']
|
_ = json_data['project_name']
|
||||||
|
|
||||||
|
if not generate_uuid:
|
||||||
|
_ = json_data['project_id']
|
||||||
|
else:
|
||||||
|
test = json_data.get('project_id', 'No ID')
|
||||||
|
generate_new_id = test == 'No ID'
|
||||||
|
|
||||||
except (json.JSONDecodeError, KeyError):
|
except (json.JSONDecodeError, KeyError):
|
||||||
return False
|
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
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from o3de import project_properties
|
|||||||
TEST_PROJECT_JSON_PAYLOAD = '''
|
TEST_PROJECT_JSON_PAYLOAD = '''
|
||||||
{
|
{
|
||||||
"project_name": "TestProject",
|
"project_name": "TestProject",
|
||||||
|
"project_id": "{24114e69-306d-4de6-b3b4-4cb1a3eca58e}",
|
||||||
"origin": "The primary repo for TestProject goes here: i.e. http://www.mydomain.com",
|
"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",
|
"license": "What license TestProject uses goes here: i.e. https://opensource.org/licenses/MIT",
|
||||||
"display_name": "TestProject",
|
"display_name": "TestProject",
|
||||||
@@ -45,20 +46,20 @@ def init_project_json_data(request):
|
|||||||
|
|
||||||
@pytest.mark.usefixtures('init_project_json_data')
|
@pytest.mark.usefixtures('init_project_json_data')
|
||||||
class TestEditProjectProperties:
|
class TestEditProjectProperties:
|
||||||
@pytest.mark.parametrize("project_path, project_name, project_new_name, project_origin, project_display,\
|
@pytest.mark.parametrize("project_path, project_name, project_new_name, project_id, project_origin,\
|
||||||
project_summary, project_icon, add_tags, delete_tags,\
|
project_display, project_summary, project_icon,\
|
||||||
replace_tags, expected_result", [
|
add_tags, delete_tags, replace_tags, expected_result", [
|
||||||
pytest.param(pathlib.PurePath('E:/TestProject'),
|
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),
|
'B', 'D E F', 0),
|
||||||
pytest.param('',
|
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)
|
'B', 'D E F', 1)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
def test_edit_project_properties(self, project_path, project_name, project_new_name, project_origin, project_display,
|
def test_edit_project_properties(self, project_path, project_name, project_new_name, project_id, project_origin,
|
||||||
project_summary, project_icon, add_tags, delete_tags,
|
project_display, project_summary, project_icon, add_tags,
|
||||||
replace_tags, expected_result):
|
delete_tags, replace_tags, expected_result):
|
||||||
|
|
||||||
def get_project_json_data(project_name: str, project_path) -> dict:
|
def get_project_json_data(project_name: str, project_path) -> dict:
|
||||||
if not project_path:
|
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, \
|
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:
|
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,
|
result = project_properties.edit_project_props(project_path, project_name, project_new_name, project_id,
|
||||||
project_display, project_summary, project_icon,
|
project_origin, project_display, project_summary, project_icon,
|
||||||
add_tags, delete_tags, replace_tags)
|
add_tags, delete_tags, replace_tags)
|
||||||
assert result == expected_result
|
assert result == expected_result
|
||||||
if project_path:
|
if project_path:
|
||||||
assert self.project_json.data
|
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('origin', '') == project_origin
|
||||||
assert self.project_json.data.get('display_name', '') == project_display
|
assert self.project_json.data.get('display_name', '') == project_display
|
||||||
assert self.project_json.data.get('summary', '') == project_summary
|
assert self.project_json.data.get('summary', '') == project_summary
|
||||||
|
|||||||
Reference in New Issue
Block a user