Project Template details and preview changes

main
Alex Peterson 5 years ago committed by GitHub
parent 74f474aae2
commit 9b17754278
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.02554 10L9 15.0362V18L0 9L9 0V2.98885L4 8H18V10H4.02554Z" fill="#1e70eb"/>
</svg>

After

Width:  |  Height:  |  Size: 230 B

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8358f4dad9878c662b9819b2b346622af691eb45f8eddc28fff79a50650ae6cf
size 2503

@ -7,6 +7,7 @@
<file>AddOffset.svg</file>
<file>AddOffset_Hover.svg</file>
<file>ArrowBack.svg</file>
<file>ArrowBack_Hover.svg</file>
<file>build.svg</file>
<file>FolderOffset.svg</file>
<file>FolderOffset_Hover.svg</file>
@ -18,6 +19,7 @@
<file>Linux.svg</file>
<file>macOS.svg</file>
<file>DefaultProjectImage.png</file>
<file>DefaultTemplate.png</file>
<file>ArrowDownLine.svg</file>
<file>ArrowUpLine.svg</file>
<file>o3de.svg</file>

@ -136,11 +136,9 @@ QTabBar::tab:pressed
#header QPushButton:focus {
border:none;
}
#header QPushButton:hover {
background:#333333 url(:/ArrowBack.svg) no-repeat center;
}
#header QPushButton:hover,
#header QPushButton:pressed {
background:#222222 url(:/ArrowBack.svg) no-repeat center;
background:transparent url(:/ArrowBack_Hover.svg) no-repeat center;
}
#headerTitle {
@ -210,9 +208,6 @@ QTabBar::tab:pressed
#projectTemplate {
margin: 55px 0 0 50px;
max-width: 780px;
min-height:200px;
max-height:200px;
}
#projectTemplateLabel {
font-size:16px;
@ -227,11 +222,67 @@ QTabBar::tab:pressed
#projectTemplateDetails {
background-color:#444444;
max-width:240px;
max-width:20%;
min-width:240px;
margin-left:30px;
}
#projectTemplateDetails #displayName,
#projectTemplateDetails #includedGemsTitle {
font-size:18px;
}
#projectTemplateDetails #moreGems {
font-size:14px;
margin-top:20px;
}
#projectTemplateDetails #includedGemsTitle {
margin-top:5px;
margin-bottom:5px;
}
#projectTemplateDetails #summary {
padding-bottom:0px;
border-bottom:2px solid #555555;
min-height:80px;
qproperty-alignment: AlignTop;
}
#projectTemplateDetails #browseCatalog {
margin:5px 0px 15px 0px;
}
#projectTemplate QPushButton {
qproperty-flat: true;
min-width: 96px;
max-width: 96px;
min-height: 160px;
max-height: 160px;
}
#projectTemplate #templateLabel {
qproperty-alignment: AlignCenter;
}
#projectTemplate QPushButton #templateImage {
border:3px solid transparent;
border-radius: 4px;
}
#projectTemplate QPushButton[Checked="true"] #templateImage {
border:3px solid #1e70eb;
}
#projectTemplate QPushButton[Checked="true"] #templateLabel {
font-weight:bold;
}
#projectTemplate QPushButton:hover {
background-color: #444444;
}
#projectTemplate QPushButton:focus {
outline: none;
border:none;
}
#projectSettingsTab::tab-bar {
left: 60px;
}

