Merge branch 'main' into ly-as-sdk/LYN-2948
# Conflicts: # Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json
This commit is contained in:
@@ -14,11 +14,17 @@
|
||||
#include <ScreensCtrl.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <NewProjectSettingsScreen.h>
|
||||
#include <ScreenHeaderWidget.h>
|
||||
#include <GemCatalog/GemCatalogScreen.h>
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include <QStackedWidget>
|
||||
#include <QLabel>
|
||||
#include <QSizePolicy>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
@@ -26,29 +32,34 @@ namespace O3DE::ProjectManager
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
setLayout(vLayout);
|
||||
vLayout->setContentsMargins(0,0,0,0);
|
||||
|
||||
m_screensCtrl = new ScreensCtrl();
|
||||
vLayout->addWidget(m_screensCtrl);
|
||||
m_header = new ScreenHeader(this);
|
||||
m_header->setTitle(tr("Create a New Project"));
|
||||
m_header->setSubTitle(tr("Enter Project Details"));
|
||||
connect(m_header->backButton(), &QPushButton::clicked, this, &CreateProjectCtrl::HandleBackButton);
|
||||
vLayout->addWidget(m_header);
|
||||
|
||||
m_stack = new QStackedWidget(this);
|
||||
m_stack->setObjectName("body");
|
||||
m_stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding));
|
||||
m_stack->addWidget(new NewProjectSettingsScreen());
|
||||
m_stack->addWidget(new GemCatalogScreen());
|
||||
vLayout->addWidget(m_stack);
|
||||
|
||||
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
|
||||
backNextButtons->setObjectName("footer");
|
||||
vLayout->addWidget(backNextButtons);
|
||||
|
||||
m_backButton = backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
|
||||
m_backButton->setProperty("secondary", true);
|
||||
m_nextButton = backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole);
|
||||
|
||||
connect(m_backButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleBackButton);
|
||||
connect(m_nextButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleNextButton);
|
||||
connect(m_backButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandleBackButton);
|
||||
connect(m_nextButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandleNextButton);
|
||||
|
||||
m_screensOrder =
|
||||
{
|
||||
ProjectManagerScreen::NewProjectSettings,
|
||||
ProjectManagerScreen::GemCatalog
|
||||
};
|
||||
m_screensCtrl->BuildScreens(m_screensOrder);
|
||||
m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::NewProjectSettings, false);
|
||||
|
||||
UpdateNextButtonText();
|
||||
Update();
|
||||
setLayout(vLayout);
|
||||
}
|
||||
|
||||
ProjectManagerScreen CreateProjectCtrl::GetScreenEnum()
|
||||
@@ -58,28 +69,20 @@ namespace O3DE::ProjectManager
|
||||
|
||||
void CreateProjectCtrl::HandleBackButton()
|
||||
{
|
||||
if (!m_screensCtrl->GotoPreviousScreen())
|
||||
if (m_stack->currentIndex() > 0)
|
||||
{
|
||||
emit GotoPreviousScreenRequest();
|
||||
m_stack->setCurrentIndex(m_stack->currentIndex() - 1);
|
||||
Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateNextButtonText();
|
||||
emit GotoPreviousScreenRequest();
|
||||
}
|
||||
}
|
||||
void CreateProjectCtrl::HandleNextButton()
|
||||
{
|
||||
ScreenWidget* currentScreen = m_screensCtrl->GetCurrentScreen();
|
||||
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
|
||||
ProjectManagerScreen screenEnum = currentScreen->GetScreenEnum();
|
||||
auto screenOrderIter = m_screensOrder.begin();
|
||||
for (; screenOrderIter != m_screensOrder.end(); ++screenOrderIter)
|
||||
{
|
||||
if (*screenOrderIter == screenEnum)
|
||||
{
|
||||
++screenOrderIter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (screenEnum == ProjectManagerScreen::NewProjectSettings)
|
||||
{
|
||||
@@ -97,10 +100,10 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
if (screenOrderIter != m_screensOrder.end())
|
||||
if (m_stack->currentIndex() != m_stack->count() - 1)
|
||||
{
|
||||
m_screensCtrl->ChangeToScreen(*screenOrderIter);
|
||||
UpdateNextButtonText();
|
||||
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
|
||||
Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -108,7 +111,7 @@ namespace O3DE::ProjectManager
|
||||
if (result.IsSuccess())
|
||||
{
|
||||
// adding gems is not implemented yet because we don't know what targets to add or how to add them
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::Projects);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -117,14 +120,21 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::UpdateNextButtonText()
|
||||
void CreateProjectCtrl::Update()
|
||||
{
|
||||
QString nextButtonText = tr("Next");
|
||||
if (m_screensCtrl->GetCurrentScreen()->GetScreenEnum() == ProjectManagerScreen::GemCatalog)
|
||||
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
|
||||
if (currentScreen && currentScreen->GetScreenEnum() == ProjectManagerScreen::GemCatalog)
|
||||
{
|
||||
nextButtonText = tr("Create Project");
|
||||
m_header->setTitle(tr("Create Project"));
|
||||
m_header->setSubTitle(tr("Configure project with Gems"));
|
||||
m_nextButton->setText(tr("Create Project"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_header->setTitle(tr("Create Project"));
|
||||
m_header->setSubTitle(tr("Enter Project Details"));
|
||||
m_nextButton->setText(tr("Next"));
|
||||
}
|
||||
m_nextButton->setText(nextButtonText);
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -12,15 +12,18 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "ProjectInfo.h"
|
||||
#include <ScreenWidget.h>
|
||||
#include <ScreensCtrl.h>
|
||||
#include <QPushButton>
|
||||
#include <ProjectInfo.h>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QStackedWidget)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
QT_FORWARD_DECLARE_CLASS(ScreenHeader)
|
||||
|
||||
class CreateProjectCtrl
|
||||
: public ScreenWidget
|
||||
{
|
||||
@@ -34,12 +37,13 @@ namespace O3DE::ProjectManager
|
||||
void HandleNextButton();
|
||||
|
||||
private:
|
||||
void UpdateNextButtonText();
|
||||
void Update();
|
||||
|
||||
QStackedWidget* m_stack;
|
||||
ScreenHeader* m_header;
|
||||
|
||||
ScreensCtrl* m_screensCtrl;
|
||||
QPushButton* m_backButton;
|
||||
QPushButton* m_nextButton;
|
||||
QVector<ProjectManagerScreen> m_screensOrder;
|
||||
|
||||
QString m_projectTemplatePath;
|
||||
ProjectInfo m_projectInfo;
|
||||
|
||||
@@ -82,6 +82,16 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::EngineSettings;
|
||||
}
|
||||
|
||||
QString EngineSettingsScreen::GetTabText()
|
||||
{
|
||||
return tr("Engine");
|
||||
}
|
||||
|
||||
bool EngineSettingsScreen::IsTab()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void EngineSettingsScreen::OnTextChanged()
|
||||
{
|
||||
// save engine settings
|
||||
|
||||
@@ -26,7 +26,10 @@ namespace O3DE::ProjectManager
|
||||
public:
|
||||
explicit EngineSettingsScreen(QWidget* parent = nullptr);
|
||||
~EngineSettingsScreen() = default;
|
||||
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
QString GetTabText() override;
|
||||
bool IsTab() override;
|
||||
|
||||
protected slots:
|
||||
void OnTextChanged();
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <FirstTimeUseScreen.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QIcon>
|
||||
#include <QSpacerItem>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
FirstTimeUseScreen::FirstTimeUseScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
setLayout(vLayout);
|
||||
vLayout->setContentsMargins(s_contentMargins, s_contentMargins, s_contentMargins, s_contentMargins);
|
||||
|
||||
QLabel* titleLabel = new QLabel(this);
|
||||
titleLabel->setText(tr("Ready. Set. Create!"));
|
||||
titleLabel->setStyleSheet("font-size: 60px");
|
||||
vLayout->addWidget(titleLabel);
|
||||
|
||||
QLabel* introLabel = new QLabel(this);
|
||||
introLabel->setTextFormat(Qt::AutoText);
|
||||
introLabel->setText(tr("<html><head/><body><p>Welcome to O3DE! Start something new by creating a project. Not sure what to create? </p><p>Explore what\342\200\231s available by downloading our sample project.</p></body></html>"));
|
||||
introLabel->setStyleSheet("font-size: 14px");
|
||||
vLayout->addWidget(introLabel);
|
||||
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout();
|
||||
buttonLayout->setSpacing(s_buttonSpacing);
|
||||
|
||||
m_createProjectButton = CreateLargeBoxButton(QIcon(":/Add.svg"), tr("Create Project"), this);
|
||||
m_createProjectButton->setIconSize(QSize(s_iconSize, s_iconSize));
|
||||
buttonLayout->addWidget(m_createProjectButton);
|
||||
|
||||
m_addProjectButton = CreateLargeBoxButton(QIcon(":/Select_Folder.svg"), tr("Add a Project"), this);
|
||||
m_addProjectButton->setIconSize(QSize(s_iconSize, s_iconSize));
|
||||
buttonLayout->addWidget(m_addProjectButton);
|
||||
|
||||
QSpacerItem* buttonSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
buttonLayout->addItem(buttonSpacer);
|
||||
|
||||
vLayout->addItem(buttonLayout);
|
||||
|
||||
QSpacerItem* verticalSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
vLayout->addItem(verticalSpacer);
|
||||
|
||||
// Using border-image allows for scaling options background-image does not support
|
||||
setStyleSheet("O3DE--ProjectManager--ScreenWidget { border-image: url(:/Backgrounds/FirstTimeBackgroundImage.jpg) repeat repeat; }");
|
||||
|
||||
connect(m_createProjectButton, &QPushButton::pressed, this, &FirstTimeUseScreen::HandleNewProjectButton);
|
||||
connect(m_addProjectButton, &QPushButton::pressed, this, &FirstTimeUseScreen::HandleAddProjectButton);
|
||||
}
|
||||
|
||||
ProjectManagerScreen FirstTimeUseScreen::GetScreenEnum()
|
||||
{
|
||||
return ProjectManagerScreen::FirstTimeUse;
|
||||
}
|
||||
|
||||
void FirstTimeUseScreen::HandleNewProjectButton()
|
||||
{
|
||||
emit ResetScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
}
|
||||
void FirstTimeUseScreen::HandleAddProjectButton()
|
||||
{
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome);
|
||||
}
|
||||
|
||||
QPushButton* FirstTimeUseScreen::CreateLargeBoxButton(const QIcon& icon, const QString& text, QWidget* parent)
|
||||
{
|
||||
QPushButton* largeBoxButton = new QPushButton(icon, text, parent);
|
||||
|
||||
largeBoxButton->setFixedSize(s_boxButtonWidth, s_boxButtonHeight);
|
||||
largeBoxButton->setFlat(true);
|
||||
largeBoxButton->setFocusPolicy(Qt::FocusPolicy::NoFocus);
|
||||
largeBoxButton->setStyleSheet("QPushButton { font-size: 14px; background-color: rgba(0, 0, 0, 191); }");
|
||||
|
||||
return largeBoxButton;
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <ScreenWidget.h>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QIcon)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class FirstTimeUseScreen
|
||||
: public ScreenWidget
|
||||
{
|
||||
public:
|
||||
explicit FirstTimeUseScreen(QWidget* parent = nullptr);
|
||||
~FirstTimeUseScreen() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
|
||||
protected slots:
|
||||
void HandleNewProjectButton();
|
||||
void HandleAddProjectButton();
|
||||
|
||||
private:
|
||||
QPushButton* CreateLargeBoxButton(const QIcon& icon, const QString& text, QWidget* parent = nullptr);
|
||||
|
||||
QPushButton* m_createProjectButton;
|
||||
QPushButton* m_addProjectButton;
|
||||
|
||||
inline constexpr static int s_contentMargins = 80;
|
||||
inline constexpr static int s_buttonSpacing = 30;
|
||||
inline constexpr static int s_iconSize = 24;
|
||||
inline constexpr static int s_spacerSize = 20;
|
||||
inline constexpr static int s_boxButtonWidth = 210;
|
||||
inline constexpr static int s_boxButtonHeight = 280;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
#include <NewProjectSettingsScreen.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <FormLineEditWidget.h>
|
||||
#include <FormBrowseEditWidget.h>
|
||||
#include <PathValidator.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
@@ -23,6 +26,7 @@
|
||||
#include <QPushButton>
|
||||
#include <QSpacerItem>
|
||||
#include <QStandardPaths>
|
||||
#include <QFrame>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
@@ -31,64 +35,81 @@ namespace O3DE::ProjectManager
|
||||
NewProjectSettingsScreen::NewProjectSettingsScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
this->setLayout(hLayout);
|
||||
QHBoxLayout* hLayout = new QHBoxLayout(this);
|
||||
hLayout->setAlignment(Qt::AlignLeft);
|
||||
hLayout->setContentsMargins(0,0,0,0);
|
||||
|
||||
// if we don't provide a parent for this box layout the stylesheet doesn't take
|
||||
// if we don't set this in a frame (just use a sub-layout) all the content will align incorrectly horizontally
|
||||
QFrame* projectSettingsFrame = new QFrame(this);
|
||||
projectSettingsFrame->setObjectName("projectSettings");
|
||||
QVBoxLayout* vLayout = new QVBoxLayout(this);
|
||||
|
||||
QLabel* projectNameLabel = new QLabel(tr("Project Name"), this);
|
||||
vLayout->addWidget(projectNameLabel);
|
||||
|
||||
m_projectNameLineEdit = new QLineEdit(tr("New Project"), this);
|
||||
vLayout->addWidget(m_projectNameLineEdit);
|
||||
|
||||
QLabel* projectPathLabel = new QLabel(tr("Project Location"), this);
|
||||
vLayout->addWidget(projectPathLabel);
|
||||
|
||||
// you cannot remove content margins in qss
|
||||
vLayout->setContentsMargins(0,0,0,0);
|
||||
vLayout->setAlignment(Qt::AlignTop);
|
||||
{
|
||||
QHBoxLayout* projectPathLayout = new QHBoxLayout(this);
|
||||
m_projectName = new FormLineEditWidget(tr("Project name"), tr("New Project"), this);
|
||||
m_projectName->setErrorLabelText(
|
||||
tr("A project with this name already exists at this location. Please choose a new name or location."));
|
||||
vLayout->addWidget(m_projectName);
|
||||
|
||||
m_projectPathLineEdit = new QLineEdit(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), this);
|
||||
projectPathLayout->addWidget(m_projectPathLineEdit);
|
||||
m_projectPath =
|
||||
new FormBrowseEditWidget(tr("Project Location"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), this);
|
||||
m_projectPath->lineEdit()->setReadOnly(true);
|
||||
m_projectPath->setErrorLabelText(tr("Please provide a valid path to a folder that exists"));
|
||||
m_projectPath->lineEdit()->setValidator(new PathValidator(PathValidator::PathMode::ExistingFolder, this));
|
||||
vLayout->addWidget(m_projectPath);
|
||||
|
||||
QPushButton* browseButton = new QPushButton(tr("Browse"), this);
|
||||
connect(browseButton, &QPushButton::pressed, this, &NewProjectSettingsScreen::HandleBrowseButton);
|
||||
projectPathLayout->addWidget(browseButton);
|
||||
|
||||
vLayout->addLayout(projectPathLayout);
|
||||
}
|
||||
|
||||
QLabel* projectTemplateLabel = new QLabel(this);
|
||||
projectTemplateLabel->setText("Project Template");
|
||||
vLayout->addWidget(projectTemplateLabel);
|
||||
|
||||
QHBoxLayout* templateLayout = new QHBoxLayout(this);
|
||||
vLayout->addItem(templateLayout);
|
||||
|
||||
m_projectTemplateButtonGroup = new QButtonGroup(this);
|
||||
auto templatesResult = PythonBindingsInterface::Get()->GetProjectTemplates();
|
||||
if (templatesResult.IsSuccess() && !templatesResult.GetValue().isEmpty())
|
||||
{
|
||||
for (auto projectTemplate : templatesResult.GetValue())
|
||||
// if we don't use a QFrame we cannot "contain" the widgets inside and move them around
|
||||
// as a group
|
||||
QFrame* projectTemplateWidget = new QFrame(this);
|
||||
projectTemplateWidget->setObjectName("projectTemplate");
|
||||
QVBoxLayout* containerLayout = new QVBoxLayout();
|
||||
containerLayout->setAlignment(Qt::AlignTop);
|
||||
{
|
||||
QRadioButton* radioButton = new QRadioButton(projectTemplate.m_name, this);
|
||||
radioButton->setProperty(k_pathProperty, projectTemplate.m_path);
|
||||
m_projectTemplateButtonGroup->addButton(radioButton);
|
||||
QLabel* projectTemplateLabel = new QLabel(tr("Select a Project Template"));
|
||||
projectTemplateLabel->setObjectName("projectTemplateLabel");
|
||||
containerLayout->addWidget(projectTemplateLabel);
|
||||
|
||||
templateLayout->addWidget(radioButton);
|
||||
QLabel* projectTemplateDetailsLabel = new QLabel(tr("Project templates are pre-configured with relevant Gems that provide "
|
||||
"additional functionality and content to the project."));
|
||||
projectTemplateDetailsLabel->setWordWrap(true);
|
||||
projectTemplateDetailsLabel->setObjectName("projectTemplateDetailsLabel");
|
||||
containerLayout->addWidget(projectTemplateDetailsLabel);
|
||||
|
||||
QHBoxLayout* templateLayout = new QHBoxLayout(this);
|
||||
containerLayout->addItem(templateLayout);
|
||||
|
||||
m_projectTemplateButtonGroup = new QButtonGroup(this);
|
||||
m_projectTemplateButtonGroup->setObjectName("templateButtonGroup");
|
||||
auto templatesResult = PythonBindingsInterface::Get()->GetProjectTemplates();
|
||||
if (templatesResult.IsSuccess() && !templatesResult.GetValue().isEmpty())
|
||||
{
|
||||
for (auto projectTemplate : templatesResult.GetValue())
|
||||
{
|
||||
QRadioButton* radioButton = new QRadioButton(projectTemplate.m_name, this);
|
||||
radioButton->setProperty(k_pathProperty, projectTemplate.m_path);
|
||||
m_projectTemplateButtonGroup->addButton(radioButton);
|
||||
|
||||
containerLayout->addWidget(radioButton);
|
||||
}
|
||||
|
||||
m_projectTemplateButtonGroup->buttons().first()->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
m_projectTemplateButtonGroup->buttons().first()->setChecked(true);
|
||||
projectTemplateWidget->setLayout(containerLayout);
|
||||
vLayout->addWidget(projectTemplateWidget);
|
||||
}
|
||||
projectSettingsFrame->setLayout(vLayout);
|
||||
|
||||
QSpacerItem* verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
vLayout->addItem(verticalSpacer);
|
||||
hLayout->addWidget(projectSettingsFrame);
|
||||
|
||||
hLayout->addItem(vLayout);
|
||||
QWidget* projectTemplateDetails = new QWidget(this);
|
||||
projectTemplateDetails->setObjectName("projectTemplateDetails");
|
||||
hLayout->addWidget(projectTemplateDetails);
|
||||
|
||||
QWidget* gemsListPlaceholder = new QWidget(this);
|
||||
gemsListPlaceholder->setFixedWidth(250);
|
||||
hLayout->addWidget(gemsListPlaceholder);
|
||||
this->setLayout(hLayout);
|
||||
}
|
||||
|
||||
ProjectManagerScreen NewProjectSettingsScreen::GetScreenEnum()
|
||||
@@ -96,26 +117,12 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::NewProjectSettings;
|
||||
}
|
||||
|
||||
void NewProjectSettingsScreen::HandleBrowseButton()
|
||||
{
|
||||
QString defaultPath = m_projectPathLineEdit->text();
|
||||
if (defaultPath.isEmpty())
|
||||
{
|
||||
defaultPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
}
|
||||
|
||||
QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("New project path"), defaultPath));
|
||||
if (!directory.isEmpty())
|
||||
{
|
||||
m_projectPathLineEdit->setText(directory);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectInfo NewProjectSettingsScreen::GetProjectInfo()
|
||||
{
|
||||
ProjectInfo projectInfo;
|
||||
projectInfo.m_projectName = m_projectNameLineEdit->text();
|
||||
projectInfo.m_path = QDir::toNativeSeparators(m_projectPathLineEdit->text() + "/" + projectInfo.m_projectName);
|
||||
projectInfo.m_projectName = m_projectName->lineEdit()->text();
|
||||
projectInfo.m_path = QDir::toNativeSeparators(m_projectPath->lineEdit()->text() + "/" + projectInfo.m_projectName);
|
||||
return projectInfo;
|
||||
}
|
||||
|
||||
@@ -127,18 +134,18 @@ namespace O3DE::ProjectManager
|
||||
bool NewProjectSettingsScreen::Validate()
|
||||
{
|
||||
bool projectNameIsValid = true;
|
||||
if (m_projectNameLineEdit->text().isEmpty())
|
||||
if (m_projectName->lineEdit()->text().isEmpty())
|
||||
{
|
||||
projectNameIsValid = false;
|
||||
}
|
||||
|
||||
bool projectPathIsValid = true;
|
||||
if (m_projectPathLineEdit->text().isEmpty())
|
||||
if (m_projectPath->lineEdit()->text().isEmpty())
|
||||
{
|
||||
projectPathIsValid = false;
|
||||
}
|
||||
|
||||
QDir path(QDir::toNativeSeparators(m_projectPathLineEdit->text() + "/" + m_projectNameLineEdit->text()));
|
||||
QDir path(QDir::toNativeSeparators(m_projectPath->lineEdit()->text() + "/" + m_projectName->lineEdit()->text()));
|
||||
if (path.exists() && !path.isEmpty())
|
||||
{
|
||||
projectPathIsValid = false;
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QButtonGroup)
|
||||
QT_FORWARD_DECLARE_CLASS(QLineEdit)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
QT_FORWARD_DECLARE_CLASS(FormLineEditWidget)
|
||||
QT_FORWARD_DECLARE_CLASS(FormBrowseEditWidget)
|
||||
|
||||
class NewProjectSettingsScreen
|
||||
: public ScreenWidget
|
||||
{
|
||||
@@ -38,8 +40,8 @@ namespace O3DE::ProjectManager
|
||||
void HandleBrowseButton();
|
||||
|
||||
private:
|
||||
QLineEdit* m_projectNameLineEdit;
|
||||
QLineEdit* m_projectPathLineEdit;
|
||||
FormLineEditWidget* m_projectName;
|
||||
FormBrowseEditWidget* m_projectPath;
|
||||
QButtonGroup* m_projectTemplateButtonGroup;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace O3DE::ProjectManager
|
||||
LabelButton::LabelButton(QWidget* parent)
|
||||
: QLabel(parent)
|
||||
{
|
||||
setObjectName("labelButton");
|
||||
m_overlayLabel = new QLabel("", this);
|
||||
m_overlayLabel->setObjectName("labelButtonOverlay");
|
||||
m_overlayLabel->setWordWrap(true);
|
||||
@@ -75,6 +76,8 @@ namespace O3DE::ProjectManager
|
||||
|
||||
void ProjectButton::Setup()
|
||||
{
|
||||
setObjectName("projectButton");
|
||||
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setSpacing(0);
|
||||
vLayout->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -98,14 +101,21 @@ namespace O3DE::ProjectManager
|
||||
m_deleteProjectAction = newProjectMenu->addAction(tr("Delete the Project"));
|
||||
#endif
|
||||
|
||||
m_projectSettingsMenuButton = new QPushButton(this);
|
||||
m_projectSettingsMenuButton->setText(m_projectName);
|
||||
m_projectSettingsMenuButton->setMenu(newProjectMenu);
|
||||
m_projectSettingsMenuButton->setFocusPolicy(Qt::FocusPolicy::NoFocus);
|
||||
m_projectSettingsMenuButton->setStyleSheet("font-size: 14px; text-align:left;");
|
||||
vLayout->addWidget(m_projectSettingsMenuButton);
|
||||
QFrame* footer = new QFrame(this);
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setContentsMargins(0, 0, 0, 0);
|
||||
footer->setLayout(hLayout);
|
||||
{
|
||||
QLabel* projectNameLabel = new QLabel(m_projectName, this);
|
||||
hLayout->addWidget(projectNameLabel);
|
||||
|
||||
setFixedSize(s_projectImageWidth, s_projectImageHeight + m_projectSettingsMenuButton->height());
|
||||
QPushButton* projectMenuButton = new QPushButton(this);
|
||||
projectMenuButton->setObjectName("projectMenuButton");
|
||||
projectMenuButton->setMenu(newProjectMenu);
|
||||
hLayout->addWidget(projectMenuButton);
|
||||
}
|
||||
|
||||
vLayout->addWidget(footer);
|
||||
|
||||
connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectName); });
|
||||
connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectName); });
|
||||
|
||||
@@ -73,7 +73,6 @@ namespace O3DE::ProjectManager
|
||||
QString m_projectName;
|
||||
QString m_projectImagePath;
|
||||
LabelButton* m_projectImageLabel;
|
||||
QPushButton* m_projectSettingsMenuButton;
|
||||
QAction* m_editProjectAction;
|
||||
QAction* m_editProjectGemsAction;
|
||||
QAction* m_copyProjectAction;
|
||||
|
||||
@@ -11,52 +11,46 @@
|
||||
*/
|
||||
|
||||
#include <ProjectManagerWindow.h>
|
||||
#include <ScreenFactory.h>
|
||||
#include <ScreensCtrl.h>
|
||||
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include <Source/ui_ProjectManagerWindow.h>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath)
|
||||
: QMainWindow(parent)
|
||||
, m_ui(new Ui::ProjectManagerWindowClass())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
QLayout* layout = m_ui->centralWidget->layout();
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_pythonBindings = AZStd::make_unique<PythonBindings>(engineRootPath);
|
||||
|
||||
m_screensCtrl = new ScreensCtrl();
|
||||
m_ui->verticalLayout->addWidget(m_screensCtrl);
|
||||
setWindowTitle(tr("O3DE Project Manager"));
|
||||
|
||||
connect(m_ui->projectsMenu, &QMenu::aboutToShow, this, &ProjectManagerWindow::HandleProjectsMenu);
|
||||
connect(m_ui->engineMenu, &QMenu::aboutToShow, this, &ProjectManagerWindow::HandleEngineMenu);
|
||||
ScreensCtrl* screensCtrl = new ScreensCtrl();
|
||||
|
||||
// currently the tab order on the home page is based on the order of this list
|
||||
QVector<ProjectManagerScreen> screenEnums =
|
||||
{
|
||||
ProjectManagerScreen::Projects,
|
||||
ProjectManagerScreen::EngineSettings,
|
||||
ProjectManagerScreen::CreateProject,
|
||||
ProjectManagerScreen::UpdateProject
|
||||
};
|
||||
screensCtrl->BuildScreens(screenEnums);
|
||||
|
||||
setCentralWidget(screensCtrl);
|
||||
|
||||
// setup stylesheets and hot reloading
|
||||
QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast<int>(engineRootPath.Native().size()));
|
||||
const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources");
|
||||
const auto qrcPath = QStringLiteral(":/ProjectManager/style");
|
||||
AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRootPath);
|
||||
|
||||
// set stylesheet after creating the screens or their styles won't get updated
|
||||
AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("style:ProjectManager.qss"));
|
||||
|
||||
QVector<ProjectManagerScreen> screenEnums =
|
||||
{
|
||||
ProjectManagerScreen::FirstTimeUse,
|
||||
ProjectManagerScreen::CreateProject,
|
||||
ProjectManagerScreen::ProjectsHome,
|
||||
ProjectManagerScreen::UpdateProject,
|
||||
ProjectManagerScreen::EngineSettings
|
||||
};
|
||||
m_screensCtrl->BuildScreens(screenEnums);
|
||||
m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::FirstTimeUse, false);
|
||||
screensCtrl->ForceChangeToScreen(ProjectManagerScreen::Projects, false);
|
||||
}
|
||||
|
||||
ProjectManagerWindow::~ProjectManagerWindow()
|
||||
@@ -64,13 +58,4 @@ namespace O3DE::ProjectManager
|
||||
m_pythonBindings.reset();
|
||||
}
|
||||
|
||||
void ProjectManagerWindow::HandleProjectsMenu()
|
||||
{
|
||||
m_screensCtrl->ChangeToScreen(ProjectManagerScreen::ProjectsHome);
|
||||
}
|
||||
void ProjectManagerWindow::HandleEngineMenu()
|
||||
{
|
||||
m_screensCtrl->ChangeToScreen(ProjectManagerScreen::EngineSettings);
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -13,17 +13,9 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QMainWindow>
|
||||
|
||||
#include <ScreensCtrl.h>
|
||||
|
||||
#include <PythonBindings.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ProjectManagerWindowClass;
|
||||
}
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ProjectManagerWindow
|
||||
@@ -35,13 +27,7 @@ namespace O3DE::ProjectManager
|
||||
explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath);
|
||||
~ProjectManagerWindow();
|
||||
|
||||
protected slots:
|
||||
void HandleProjectsMenu();
|
||||
void HandleEngineMenu();
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::ProjectManagerWindowClass> m_ui;
|
||||
ScreensCtrl* m_screensCtrl;
|
||||
AZStd::unique_ptr<PythonBindings> m_pythonBindings;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProjectManagerWindowClass</class>
|
||||
<widget class="QMainWindow" name="ProjectManagerWindowClass">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1200</width>
|
||||
<height>800</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>O3DE Project Manager</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1200</width>
|
||||
<height>36</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QMenu" name="iconMenu">
|
||||
<property name="title">
|
||||
<string>Icon</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/ProjectManager.qrc">
|
||||
<normaloff>:/o3de_editor.ico</normaloff>:/o3de_editor.ico</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="projectsMenu">
|
||||
<property name="title">
|
||||
<string>Projects</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="engineMenu">
|
||||
<property name="title">
|
||||
<string>Engine</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="iconMenu"/>
|
||||
<addaction name="projectsMenu"/>
|
||||
<addaction name="engineMenu"/>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../Resources/ProjectManager.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ProjectsHomeScreen.h>
|
||||
|
||||
#include <ProjectButtonWidget.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <AzCore/Platform.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzFramework/AzFramework_Traits_Platform.h>
|
||||
#include <AzFramework/Process/ProcessCommon.h>
|
||||
#include <AzFramework/Process/ProcessWatcher.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QMenu>
|
||||
#include <QListView>
|
||||
#include <QSpacerItem>
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QFileInfo>
|
||||
#include <QScrollArea>
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
ProjectsHomeScreen::ProjectsHomeScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
setLayout(vLayout);
|
||||
vLayout->setContentsMargins(s_contentMargins, s_contentMargins, s_contentMargins, s_contentMargins);
|
||||
|
||||
QHBoxLayout* topLayout = new QHBoxLayout();
|
||||
|
||||
QLabel* titleLabel = new QLabel(this);
|
||||
titleLabel->setText("My Projects");
|
||||
titleLabel->setStyleSheet("font-size: 24px");
|
||||
topLayout->addWidget(titleLabel);
|
||||
|
||||
QSpacerItem* topSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
topLayout->addItem(topSpacer);
|
||||
|
||||
QMenu* newProjectMenu = new QMenu(this);
|
||||
m_createNewProjectAction = newProjectMenu->addAction("Create New Project");
|
||||
m_addExistingProjectAction = newProjectMenu->addAction("Add Existing Project");
|
||||
|
||||
QPushButton* newProjectMenuButton = new QPushButton(this);
|
||||
newProjectMenuButton->setText("New Project...");
|
||||
newProjectMenuButton->setMenu(newProjectMenu);
|
||||
newProjectMenuButton->setFixedWidth(s_newProjectButtonWidth);
|
||||
newProjectMenuButton->setStyleSheet("font-size: 14px;");
|
||||
topLayout->addWidget(newProjectMenuButton);
|
||||
|
||||
vLayout->addLayout(topLayout);
|
||||
|
||||
// Get all projects and create a horizontal scrolling list of them
|
||||
auto projectsResult = PythonBindingsInterface::Get()->GetProjects();
|
||||
if (projectsResult.IsSuccess() && !projectsResult.GetValue().isEmpty())
|
||||
{
|
||||
QScrollArea* projectsScrollArea = new QScrollArea(this);
|
||||
QWidget* scrollWidget = new QWidget();
|
||||
QGridLayout* projectGridLayout = new QGridLayout();
|
||||
scrollWidget->setLayout(projectGridLayout);
|
||||
projectsScrollArea->setWidget(scrollWidget);
|
||||
projectsScrollArea->setWidgetResizable(true);
|
||||
|
||||
int gridIndex = 0;
|
||||
for (auto project : projectsResult.GetValue())
|
||||
{
|
||||
ProjectButton* projectButton;
|
||||
QString projectPreviewPath = project.m_path + m_projectPreviewImagePath;
|
||||
QFileInfo doesPreviewExist(projectPreviewPath);
|
||||
if (doesPreviewExist.exists() && doesPreviewExist.isFile())
|
||||
{
|
||||
projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
projectButton = new ProjectButton(project.m_projectName, this);
|
||||
}
|
||||
|
||||
// Create rows of projects buttons s_projectButtonRowCount buttons wide
|
||||
projectGridLayout->addWidget(projectButton, gridIndex / s_projectButtonRowCount, gridIndex % s_projectButtonRowCount);
|
||||
|
||||
connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsHomeScreen::HandleOpenProject);
|
||||
connect(projectButton, &ProjectButton::EditProject, this, &ProjectsHomeScreen::HandleEditProject);
|
||||
|
||||
#ifdef SHOW_ALL_PROJECT_ACTIONS
|
||||
connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsHomeScreen::HandleEditProjectGems);
|
||||
connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsHomeScreen::HandleCopyProject);
|
||||
connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsHomeScreen::HandleRemoveProject);
|
||||
connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsHomeScreen::HandleDeleteProject);
|
||||
#endif
|
||||
++gridIndex;
|
||||
}
|
||||
|
||||
vLayout->addWidget(projectsScrollArea);
|
||||
}
|
||||
|
||||
// Using border-image allows for scaling options background-image does not support
|
||||
setStyleSheet("O3DE--ProjectManager--ScreenWidget { border-image: url(:/Backgrounds/FirstTimeBackgroundImage.jpg) repeat repeat; }");
|
||||
|
||||
connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsHomeScreen::HandleNewProjectButton);
|
||||
connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsHomeScreen::HandleAddProjectButton);
|
||||
}
|
||||
|
||||
ProjectManagerScreen ProjectsHomeScreen::GetScreenEnum()
|
||||
{
|
||||
return ProjectManagerScreen::ProjectsHome;
|
||||
}
|
||||
|
||||
void ProjectsHomeScreen::HandleNewProjectButton()
|
||||
{
|
||||
emit ResetScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
}
|
||||
void ProjectsHomeScreen::HandleAddProjectButton()
|
||||
{
|
||||
// Do nothing for now
|
||||
}
|
||||
void ProjectsHomeScreen::HandleOpenProject(const QString& projectPath)
|
||||
{
|
||||
if (!projectPath.isEmpty())
|
||||
{
|
||||
AZ::IO::FixedMaxPath executableDirectory = AZ::Utils::GetExecutableDirectory();
|
||||
AZStd::string executableFilename = "Editor";
|
||||
AZ::IO::FixedMaxPath editorExecutablePath = executableDirectory / (executableFilename + AZ_TRAIT_OS_EXECUTABLE_EXTENSION);
|
||||
auto cmdPath = AZ::IO::FixedMaxPathString::format("%s -regset=\"/Amazon/AzCore/Bootstrap/project_path=%s\"", editorExecutablePath.c_str(), projectPath.toStdString().c_str());
|
||||
|
||||
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
processLaunchInfo.m_commandlineParameters = cmdPath;
|
||||
bool launchSucceeded = AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo);
|
||||
if (!launchSucceeded)
|
||||
{
|
||||
AZ_Error("ProjectManager", false, "Failed to launch editor");
|
||||
QMessageBox::critical( this, tr("Error"), tr("Failed to launch the Editor, please verify the project settings are valid."));
|
||||
}
|
||||
else
|
||||
{
|
||||
// prevent the user from accidentally pressing the button while the editor is launching
|
||||
// and let them know what's happening
|
||||
ProjectButton* button = qobject_cast<ProjectButton*>(sender());
|
||||
if (button)
|
||||
{
|
||||
button->SetButtonEnabled(false);
|
||||
button->SetButtonOverlayText(tr("Opening Editor..."));
|
||||
}
|
||||
|
||||
// enable the button after 3 seconds
|
||||
constexpr int waitTimeInMs = 3000;
|
||||
QTimer::singleShot(waitTimeInMs, this, [this, button] {
|
||||
if (button)
|
||||
{
|
||||
button->SetButtonEnabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("ProjectManager", false, "Cannot open editor because an empty project path was provided");
|
||||
QMessageBox::critical( this, tr("Error"), tr("Failed to launch the Editor because the project path is invalid."));
|
||||
}
|
||||
|
||||
}
|
||||
void ProjectsHomeScreen::HandleEditProject(const QString& projectPath)
|
||||
{
|
||||
emit NotifyCurrentProject(projectPath);
|
||||
emit ResetScreenRequest(ProjectManagerScreen::UpdateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::UpdateProject);
|
||||
}
|
||||
void ProjectsHomeScreen::HandleEditProjectGems(const QString& projectPath)
|
||||
{
|
||||
emit NotifyCurrentProject(projectPath);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
|
||||
}
|
||||
void ProjectsHomeScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Open file dialog and choose location for copied project then register copy with O3DE
|
||||
}
|
||||
void ProjectsHomeScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Unregister Project from O3DE
|
||||
}
|
||||
void ProjectsHomeScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Remove project from 03DE and delete from disk
|
||||
ProjectsHomeScreen::HandleRemoveProject(projectPath);
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ProjectsScreen.h>
|
||||
|
||||
#include <ProjectButtonWidget.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
|
||||
#include <AzQtComponents/Components/FlowLayout.h>
|
||||
#include <AzCore/Platform.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzFramework/AzFramework_Traits_Platform.h>
|
||||
#include <AzFramework/Process/ProcessCommon.h>
|
||||
#include <AzFramework/Process/ProcessWatcher.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QMenu>
|
||||
#include <QListView>
|
||||
#include <QSpacerItem>
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QFileInfo>
|
||||
#include <QScrollArea>
|
||||
#include <QStackedWidget>
|
||||
#include <QFrame>
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QSettings>
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
|
||||
//#define DISPLAY_PROJECT_DEV_DATA true
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
ProjectsScreen::ProjectsScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setAlignment(Qt::AlignTop);
|
||||
vLayout->setContentsMargins(s_contentMargins, 0, s_contentMargins, 0);
|
||||
setLayout(vLayout);
|
||||
|
||||
m_background.load(":/Backgrounds/FirstTimeBackgroundImage.jpg");
|
||||
|
||||
m_stack = new QStackedWidget(this);
|
||||
|
||||
m_firstTimeContent = CreateFirstTimeContent();
|
||||
m_stack->addWidget(m_firstTimeContent);
|
||||
|
||||
m_projectsContent = CreateProjectsContent();
|
||||
m_stack->addWidget(m_projectsContent);
|
||||
|
||||
vLayout->addWidget(m_stack);
|
||||
|
||||
connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleNewProjectButton);
|
||||
connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleAddProjectButton);
|
||||
}
|
||||
|
||||
QFrame* ProjectsScreen::CreateFirstTimeContent()
|
||||
{
|
||||
QFrame* frame = new QFrame(this);
|
||||
frame->setObjectName("firstTimeContent");
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
frame->setLayout(layout);
|
||||
|
||||
QLabel* titleLabel = new QLabel(tr("Ready. Set. Create."), this);
|
||||
titleLabel->setObjectName("titleLabel");
|
||||
layout->addWidget(titleLabel);
|
||||
|
||||
QLabel* introLabel = new QLabel(this);
|
||||
introLabel->setObjectName("introLabel");
|
||||
introLabel->setText(tr("Welcome to O3DE! Start something new by creating a project. Not sure what to create? \nExplore what's "
|
||||
"available by downloading our sample project."));
|
||||
layout->addWidget(introLabel);
|
||||
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout(this);
|
||||
buttonLayout->setAlignment(Qt::AlignLeft);
|
||||
buttonLayout->setSpacing(s_spacerSize);
|
||||
|
||||
// use a newline to force the text up
|
||||
QPushButton* createProjectButton = new QPushButton(tr("Create a Project\n"), this);
|
||||
createProjectButton->setObjectName("createProjectButton");
|
||||
buttonLayout->addWidget(createProjectButton);
|
||||
|
||||
QPushButton* addProjectButton = new QPushButton(tr("Add a Project\n"), this);
|
||||
addProjectButton->setObjectName("addProjectButton");
|
||||
buttonLayout->addWidget(addProjectButton);
|
||||
|
||||
connect(createProjectButton, &QPushButton::clicked, this, &ProjectsScreen::HandleNewProjectButton);
|
||||
connect(addProjectButton, &QPushButton::clicked, this, &ProjectsScreen::HandleAddProjectButton);
|
||||
|
||||
layout->addLayout(buttonLayout);
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
QFrame* ProjectsScreen::CreateProjectsContent()
|
||||
{
|
||||
QFrame* frame = new QFrame(this);
|
||||
frame->setObjectName("projectsContent");
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
frame->setLayout(layout);
|
||||
|
||||
QFrame* header = new QFrame(this);
|
||||
QHBoxLayout* headerLayout = new QHBoxLayout();
|
||||
{
|
||||
QLabel* titleLabel = new QLabel(tr("My Projects"), this);
|
||||
titleLabel->setObjectName("titleLabel");
|
||||
headerLayout->addWidget(titleLabel);
|
||||
|
||||
QMenu* newProjectMenu = new QMenu(this);
|
||||
m_createNewProjectAction = newProjectMenu->addAction("Create New Project");
|
||||
m_addExistingProjectAction = newProjectMenu->addAction("Add Existing Project");
|
||||
|
||||
connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleNewProjectButton);
|
||||
connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleAddProjectButton);
|
||||
|
||||
QPushButton* newProjectMenuButton = new QPushButton(tr("New Project..."), this);
|
||||
newProjectMenuButton->setObjectName("newProjectButton");
|
||||
newProjectMenuButton->setMenu(newProjectMenu);
|
||||
newProjectMenuButton->setDefault(true);
|
||||
headerLayout->addWidget(newProjectMenuButton);
|
||||
}
|
||||
header->setLayout(headerLayout);
|
||||
|
||||
layout->addWidget(header);
|
||||
|
||||
// Get all projects and create a horizontal scrolling list of them
|
||||
auto projectsResult = PythonBindingsInterface::Get()->GetProjects();
|
||||
if (projectsResult.IsSuccess() && !projectsResult.GetValue().isEmpty())
|
||||
{
|
||||
QScrollArea* projectsScrollArea = new QScrollArea(this);
|
||||
QWidget* scrollWidget = new QWidget();
|
||||
|
||||
FlowLayout* flowLayout = new FlowLayout(0, s_spacerSize, s_spacerSize);
|
||||
scrollWidget->setLayout(flowLayout);
|
||||
|
||||
projectsScrollArea->setWidget(scrollWidget);
|
||||
projectsScrollArea->setWidgetResizable(true);
|
||||
|
||||
#ifndef DISPLAY_PROJECT_DEV_DATA
|
||||
for (auto project : projectsResult.GetValue())
|
||||
#else
|
||||
ProjectInfo project = projectsResult.GetValue().at(0);
|
||||
for (int i = 0; i < 15; i++)
|
||||
#endif
|
||||
{
|
||||
ProjectButton* projectButton;
|
||||
QString projectPreviewPath = project.m_path + m_projectPreviewImagePath;
|
||||
QFileInfo doesPreviewExist(projectPreviewPath);
|
||||
if (doesPreviewExist.exists() && doesPreviewExist.isFile())
|
||||
{
|
||||
projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
projectButton = new ProjectButton(project.m_projectName, this);
|
||||
}
|
||||
|
||||
flowLayout->addWidget(projectButton);
|
||||
|
||||
connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsScreen::HandleOpenProject);
|
||||
connect(projectButton, &ProjectButton::EditProject, this, &ProjectsScreen::HandleEditProject);
|
||||
|
||||
#ifdef DISPLAY_PROJECT_DEV_DATA
|
||||
connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsScreen::HandleEditProjectGems);
|
||||
connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsScreen::HandleCopyProject);
|
||||
connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsScreen::HandleRemoveProject);
|
||||
connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsScreen::HandleDeleteProject);
|
||||
#endif
|
||||
}
|
||||
|
||||
layout->addWidget(projectsScrollArea);
|
||||
}
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
ProjectManagerScreen ProjectsScreen::GetScreenEnum()
|
||||
{
|
||||
return ProjectManagerScreen::Projects;
|
||||
}
|
||||
|
||||
bool ProjectsScreen::IsTab()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QString ProjectsScreen::GetTabText()
|
||||
{
|
||||
return tr("Projects");
|
||||
}
|
||||
|
||||
void ProjectsScreen::paintEvent([[maybe_unused]] QPaintEvent* event)
|
||||
{
|
||||
// we paint the background here because qss does not support background cover scaling
|
||||
QPainter painter(this);
|
||||
|
||||
auto winSize = size();
|
||||
auto pixmapRatio = (float)m_background.width() / m_background.height();
|
||||
auto windowRatio = (float)winSize.width() / winSize.height();
|
||||
|
||||
if (pixmapRatio > windowRatio)
|
||||
{
|
||||
auto newWidth = (int)(winSize.height() * pixmapRatio);
|
||||
auto offset = (newWidth - winSize.width()) / -2;
|
||||
painter.drawPixmap(offset, 0, newWidth, winSize.height(), m_background);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto newHeight = (int)(winSize.width() / pixmapRatio);
|
||||
painter.drawPixmap(0, 0, winSize.width(), newHeight, m_background);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectsScreen::HandleNewProjectButton()
|
||||
{
|
||||
emit ResetScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
}
|
||||
void ProjectsScreen::HandleAddProjectButton()
|
||||
{
|
||||
// Do nothing for now
|
||||
}
|
||||
void ProjectsScreen::HandleOpenProject(const QString& projectPath)
|
||||
{
|
||||
if (!projectPath.isEmpty())
|
||||
{
|
||||
AZ::IO::FixedMaxPath executableDirectory = AZ::Utils::GetExecutableDirectory();
|
||||
AZStd::string executableFilename = "Editor";
|
||||
AZ::IO::FixedMaxPath editorExecutablePath = executableDirectory / (executableFilename + AZ_TRAIT_OS_EXECUTABLE_EXTENSION);
|
||||
auto cmdPath = AZ::IO::FixedMaxPathString::format("%s -regset=\"/Amazon/AzCore/Bootstrap/project_path=%s\"", editorExecutablePath.c_str(), projectPath.toStdString().c_str());
|
||||
|
||||
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
processLaunchInfo.m_commandlineParameters = cmdPath;
|
||||
bool launchSucceeded = AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo);
|
||||
if (!launchSucceeded)
|
||||
{
|
||||
AZ_Error("ProjectManager", false, "Failed to launch editor");
|
||||
QMessageBox::critical( this, tr("Error"), tr("Failed to launch the Editor, please verify the project settings are valid."));
|
||||
}
|
||||
else
|
||||
{
|
||||
// prevent the user from accidentally pressing the button while the editor is launching
|
||||
// and let them know what's happening
|
||||
ProjectButton* button = qobject_cast<ProjectButton*>(sender());
|
||||
if (button)
|
||||
{
|
||||
button->SetButtonEnabled(false);
|
||||
button->SetButtonOverlayText(tr("Opening Editor..."));
|
||||
}
|
||||
|
||||
// enable the button after 3 seconds
|
||||
constexpr int waitTimeInMs = 3000;
|
||||
QTimer::singleShot(waitTimeInMs, this, [this, button] {
|
||||
if (button)
|
||||
{
|
||||
button->SetButtonEnabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("ProjectManager", false, "Cannot open editor because an empty project path was provided");
|
||||
QMessageBox::critical( this, tr("Error"), tr("Failed to launch the Editor because the project path is invalid."));
|
||||
}
|
||||
|
||||
}
|
||||
void ProjectsScreen::HandleEditProject(const QString& projectPath)
|
||||
{
|
||||
emit NotifyCurrentProject(projectPath);
|
||||
emit ResetScreenRequest(ProjectManagerScreen::UpdateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::UpdateProject);
|
||||
}
|
||||
void ProjectsScreen::HandleEditProjectGems(const QString& projectPath)
|
||||
{
|
||||
emit NotifyCurrentProject(projectPath);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
|
||||
}
|
||||
void ProjectsScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Open file dialog and choose location for copied project then register copy with O3DE
|
||||
}
|
||||
void ProjectsScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Unregister Project from O3DE
|
||||
}
|
||||
void ProjectsScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Remove project from 03DE and delete from disk
|
||||
ProjectsScreen::HandleRemoveProject(projectPath);
|
||||
}
|
||||
|
||||
void ProjectsScreen::NotifyCurrentScreen()
|
||||
{
|
||||
if (ShouldDisplayFirstTimeContent())
|
||||
{
|
||||
m_stack->setCurrentWidget(m_firstTimeContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stack->setCurrentWidget(m_projectsContent);
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectsScreen::ShouldDisplayFirstTimeContent()
|
||||
{
|
||||
auto projectsResult = PythonBindingsInterface::Get()->GetProjects();
|
||||
if (!projectsResult.IsSuccess() || projectsResult.GetValue().isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
bool displayFirstTimeContent = settings.value("displayFirstTimeContent", true).toBool();
|
||||
if (displayFirstTimeContent)
|
||||
{
|
||||
settings.setValue("displayFirstTimeContent", false);
|
||||
}
|
||||
|
||||
return displayFirstTimeContent;
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
+24
-6
@@ -15,16 +15,26 @@
|
||||
#include <ScreenWidget.h>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QPaintEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QFrame)
|
||||
QT_FORWARD_DECLARE_CLASS(QStackedWidget)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ProjectsHomeScreen
|
||||
class ProjectsScreen
|
||||
: public ScreenWidget
|
||||
{
|
||||
|
||||
public:
|
||||
explicit ProjectsHomeScreen(QWidget* parent = nullptr);
|
||||
~ProjectsHomeScreen() = default;
|
||||
explicit ProjectsScreen(QWidget* parent = nullptr);
|
||||
~ProjectsScreen() = default;
|
||||
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
QString GetTabText() override;
|
||||
bool IsTab() override;
|
||||
|
||||
protected:
|
||||
void NotifyCurrentScreen() override;
|
||||
|
||||
protected slots:
|
||||
void HandleNewProjectButton();
|
||||
@@ -36,16 +46,24 @@ namespace O3DE::ProjectManager
|
||||
void HandleRemoveProject(const QString& projectPath);
|
||||
void HandleDeleteProject(const QString& projectPath);
|
||||
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
QFrame* CreateFirstTimeContent();
|
||||
QFrame* CreateProjectsContent();
|
||||
bool ShouldDisplayFirstTimeContent();
|
||||
|
||||
QAction* m_createNewProjectAction;
|
||||
QAction* m_addExistingProjectAction;
|
||||
QPixmap m_background;
|
||||
QFrame* m_firstTimeContent;
|
||||
QFrame* m_projectsContent;
|
||||
QStackedWidget* m_stack;
|
||||
|
||||
const QString m_projectPreviewImagePath = "/preview.png";
|
||||
|
||||
inline constexpr static int s_contentMargins = 80;
|
||||
inline constexpr static int s_spacerSize = 20;
|
||||
inline constexpr static int s_projectButtonRowCount = 4;
|
||||
inline constexpr static int s_newProjectButtonWidth = 156;
|
||||
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -17,11 +17,10 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
Invalid = -1,
|
||||
Empty,
|
||||
FirstTimeUse,
|
||||
CreateProject,
|
||||
NewProjectSettings,
|
||||
GemCatalog,
|
||||
ProjectsHome,
|
||||
Projects,
|
||||
UpdateProject,
|
||||
ProjectSettings,
|
||||
EngineSettings
|
||||
|
||||
@@ -11,12 +11,11 @@
|
||||
*/
|
||||
#include <ScreenFactory.h>
|
||||
|
||||
#include <FirstTimeUseScreen.h>
|
||||
#include <CreateProjectCtrl.h>
|
||||
#include <UpdateProjectCtrl.h>
|
||||
#include <NewProjectSettingsScreen.h>
|
||||
#include <GemCatalog/GemCatalogScreen.h>
|
||||
#include <ProjectsHomeScreen.h>
|
||||
#include <ProjectsScreen.h>
|
||||
#include <ProjectSettingsScreen.h>
|
||||
#include <EngineSettingsScreen.h>
|
||||
|
||||
@@ -28,9 +27,6 @@ namespace O3DE::ProjectManager
|
||||
|
||||
switch(screen)
|
||||
{
|
||||
case (ProjectManagerScreen::FirstTimeUse):
|
||||
newScreen = new FirstTimeUseScreen(parent);
|
||||
break;
|
||||
case (ProjectManagerScreen::CreateProject):
|
||||
newScreen = new CreateProjectCtrl(parent);
|
||||
break;
|
||||
@@ -40,8 +36,8 @@ namespace O3DE::ProjectManager
|
||||
case (ProjectManagerScreen::GemCatalog):
|
||||
newScreen = new GemCatalogScreen(parent);
|
||||
break;
|
||||
case (ProjectManagerScreen::ProjectsHome):
|
||||
newScreen = new ProjectsHomeScreen(parent);
|
||||
case (ProjectManagerScreen::Projects):
|
||||
newScreen = new ProjectsScreen(parent);
|
||||
break;
|
||||
case (ProjectManagerScreen::UpdateProject):
|
||||
newScreen = new UpdateProjectCtrl(parent);
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ScreenHeaderWidget.h>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
ScreenHeader::ScreenHeader(QWidget* parent)
|
||||
: QFrame(parent)
|
||||
{
|
||||
setObjectName("header");
|
||||
|
||||
QHBoxLayout* layout = new QHBoxLayout();
|
||||
layout->setAlignment(Qt::AlignLeft);
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
|
||||
m_backButton = new QPushButton();
|
||||
m_backButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
layout->addWidget(m_backButton);
|
||||
|
||||
QVBoxLayout* titleLayout = new QVBoxLayout();
|
||||
m_title = new QLabel();
|
||||
m_title->setObjectName("headerTitle");
|
||||
titleLayout->addWidget(m_title);
|
||||
|
||||
m_subTitle = new QLabel();
|
||||
m_subTitle->setObjectName("headerSubTitle");
|
||||
titleLayout->addWidget(m_subTitle);
|
||||
|
||||
layout->addLayout(titleLayout);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void ScreenHeader::setTitle(const QString& text)
|
||||
{
|
||||
m_title->setText(text);
|
||||
}
|
||||
|
||||
void ScreenHeader::setSubTitle(const QString& text)
|
||||
{
|
||||
m_subTitle->setText(text);
|
||||
}
|
||||
|
||||
QPushButton* ScreenHeader::backButton()
|
||||
{
|
||||
return m_backButton;
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QFrame>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ScreenHeader
|
||||
: public QFrame
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
ScreenHeader(QWidget* parent = nullptr);
|
||||
|
||||
void setTitle(const QString& text);
|
||||
void setSubTitle(const QString& text);
|
||||
|
||||
QPushButton* backButton();
|
||||
|
||||
private:
|
||||
QLabel* m_title;
|
||||
QLabel* m_subTitle;
|
||||
QPushButton* m_backButton;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -41,12 +41,27 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual bool IsTab()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual QString GetTabText()
|
||||
{
|
||||
return tr("Missing");
|
||||
}
|
||||
|
||||
//! Notify this screen it is the current screen
|
||||
virtual void NotifyCurrentScreen()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
signals:
|
||||
void ChangeScreenRequest(ProjectManagerScreen screen);
|
||||
void GotoPreviousScreenRequest();
|
||||
void ResetScreenRequest(ProjectManagerScreen screen);
|
||||
void NotifyCurrentProject(const QString& projectPath);
|
||||
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <ScreenFactory.h>
|
||||
#include <ScreenWidget.h>
|
||||
|
||||
#include <QTabWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
@@ -21,17 +22,19 @@ namespace O3DE::ProjectManager
|
||||
ScreensCtrl::ScreensCtrl(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setObjectName("ScreensCtrl");
|
||||
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setMargin(0);
|
||||
vLayout->setSpacing(0);
|
||||
vLayout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(vLayout);
|
||||
|
||||
m_screenStack = new QStackedWidget();
|
||||
vLayout->addWidget(m_screenStack);
|
||||
|
||||
//Track the bottom of the stack
|
||||
m_screenVisitOrder.push(ProjectManagerScreen::Invalid);
|
||||
// add a tab widget at the bottom of the stack
|
||||
m_tabWidget = new QTabWidget();
|
||||
m_screenStack->addWidget(m_tabWidget);
|
||||
connect(m_tabWidget, &QTabWidget::currentChanged, this, &ScreensCtrl::TabChanged);
|
||||
}
|
||||
|
||||
void ScreensCtrl::BuildScreens(QVector<ProjectManagerScreen> screens)
|
||||
@@ -57,7 +60,14 @@ namespace O3DE::ProjectManager
|
||||
|
||||
ScreenWidget* ScreensCtrl::GetCurrentScreen()
|
||||
{
|
||||
return reinterpret_cast<ScreenWidget*>(m_screenStack->currentWidget());
|
||||
if (m_screenStack->currentWidget() == m_tabWidget)
|
||||
{
|
||||
return reinterpret_cast<ScreenWidget*>(m_tabWidget->currentWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<ScreenWidget*>(m_screenStack->currentWidget());
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreensCtrl::ChangeToScreen(ProjectManagerScreen screen)
|
||||
@@ -79,13 +89,28 @@ namespace O3DE::ProjectManager
|
||||
if (iterator != m_screenMap.end())
|
||||
{
|
||||
ScreenWidget* currentScreen = GetCurrentScreen();
|
||||
if (currentScreen != iterator.value())
|
||||
ScreenWidget* newScreen = iterator.value();
|
||||
|
||||
if (currentScreen != newScreen)
|
||||
{
|
||||
if (addVisit)
|
||||
{
|
||||
m_screenVisitOrder.push(currentScreen->GetScreenEnum());
|
||||
ProjectManagerScreen oldScreen = currentScreen->GetScreenEnum();
|
||||
m_screenVisitOrder.push(oldScreen);
|
||||
}
|
||||
m_screenStack->setCurrentWidget(iterator.value());
|
||||
|
||||
if (newScreen->IsTab())
|
||||
{
|
||||
m_tabWidget->setCurrentWidget(newScreen);
|
||||
m_screenStack->setCurrentWidget(m_tabWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_screenStack->setCurrentWidget(newScreen);
|
||||
}
|
||||
|
||||
newScreen->NotifyCurrentScreen();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -95,23 +120,46 @@ namespace O3DE::ProjectManager
|
||||
|
||||
bool ScreensCtrl::GotoPreviousScreen()
|
||||
{
|
||||
// Don't go back if we are on the first set screen
|
||||
if (m_screenVisitOrder.top() != ProjectManagerScreen::Invalid)
|
||||
if (!m_screenVisitOrder.isEmpty())
|
||||
{
|
||||
// We do not check with screen if we can go back, we should always be able to go back
|
||||
return ForceChangeToScreen(m_screenVisitOrder.pop(), false);
|
||||
ProjectManagerScreen previousScreen = m_screenVisitOrder.pop();
|
||||
return ForceChangeToScreen(previousScreen, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScreensCtrl::ResetScreen(ProjectManagerScreen screen)
|
||||
{
|
||||
bool shouldRestoreCurrentScreen = false;
|
||||
if (GetCurrentScreen() && GetCurrentScreen()->GetScreenEnum() == screen)
|
||||
{
|
||||
shouldRestoreCurrentScreen = true;
|
||||
}
|
||||
|
||||
// Delete old screen if it exists to start fresh
|
||||
DeleteScreen(screen);
|
||||
|
||||
// Add new screen
|
||||
ScreenWidget* newScreen = BuildScreen(this, screen);
|
||||
m_screenStack->addWidget(newScreen);
|
||||
if (newScreen->IsTab())
|
||||
{
|
||||
m_tabWidget->addTab(newScreen, newScreen->GetTabText());
|
||||
if (shouldRestoreCurrentScreen)
|
||||
{
|
||||
m_tabWidget->setCurrentWidget(newScreen);
|
||||
m_screenStack->setCurrentWidget(m_tabWidget);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_screenStack->addWidget(newScreen);
|
||||
if (shouldRestoreCurrentScreen)
|
||||
{
|
||||
m_screenStack->setCurrentWidget(newScreen);
|
||||
}
|
||||
}
|
||||
|
||||
m_screenMap.insert(screen, newScreen);
|
||||
|
||||
connect(newScreen, &ScreenWidget::ChangeScreenRequest, this, &ScreensCtrl::ChangeToScreen);
|
||||
@@ -134,8 +182,21 @@ namespace O3DE::ProjectManager
|
||||
const auto iter = m_screenMap.find(screen);
|
||||
if (iter != m_screenMap.end())
|
||||
{
|
||||
m_screenStack->removeWidget(iter.value());
|
||||
iter.value()->deleteLater();
|
||||
ScreenWidget* screenToDelete = iter.value();
|
||||
if (screenToDelete->IsTab())
|
||||
{
|
||||
int tabIndex = m_tabWidget->indexOf(screenToDelete);
|
||||
if (tabIndex > -1)
|
||||
{
|
||||
m_tabWidget->removeTab(tabIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the screen we delete is the current widget, a new one will
|
||||
// be selected automatically (randomly?)
|
||||
m_screenStack->removeWidget(screenToDelete);
|
||||
}
|
||||
|
||||
// Erase does not cause a rehash so interators remain valid
|
||||
m_screenMap.erase(iter);
|
||||
@@ -150,4 +211,12 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
void ScreensCtrl::TabChanged([[maybe_unused]] int index)
|
||||
{
|
||||
ScreenWidget* screen = reinterpret_cast<ScreenWidget*>(m_tabWidget->currentWidget());
|
||||
if (screen)
|
||||
{
|
||||
screen->NotifyCurrentScreen();
|
||||
}
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <QStack>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QTabWidget)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ScreenWidget;
|
||||
@@ -46,11 +48,13 @@ namespace O3DE::ProjectManager
|
||||
void ResetAllScreens();
|
||||
void DeleteScreen(ProjectManagerScreen screen);
|
||||
void DeleteAllScreens();
|
||||
void TabChanged(int index);
|
||||
|
||||
private:
|
||||
QStackedWidget* m_screenStack;
|
||||
QHash<ProjectManagerScreen, ScreenWidget*> m_screenMap;
|
||||
QStack<ProjectManagerScreen> m_screenVisitOrder;
|
||||
QTabWidget* m_tabWidget;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace O3DE::ProjectManager
|
||||
auto result = PythonBindingsInterface::Get()->UpdateProject(m_projectInfo);
|
||||
if (result)
|
||||
{
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::Projects);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -35,7 +35,6 @@ int main(int argc, char* argv[])
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
|
||||
|
||||
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
|
||||
int runSuccess = 0;
|
||||
{
|
||||
@@ -55,6 +54,12 @@ int main(int argc, char* argv[])
|
||||
O3DE::ProjectManager::ProjectManagerWindow window(nullptr, engineRootPath);
|
||||
window.show();
|
||||
|
||||
// somethings is preventing us from moving the window to the center of the
|
||||
// primary screen - likely an Az style or component helper
|
||||
constexpr int width = 1200;
|
||||
constexpr int height = 800;
|
||||
window.resize(width, height);
|
||||
|
||||
runSuccess = app.exec();
|
||||
}
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
|
||||
|
||||
Reference in New Issue
Block a user