@ -15,6 +15,7 @@
#include <PythonBindingsInterface.h>
#include <NewProjectSettingsScreen.h>
#include <ScreenHeaderWidget.h>
#include <GemCatalog/GemCatalogScreen.h>
#include <QDialogButtonBox>
#include <QHBoxLayout>
@ -41,24 +42,33 @@ namespace O3DE::ProjectManager
m_stack = new QStackedWidget(this);
m_stack->setObjectName("body");
m_stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
m_stack->addWidget(new NewProjectSettingsScreen());
m_gemCatalog = new GemCatalogScreen();
m_stack->addWidget(m_gemCatalog);
m_stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding));
m_newProjectSettingsScreen = new NewProjectSettingsScreen(this);
m_stack->addWidget(m_newProjectSettingsScreen);
m_gemCatalogScreen = new GemCatalogScreen(this);
m_stack->addWidget(m_gemCatalogScreen);
vLayout->addWidget(m_stack);
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
backNextButtons->setObjectName("footer");
vLayout->addWidget(backNextButtons);
QDialogButtonBox* buttons = new QDialogButtonBox();
buttons->setObjectName("footer");
vLayout->addWidget(buttons);
m_backButton = backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
m_backButton->setProperty("secondary", true);
m_nextButton = backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole);
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
connect(m_newProjectSettingsScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest);
connect(m_backButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandleBackButton);
connect(m_nextButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandleNextButton);
m_secondaryButton = buttons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
m_secondaryButton->setProperty("secondary", true);
m_secondaryButton->setVisible(false);
connect(m_secondaryButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandleSecondaryButton);
Update();
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
m_primaryButton = buttons->addButton(tr("Create Project"), QDialogButtonBox::ApplyRole);
connect(m_primaryButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandlePrimaryButton);
setLayout(vLayout);
}
@ -80,8 +90,10 @@ namespace O3DE::ProjectManager
{
if (m_stack->currentIndex() > 0)
{
m_stack->setCurrentIndex(m_stack->currentIndex() - 1);
Update();
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
PreviousScreen();
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
}
else
{
@ -89,70 +101,121 @@ namespace O3DE::ProjectManager
}
}
void CreateProjectCtrl::HandleNextButton()
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
void CreateProjectCtrl::HandleSecondaryButton()
{
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
ProjectManagerScreen screenEnum = currentScreen->GetScreenEnum();
if (m_stack->currentIndex() > 0)
{
// return to Project Settings page
PreviousScreen();
}
else
{
// Configure Gems
NextScreen();
}
}
void CreateProjectCtrl::Update()
{
if (m_stack->currentWidget() == m_gemCatalogScreen)
{
m_header->setSubTitle(tr("Configure project with Gems"));
m_secondaryButton->setVisible(false);
}
else
{
m_header->setSubTitle(tr("Enter Project Details"));
m_secondaryButton->setVisible(true);
m_secondaryButton->setText(tr("Configure Gems"));
}
}
if (screenEnum == ProjectManagerScreen::NewProjectSettings)
void CreateProjectCtrl::OnChangeScreenRequest(ProjectManagerScreen screen)
{
if (screen == ProjectManagerScreen::GemCatalog)
{
HandleSecondaryButton();
}
else
{
auto newProjectScreen = reinterpret_cast<NewProjectSettingsScreen*>(currentScreen);
if (newProjectScreen)
emit ChangeScreenRequest(screen);
}
}
void CreateProjectCtrl::NextScreen()
{
if (m_stack->currentIndex() < m_stack->count())
{
if(CurrentScreenIsValid())
{
if (!newProjectScreen->Validate())
{
QMessageBox::critical(this, tr("Invalid project settings"), tr("Invalid project settings"));
return;
}
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
m_projectInfo = newProjectScreen->GetProjectInfo();
m_projectTemplatePath = newProjectScreen->GetProjectTemplatePath();
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
// The next page is the gem catalog. Gather the available gems that will be shown in the gem catalog.
m_gemCatalog->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/true);
Update();
}
else
{
QMessageBox::warning(this, tr("Invalid project settings"), tr("Please correct the indicated project settings and try again."));
}
}
}
if (m_stack->currentIndex() != m_stack->count() - 1)
void CreateProjectCtrl::PreviousScreen()
{
// we don't require the current screen to be valid when moving back
if (m_stack->currentIndex() > 0)
{
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
m_stack->setCurrentIndex(m_stack->currentIndex() - 1);
Update();
}
else
}
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
void CreateProjectCtrl::HandlePrimaryButton()
{
CreateProject();
}
bool CreateProjectCtrl::CurrentScreenIsValid()
{
if (m_stack->currentWidget() == m_newProjectSettingsScreen)
{
auto result = PythonBindingsInterface::Get()->CreateProject(m_projectTemplatePath, m_projectInfo);
return m_newProjectSettingsScreen->Validate();
}
return true;
}
void CreateProjectCtrl::CreateProject()
{
if (m_newProjectSettingsScreen->Validate())
{
ProjectInfo projectInfo = m_newProjectSettingsScreen->GetProjectInfo();
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
auto result = PythonBindingsInterface::Get()->CreateProject(projectTemplatePath, projectInfo);
if (result.IsSuccess())
{
// automatically register the project
PythonBindingsInterface::Get()->AddProject(m_projectInfo.m_path);
PythonBindingsInterface::Get()->AddProject(projectInfo.m_path);
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
m_gemCatalogScreen->EnableDisableGemsForProject(projectInfo.m_path);
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
// adding gems is not implemented yet because we don't know what targets to add or how to add them
emit ChangeScreenRequest(ProjectManagerScreen::Projects);
}
else
{
QMessageBox::critical(this, tr("Project creation failed"), tr("Failed to create project."));
}
// Enable/disable gems for the newly created project.
m_gemCatalog->EnableDisableGemsForProject(m_projectInfo.m_path);
}
}
void CreateProjectCtrl::Update()
{
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
if (currentScreen && currentScreen->GetScreenEnum() == ProjectManagerScreen::GemCatalog)
{
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"));
QMessageBox::warning(this, tr("Invalid project settings"), tr("Please correct the indicated project settings and try again."));
}
}

@ -14,9 +14,11 @@
#if !defined(Q_MOC_RUN)
#include <ScreenWidget.h>
#include <ProjectInfo.h>
#include <GemCatalog/GemCatalogScreen.h>
#endif
// due to current limitations, customizing template Gems is disabled
#define TEMPLATE_GEM_CONFIGURATION_ENABLED
QT_FORWARD_DECLARE_CLASS(QStackedWidget)
QT_FORWARD_DECLARE_CLASS(QPushButton)
QT_FORWARD_DECLARE_CLASS(QLabel)
@ -24,6 +26,8 @@ QT_FORWARD_DECLARE_CLASS(QLabel)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(ScreenHeader)
QT_FORWARD_DECLARE_CLASS(NewProjectSettingsScreen)
QT_FORWARD_DECLARE_CLASS(GemCatalogScreen)
class CreateProjectCtrl
: public ScreenWidget
@ -36,21 +40,37 @@ namespace O3DE::ProjectManager
protected slots:
void HandleBackButton();
void HandleNextButton();
void HandlePrimaryButton();
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
void OnChangeScreenRequest(ProjectManagerScreen screen);
void HandleSecondaryButton();
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
private:
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
void Update();
void NextScreen();
void PreviousScreen();
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
bool CurrentScreenIsValid();
void CreateProject();
QStackedWidget* m_stack;
ScreenHeader* m_header;
QStackedWidget* m_stack = nullptr;
ScreenHeader* m_header = nullptr;
QPushButton* m_backButton;
QPushButton* m_nextButton;
QPushButton* m_primaryButton = nullptr;
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
QPushButton* m_secondaryButton = nullptr;
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
QString m_projectTemplatePath;
ProjectInfo m_projectInfo;
GemCatalogScreen* m_gemCatalog = nullptr;
NewProjectSettingsScreen* m_newProjectSettingsScreen = nullptr;
GemCatalogScreen* m_gemCatalogScreen = nullptr;
};
} // namespace O3DE::ProjectManager

@ -14,8 +14,12 @@
#include <PythonBindingsInterface.h>
#include <FormLineEditWidget.h>
#include <FormBrowseEditWidget.h>
#include <TemplateButtonWidget.h>
#include <PathValidator.h>
#include <EngineInfo.h>
#include <CreateProjectCtrl.h>
#include <TagWidget.h>
#include <AzQtComponents/Components/FlowLayout.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
@ -28,10 +32,12 @@
#include <QSpacerItem>
#include <QStandardPaths>
#include <QFrame>
#include <QScrollArea>
#include <QAbstractButton>
namespace O3DE::ProjectManager
{
constexpr const char* k_pathProperty = "Path";
constexpr const char* k_templateIndexProperty = "TemplateIndex";
NewProjectSettingsScreen::NewProjectSettingsScreen(QWidget* parent)
: ProjectSettingsScreen(parent)
@ -59,30 +65,69 @@ namespace O3DE::ProjectManager
projectTemplateDetailsLabel->setObjectName("projectTemplateDetailsLabel");
containerLayout->addWidget(projectTemplateDetailsLabel);
QHBoxLayout* templateLayout = new QHBoxLayout(this);
containerLayout->addItem(templateLayout);
// we might have enough templates that we need to scroll
QScrollArea* templatesScrollArea = new QScrollArea(this);
QWidget* scrollWidget = new QWidget();
FlowLayout* flowLayout = new FlowLayout(0, s_spacerSize, s_spacerSize);
scrollWidget->setLayout(flowLayout);
templatesScrollArea->setWidget(scrollWidget);
templatesScrollArea->setWidgetResizable(true);
m_projectTemplateButtonGroup = new QButtonGroup(this);
m_projectTemplateButtonGroup->setObjectName("templateButtonGroup");
// QButtonGroup has overloaded buttonClicked methods so we need the QOverload
connect(
m_projectTemplateButtonGroup, QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked), this,
[=](QAbstractButton* button)
{
if (button && button->property(k_templateIndexProperty).isValid())
{
int projectIndex = button->property(k_templateIndexProperty).toInt();
UpdateTemplateDetails(m_templates.at(projectIndex));
}
});
auto templatesResult = PythonBindingsInterface::Get()->GetProjectTemplates();
if (templatesResult.IsSuccess() && !templatesResult.GetValue().isEmpty())
{
for (const ProjectTemplateInfo& projectTemplate : templatesResult.GetValue())
m_templates = templatesResult.GetValue();
// sort alphabetically by display name because they could be in any order
std::sort(m_templates.begin(), m_templates.end(), [](const ProjectTemplateInfo& arg1, const ProjectTemplateInfo& arg2)
{
QRadioButton* radioButton = new QRadioButton(projectTemplate.m_name, this);
radioButton->setProperty(k_pathProperty, projectTemplate.m_path);
m_projectTemplateButtonGroup->addButton(radioButton);
return arg1.m_displayName.toLower() < arg2.m_displayName.toLower();
});
containerLayout->addWidget(radioButton);
for (int index = 0; index < m_templates.size(); ++index)
{
ProjectTemplateInfo projectTemplate = m_templates.at(index);
QString projectPreviewPath = projectTemplate.m_path + "/Template/preview.png";
QFileInfo doesPreviewExist(projectPreviewPath);
if (!doesPreviewExist.exists() || !doesPreviewExist.isFile())
{
projectPreviewPath = ":/DefaultTemplate.png";
}
TemplateButton* templateButton = new TemplateButton(projectPreviewPath, projectTemplate.m_displayName, this);
templateButton->setCheckable(true);
templateButton->setProperty(k_templateIndexProperty, index);
m_projectTemplateButtonGroup->addButton(templateButton);
flowLayout->addWidget(templateButton);
}
m_projectTemplateButtonGroup->buttons().first()->setChecked(true);
}
containerLayout->addWidget(templatesScrollArea);
}
projectTemplateWidget->setLayout(containerLayout);
m_verticalLayout->addWidget(projectTemplateWidget);
QWidget* projectTemplateDetails = new QWidget(this);
QFrame* projectTemplateDetails = CreateTemplateDetails(s_templateDetailsContentMargin);
projectTemplateDetails->setObjectName("projectTemplateDetails");
m_horizontalLayout->addWidget(projectTemplateDetails);
}
@ -109,11 +154,71 @@ namespace O3DE::ProjectManager
void NewProjectSettingsScreen::NotifyCurrentScreen()
{
if (!m_templates.isEmpty())
{
UpdateTemplateDetails(m_templates.first());
}
Validate();
}
QString NewProjectSettingsScreen::GetProjectTemplatePath()
{
return m_projectTemplateButtonGroup->checkedButton()->property(k_pathProperty).toString();
const int templateIndex = m_projectTemplateButtonGroup->checkedButton()->property(k_templateIndexProperty).toInt();
return m_templates.at(templateIndex).m_path;
}
QFrame* NewProjectSettingsScreen::CreateTemplateDetails(int margin)
{
QFrame* projectTemplateDetails = new QFrame(this);
projectTemplateDetails->setObjectName("projectTemplateDetails");
QVBoxLayout* templateDetailsLayout = new QVBoxLayout();
templateDetailsLayout->setContentsMargins(margin, margin, margin, margin);
templateDetailsLayout->setAlignment(Qt::AlignTop);
{
m_templateDisplayName = new QLabel(this);
m_templateDisplayName->setObjectName("displayName");
templateDetailsLayout->addWidget(m_templateDisplayName);
m_templateSummary = new QLabel(this);
m_templateSummary->setObjectName("summary");
m_templateSummary->setWordWrap(true);
templateDetailsLayout->addWidget(m_templateSummary);
QLabel* includedGemsTitle = new QLabel(tr("Included Gems"), this);
includedGemsTitle->setObjectName("includedGemsTitle");
templateDetailsLayout->addWidget(includedGemsTitle);
m_templateIncludedGems = new TagContainerWidget(this);
m_templateIncludedGems->setObjectName("includedGems");
templateDetailsLayout->addWidget(m_templateIncludedGems);
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
QLabel* moreGemsLabel = new QLabel(tr("Looking for more Gems?"), this);
moreGemsLabel->setObjectName("moreGems");
templateDetailsLayout->addWidget(moreGemsLabel);
QLabel* browseCatalogLabel = new QLabel(tr("Browse the Gems Catalog to further customize your project."), this);
browseCatalogLabel->setObjectName("browseCatalog");
browseCatalogLabel->setWordWrap(true);
templateDetailsLayout->addWidget(browseCatalogLabel);
QPushButton* configureGemsButton = new QPushButton(tr("Configure with more Gems"), this);
connect(configureGemsButton, &QPushButton::clicked, this, [=]()
{
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
});
templateDetailsLayout->addWidget(configureGemsButton);
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
}
projectTemplateDetails->setLayout(templateDetailsLayout);
return projectTemplateDetails;
}
void NewProjectSettingsScreen::UpdateTemplateDetails(const ProjectTemplateInfo& templateInfo)
{
m_templateDisplayName->setText(templateInfo.m_displayName);
m_templateSummary->setText(templateInfo.m_summary);
m_templateIncludedGems->Update(templateInfo.m_includedGems);
}
} // namespace O3DE::ProjectManager

@ -13,12 +13,17 @@
#if !defined(Q_MOC_RUN)
#include <ProjectSettingsScreen.h>
#include <ProjectTemplateInfo.h>
#include <QVector>
#endif
QT_FORWARD_DECLARE_CLASS(QButtonGroup)
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QFrame)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(TagContainerWidget)
class NewProjectSettingsScreen
: public ProjectSettingsScreen
{
@ -33,8 +38,17 @@ namespace O3DE::ProjectManager
private:
QString GetDefaultProjectPath();
QFrame* CreateTemplateDetails(int margin);
void UpdateTemplateDetails(const ProjectTemplateInfo& templateInfo);
QButtonGroup* m_projectTemplateButtonGroup;
QLabel* m_templateDisplayName;
QLabel* m_templateSummary;
TagContainerWidget* m_templateIncludedGems;
QVector<ProjectTemplateInfo> m_templates;
inline constexpr static int s_spacerSize = 20;
inline constexpr static int s_templateDetailsContentMargin = 20;
};
} // namespace O3DE::ProjectManager

@ -31,6 +31,7 @@ namespace O3DE::ProjectManager
QString m_name;
QString m_path;
QString m_summary;
QStringList m_includedGems;
QStringList m_canonicalTags;
QStringList m_userTags;
};

@ -754,7 +754,7 @@ namespace O3DE::ProjectManager
ProjectTemplateInfo PythonBindings::ProjectTemplateInfoFromPath(pybind11::handle path)
{
ProjectTemplateInfo templateInfo;
templateInfo.m_path = Py_To_String(path);
templateInfo.m_path = Py_To_String(pybind11::str(path));
auto data = m_manifest.attr("get_template_json_data")(pybind11::none(), path);
if (pybind11::isinstance<pybind11::dict>(data))
@ -781,6 +781,13 @@ namespace O3DE::ProjectManager
templateInfo.m_canonicalTags.push_back(Py_To_String(tag));
}
}
if (data.contains("included_gems"))
{
for (auto gem : data["included_gems"])
{
templateInfo.m_includedGems.push_back(Py_To_String(gem));
}
}
}
catch ([[maybe_unused]] const std::exception& e)
{

@ -0,0 +1,65 @@
/*
* 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 <TemplateButtonWidget.h>
#include <QVBoxLayout>
#include <QLabel>
#include <QPixmap>
#include <QAbstractButton>
#include <QStyle>
#include <QVariant>
namespace O3DE::ProjectManager
{
TemplateButton::TemplateButton(const QString& imagePath, const QString& labelText, QWidget* parent)
: QPushButton(parent)
{
setAutoExclusive(true);
setObjectName("templateButton");
QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setSpacing(0);
vLayout->setContentsMargins(0, 0, 0, 0);
setLayout(vLayout);
QLabel* image = new QLabel(this);
image->setObjectName("templateImage");
image->setPixmap(
QPixmap(imagePath).scaled(QSize(s_templateImageWidth,s_templateImageHeight) , Qt::KeepAspectRatio, Qt::SmoothTransformation));
vLayout->addWidget(image);
QLabel* label = new QLabel(labelText, this);
label->setObjectName("templateLabel");
vLayout->addWidget(label);
connect(this, &QAbstractButton::toggled, this, &TemplateButton::onToggled);
}
void TemplateButton::onToggled()
{
setProperty("Checked", isChecked());
// we must unpolish/polish every child after changing a property
// or else they won't use the correct stylesheet selector
for (auto child : findChildren<QWidget*>())
{
child->style()->unpolish(child);
child->style()->polish(child);
}
style()->unpolish(this);
style()->polish(this);
}
} // namespace O3DE::ProjectManager

@ -0,0 +1,37 @@
/*
* 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 <QPushButton>
#endif
namespace O3DE::ProjectManager
{
class TemplateButton
: public QPushButton
{
Q_OBJECT // AUTOMOC
public:
explicit TemplateButton(const QString& imagePath, const QString& labelText, QWidget* parent = nullptr);
~TemplateButton() = default;
protected slots:
void onToggled();
private:
inline constexpr static int s_templateImageWidth = 92;
inline constexpr static int s_templateImageHeight = 122;
};
} // namespace O3DE::ProjectManager

@ -60,6 +60,8 @@ set(FILES
Source/LinkWidget.cpp
Source/TagWidget.h
Source/TagWidget.cpp
Source/TemplateButtonWidget.h
Source/TemplateButtonWidget.cpp
Source/GemCatalog/GemCatalogHeaderWidget.h
Source/GemCatalog/GemCatalogHeaderWidget.cpp
Source/GemCatalog/GemCatalogScreen.h

@ -4,8 +4,9 @@
"restricted_platform_relative_path": "Templates",
"origin": "The primary repo for DefaultProject goes here: i.e. http://www.mydomain.com",
"license": "What license DefaultProject uses goes here: i.e. https://opensource.org/licenses/MIT",
"display_name": "DefaultProject",
"display_name": "Default",
"summary": "A short description of DefaultProject.",
"included_gems": ["Atom","Camera","EMotionFX","UI","Maestro","Input","ImGui"],
"canonical_tags": [],
"user_tags": [
"DefaultProject"
@ -651,4 +652,4 @@
"origin": "Shaders"
}
]
}
}

Loading…
Cancel
Save