Merge branch 'stabilization/2110' of https://github.com/aws-lumberyard/o3de into Prism/CLIDisplayLastError

Signed-off-by: AMZN-Phil <pconroy@amazon.com>
This commit is contained in:
AMZN-Phil
2021-11-17 14:43:03 -08:00
65 changed files with 805 additions and 390 deletions
@@ -15,6 +15,7 @@
#include <GemCatalog/GemCatalogScreen.h>
#include <GemRepo/GemRepoScreen.h>
#include <ProjectUtils.h>
#include <DownloadController.h>
#include <QDialogButtonBox>
#include <QHBoxLayout>
@@ -72,12 +72,7 @@ namespace O3DE::ProjectManager
bool EngineScreenCtrl::ContainsScreen(ProjectManagerScreen screen)
{
if (screen == m_engineSettingsScreen->GetScreenEnum() || screen == m_gemRepoScreen->GetScreenEnum())
{
return true;
}
return false;
return screen == m_engineSettingsScreen->GetScreenEnum() || screen == m_gemRepoScreen->GetScreenEnum();
}
void EngineScreenCtrl::NotifyCurrentScreen()
@@ -7,25 +7,32 @@
*/
#include <GemCatalog/GemCatalogHeaderWidget.h>
#include <TagWidget.h>
#include <AzCore/std/functional.h>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QLabel>
#include <QPushButton>
#include <QProgressBar>
#include <TagWidget.h>
#include <QMenu>
#include <QLocale>
#include <QMovie>
#include <QPainter>
#include <QPainterPath>
namespace O3DE::ProjectManager
{
CartOverlayWidget::CartOverlayWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent)
: QWidget(parent)
GemCartWidget::GemCartWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent)
: QScrollArea(parent)
, m_gemModel(gemModel)
, m_downloadController(downloadController)
{
setObjectName("GemCatalogCart");
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_layout = new QVBoxLayout();
m_layout->setSpacing(0);
@@ -118,17 +125,15 @@ namespace O3DE::ProjectManager
}
return dependencies;
});
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
}
CartOverlayWidget::~CartOverlayWidget()
GemCartWidget::~GemCartWidget()
{
// disconnect from all download controller signals
disconnect(m_downloadController, nullptr, this, nullptr);
}
void CartOverlayWidget::CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices)
void GemCartWidget::CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices)
{
QWidget* widget = new QWidget();
widget->setFixedWidth(s_width);
@@ -164,12 +169,12 @@ namespace O3DE::ProjectManager
update();
}
void CartOverlayWidget::OnCancelDownloadActivated(const QString& gemName)
void GemCartWidget::OnCancelDownloadActivated(const QString& gemName)
{
m_downloadController->CancelGemDownload(gemName);
}
void CartOverlayWidget::CreateDownloadSection()
void GemCartWidget::CreateDownloadSection()
{
m_downloadSectionWidget = new QWidget();
m_downloadSectionWidget->setFixedWidth(s_width);
@@ -223,12 +228,12 @@ namespace O3DE::ProjectManager
}
// connect to download controller data changed
connect(m_downloadController, &DownloadController::GemDownloadAdded, this, &CartOverlayWidget::GemDownloadAdded);
connect(m_downloadController, &DownloadController::GemDownloadRemoved, this, &CartOverlayWidget::GemDownloadRemoved);
connect(m_downloadController, &DownloadController::GemDownloadProgress, this, &CartOverlayWidget::GemDownloadProgress);
connect(m_downloadController, &DownloadController::GemDownloadAdded, this, &GemCartWidget::GemDownloadAdded);
connect(m_downloadController, &DownloadController::GemDownloadRemoved, this, &GemCartWidget::GemDownloadRemoved);
connect(m_downloadController, &DownloadController::GemDownloadProgress, this, &GemCartWidget::GemDownloadProgress);
}
void CartOverlayWidget::GemDownloadAdded(const QString& gemName)
void GemCartWidget::GemDownloadAdded(const QString& gemName)
{
// Containing widget for the current download item
QWidget* newGemDownloadWidget = new QWidget();
@@ -246,7 +251,7 @@ namespace O3DE::ProjectManager
nameProgressLayout->addStretch();
QLabel* cancelText = new QLabel(tr("<a href=\"%1\">Cancel</a>").arg(gemName), newGemDownloadWidget);
cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated);
connect(cancelText, &QLabel::linkActivated, this, &GemCartWidget::OnCancelDownloadActivated);
nameProgressLayout->addWidget(cancelText);
downloadingGemLayout->addLayout(nameProgressLayout);
@@ -267,7 +272,7 @@ namespace O3DE::ProjectManager
m_downloadingListWidget->show();
}
void CartOverlayWidget::GemDownloadRemoved(const QString& gemName)
void GemCartWidget::GemDownloadRemoved(const QString& gemName)
{
QWidget* gemToRemove = m_downloadingListWidget->findChild<QWidget*>(gemName);
if (gemToRemove)
@@ -289,7 +294,7 @@ namespace O3DE::ProjectManager
}
}
void CartOverlayWidget::GemDownloadProgress(const QString& gemName, int bytesDownloaded, int totalBytes)
void GemCartWidget::GemDownloadProgress(const QString& gemName, int bytesDownloaded, int totalBytes)
{
QWidget* gemToUpdate = m_downloadingListWidget->findChild<QWidget*>(gemName);
if (gemToUpdate)
@@ -324,7 +329,7 @@ namespace O3DE::ProjectManager
}
}
QVector<Tag> CartOverlayWidget::GetTagsFromModelIndices(const QVector<QModelIndex>& gems) const
QVector<Tag> GemCartWidget::GetTagsFromModelIndices(const QVector<QModelIndex>& gems) const
{
QVector<Tag> tags;
tags.reserve(gems.size());
@@ -349,7 +354,7 @@ namespace O3DE::ProjectManager
iconButton->setFocusPolicy(Qt::NoFocus);
iconButton->setIcon(QIcon(":/Summary.svg"));
iconButton->setFixedSize(s_iconSize, s_iconSize);
connect(iconButton, &QPushButton::clicked, this, &CartButton::ShowOverlay);
connect(iconButton, &QPushButton::clicked, this, &CartButton::ShowGemCart);
m_layout->addWidget(iconButton);
m_countLabel = new QLabel();
@@ -362,7 +367,7 @@ namespace O3DE::ProjectManager
m_dropDownButton->setFocusPolicy(Qt::NoFocus);
m_dropDownButton->setIcon(QIcon(":/CarrotArrowDown.svg"));
m_dropDownButton->setFixedSize(s_arrowDownIconSize, s_arrowDownIconSize);
connect(m_dropDownButton, &QPushButton::clicked, this, &CartButton::ShowOverlay);
connect(m_dropDownButton, &QPushButton::clicked, this, &CartButton::ShowGemCart);
m_layout->addWidget(m_dropDownButton);
// Adjust the label text whenever the model gets updated.
@@ -377,28 +382,28 @@ namespace O3DE::ProjectManager
m_dropDownButton->setVisible(!toBeAdded.isEmpty() || !toBeRemoved.isEmpty());
// Automatically close the overlay window in case there are no gems to be activated or deactivated anymore.
if (m_cartOverlay && toBeAdded.isEmpty() && toBeRemoved.isEmpty())
if (m_gemCart && toBeAdded.isEmpty() && toBeRemoved.isEmpty())
{
m_cartOverlay->deleteLater();
m_cartOverlay = nullptr;
m_gemCart->deleteLater();
m_gemCart = nullptr;
}
});
}
void CartButton::mousePressEvent([[maybe_unused]] QMouseEvent* event)
{
ShowOverlay();
ShowGemCart();
}
void CartButton::hideEvent(QHideEvent*)
{
if (m_cartOverlay)
if (m_gemCart)
{
m_cartOverlay->hide();
m_gemCart->hide();
}
}
void CartButton::ShowOverlay()
void CartButton::ShowGemCart()
{
const QVector<QModelIndex> toBeAdded = m_gemModel->GatherGemsToBeAdded(/*includeDependencies=*/true);
const QVector<QModelIndex> toBeRemoved = m_gemModel->GatherGemsToBeRemoved(/*includeDependencies=*/true);
@@ -407,37 +412,33 @@ namespace O3DE::ProjectManager
return;
}
if (m_cartOverlay)
if (m_gemCart)
{
// Directly delete the former overlay before creating the new one.
// Don't use deleteLater() here. This might overwrite the new overlay pointer
// depending on the event queue.
delete m_cartOverlay;
delete m_gemCart;
}
m_cartOverlay = new CartOverlayWidget(m_gemModel, m_downloadController, this);
connect(m_cartOverlay, &QWidget::destroyed, this, [=]
m_gemCart = new GemCartWidget(m_gemModel, m_downloadController, this);
connect(m_gemCart, &QWidget::destroyed, this, [=]
{
// Reset the overlay pointer on destruction to prevent dangling pointers.
m_cartOverlay = nullptr;
m_gemCart = nullptr;
// Tell header gem cart is no longer open
UpdateGemCart(nullptr);
});
m_cartOverlay->show();
m_gemCart->show();
const QPoint parentPos = m_dropDownButton->mapToParent(m_dropDownButton->pos());
const QPoint globalPos = m_dropDownButton->mapToGlobal(m_dropDownButton->pos());
const QPoint offset(-4, 10);
m_cartOverlay->setGeometry(globalPos.x() - parentPos.x() - m_cartOverlay->width() + width() + offset.x(),
globalPos.y() + offset.y(),
m_cartOverlay->width(),
m_cartOverlay->height());
emit UpdateGemCart(m_gemCart);
}
CartButton::~CartButton()
{
// Make sure the overlay window is automatically closed in case the gem catalog is destroyed.
if (m_cartOverlay)
if (m_gemCart)
{
m_cartOverlay->deleteLater();
m_gemCart->deleteLater();
}
}
@@ -514,6 +515,17 @@ namespace O3DE::ProjectManager
connect(m_downloadController, &DownloadController::GemDownloadAdded, this, &GemCatalogHeaderWidget::GemDownloadAdded);
connect(m_downloadController, &DownloadController::GemDownloadRemoved, this, &GemCatalogHeaderWidget::GemDownloadRemoved);
connect(
m_cartButton, &CartButton::UpdateGemCart, this,
[this](QWidget* gemCart)
{
GemCartShown(gemCart);
if (gemCart)
{
emit UpdateGemCart(gemCart);
}
});
}
void GemCatalogHeaderWidget::GemDownloadAdded(const QString& /*gemName*/)
@@ -521,7 +533,7 @@ namespace O3DE::ProjectManager
m_downloadSpinner->show();
m_downloadLabel->show();
m_downloadSpinnerMovie->start();
m_cartButton->ShowOverlay();
m_cartButton->ShowGemCart();
}
void GemCatalogHeaderWidget::GemDownloadRemoved(const QString& /*gemName*/)
@@ -534,8 +546,44 @@ namespace O3DE::ProjectManager
}
}
void GemCatalogHeaderWidget::GemCartShown(bool state)
{
m_showGemCart = state;
repaint();
}
void GemCatalogHeaderWidget::ReinitForProject()
{
m_filterLineEdit->setText({});
}
void GemCatalogHeaderWidget::paintEvent([[maybe_unused]] QPaintEvent* event)
{
// Only show triangle when cart is shown
if (!m_showGemCart)
{
return;
}
const QPoint buttonPos = m_cartButton->pos();
const QSize buttonSize = m_cartButton->size();
// Draw isosceles triangle with top point touching bottom of cartButton
// Bottom aligned with header bottom and top of right panel
const QPoint topPoint(buttonPos.x() + buttonSize.width() / 2, buttonPos.y() + buttonSize.height());
const QPoint bottomLeftPoint(topPoint.x() - 20, height());
const QPoint bottomRightPoint(topPoint.x() + 20, height());
QPainterPath trianglePath;
trianglePath.moveTo(topPoint);
trianglePath.lineTo(bottomLeftPoint);
trianglePath.lineTo(bottomRightPoint);
trianglePath.lineTo(topPoint);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(Qt::NoPen);
painter.fillPath(trianglePath, QBrush(QColor("#555555")));
}
} // namespace O3DE::ProjectManager
@@ -14,8 +14,10 @@
#include <GemCatalog/GemModel.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <TagWidget.h>
#include <QFrame>
#include <DownloadController.h>
#include <QFrame>
#include <QScrollArea>
#endif
QT_FORWARD_DECLARE_CLASS(QPushButton)
@@ -28,14 +30,14 @@ QT_FORWARD_DECLARE_CLASS(QMovie)
namespace O3DE::ProjectManager
{
class CartOverlayWidget
: public QWidget
class GemCartWidget
: public QScrollArea
{
Q_OBJECT // AUTOMOC
public:
CartOverlayWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr);
~CartOverlayWidget();
GemCartWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr);
~GemCartWidget();
public slots:
void GemDownloadAdded(const QString& gemName);
@@ -68,7 +70,10 @@ namespace O3DE::ProjectManager
public:
CartButton(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr);
~CartButton();
void ShowOverlay();
void ShowGemCart();
signals:
void UpdateGemCart(QWidget* gemCart);
private:
void mousePressEvent(QMouseEvent* event) override;
@@ -78,7 +83,7 @@ namespace O3DE::ProjectManager
QHBoxLayout* m_layout = nullptr;
QLabel* m_countLabel = nullptr;
QPushButton* m_dropDownButton = nullptr;
CartOverlayWidget* m_cartOverlay = nullptr;
GemCartWidget* m_gemCart = nullptr;
DownloadController* m_downloadController = nullptr;
inline constexpr static int s_iconSize = 24;
@@ -99,11 +104,16 @@ namespace O3DE::ProjectManager
public slots:
void GemDownloadAdded(const QString& gemName);
void GemDownloadRemoved(const QString& gemName);
void GemCartShown(bool state = false);
signals:
void AddGem();
void OpenGemsRepo();
void RefreshGems();
void UpdateGemCart(QWidget* gemCart);
protected slots:
void paintEvent(QPaintEvent* event) override;
private:
AzQtComponents::SearchLineEdit* m_filterLineEdit = nullptr;
@@ -113,5 +123,6 @@ namespace O3DE::ProjectManager
QLabel* m_downloadLabel = nullptr;
QMovie* m_downloadSpinnerMovie = nullptr;
CartButton* m_cartButton = nullptr;
bool m_showGemCart = false;
};
} // namespace O3DE::ProjectManager
@@ -8,6 +8,11 @@
#include <GemCatalog/GemCatalogScreen.h>
#include <PythonBindingsInterface.h>
#include <GemCatalog/GemCatalogHeaderWidget.h>
#include <GemCatalog/GemFilterWidget.h>
#include <GemCatalog/GemListView.h>
#include <GemCatalog/GemInspector.h>
#include <GemCatalog/GemModel.h>
#include <GemCatalog/GemListHeaderWidget.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <GemCatalog/GemRequirementDialog.h>
@@ -28,6 +33,7 @@
#include <QFileDialog>
#include <QMessageBox>
#include <QHash>
#include <QStackedWidget>
namespace O3DE::ProjectManager
{
@@ -51,9 +57,11 @@ namespace O3DE::ProjectManager
vLayout->addWidget(m_headerWidget);
connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged);
connect(m_gemModel->GetSelectionModel(), &QItemSelectionModel::selectionChanged, this, [this]{ ShowInspector(); });
connect(m_headerWidget, &GemCatalogHeaderWidget::RefreshGems, this, &GemCatalogScreen::Refresh);
connect(m_headerWidget, &GemCatalogHeaderWidget::OpenGemsRepo, this, &GemCatalogScreen::HandleOpenGemRepo);
connect(m_headerWidget, &GemCatalogHeaderWidget::AddGem, this, &GemCatalogScreen::OnAddGemClicked);
connect(m_headerWidget, &GemCatalogHeaderWidget::UpdateGemCart, this, &GemCatalogScreen::UpdateAndShowGemCart);
connect(m_downloadController, &DownloadController::Done, this, &GemCatalogScreen::OnGemDownloadResult);
QHBoxLayout* hLayout = new QHBoxLayout();
@@ -61,8 +69,11 @@ namespace O3DE::ProjectManager
vLayout->addLayout(hLayout);
m_gemListView = new GemListView(m_proxyModel, m_proxyModel->GetSelectionModel(), this);
m_rightPanelStack = new QStackedWidget(this);
m_rightPanelStack->setFixedWidth(240);
m_gemInspector = new GemInspector(m_gemModel, this);
m_gemInspector->setFixedWidth(240);
connect(m_gemInspector, &GemInspector::TagClicked, [=](const Tag& tag) { SelectGem(tag.id); });
connect(m_gemInspector, &GemInspector::UpdateGem, this, &GemCatalogScreen::UpdateGem);
@@ -85,7 +96,9 @@ namespace O3DE::ProjectManager
hLayout->addWidget(filterWidget);
hLayout->addLayout(middleVLayout);
hLayout->addWidget(m_gemInspector);
hLayout->addWidget(m_rightPanelStack);
m_rightPanelStack->addWidget(m_gemInspector);
m_notificationsView = AZStd::make_unique<AzToolsFramework::ToastNotificationsView>(this, AZ_CRC("GemCatalogNotificationsView"));
m_notificationsView->SetOffset(QPoint(10, 70));
@@ -188,7 +201,7 @@ namespace O3DE::ProjectManager
}
// add all the gem repos into the hash
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemReposGemInfos();
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allRepoGemInfosResult = PythonBindingsInterface::Get()->GetGemInfosForAllRepos();
if (allRepoGemInfosResult.IsSuccess())
{
const QVector<GemInfo>& allRepoGemInfos = allRepoGemInfosResult.GetValue();
@@ -303,6 +316,8 @@ namespace O3DE::ProjectManager
QModelIndex proxyIndex = m_proxyModel->mapFromSource(modelIndex);
m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
m_gemListView->scrollTo(proxyIndex);
ShowInspector();
}
void GemCatalogScreen::UpdateGem(const QModelIndex& modelIndex)
@@ -440,7 +455,7 @@ namespace O3DE::ProjectManager
m_gemModel->AddGem(gemInfo);
}
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemReposGemInfos();
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allRepoGemInfosResult = PythonBindingsInterface::Get()->GetGemInfosForAllRepos();
if (allRepoGemInfosResult.IsSuccess())
{
const QVector<GemInfo>& allRepoGemInfos = allRepoGemInfosResult.GetValue();
@@ -496,6 +511,12 @@ namespace O3DE::ProjectManager
}
}
void GemCatalogScreen::ShowInspector()
{
m_rightPanelStack->setCurrentIndex(RightPanelWidgetOrder::Inspector);
m_headerWidget->GemCartShown();
}
GemCatalogScreen::EnableDisableGemsResult GemCatalogScreen::EnableDisableGemsForProject(const QString& projectPath)
{
IPythonBindings* pythonBindings = PythonBindingsInterface::Get();
@@ -577,6 +598,18 @@ namespace O3DE::ProjectManager
emit ChangeScreenRequest(ProjectManagerScreen::GemRepos);
}
void GemCatalogScreen::UpdateAndShowGemCart(QWidget* cartWidget)
{
QWidget* previousCart = m_rightPanelStack->widget(RightPanelWidgetOrder::Cart);
if (previousCart)
{
m_rightPanelStack->removeWidget(previousCart);
}
m_rightPanelStack->insertWidget(RightPanelWidgetOrder::Cart, cartWidget);
m_rightPanelStack->setCurrentIndex(RightPanelWidgetOrder::Cart);
}
void GemCatalogScreen::OnGemDownloadResult(const QString& gemName, bool succeeded)
{
if (succeeded)
@@ -12,18 +12,24 @@
#include <ScreenWidget.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzToolsFramework/UI/Notifications/ToastNotificationsView.h>
#include <GemCatalog/GemCatalogHeaderWidget.h>
#include <GemCatalog/GemFilterWidget.h>
#include <GemCatalog/GemListView.h>
#include <GemCatalog/GemInspector.h>
#include <GemCatalog/GemModel.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <QSet>
#include <QString>
#endif
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
QT_FORWARD_DECLARE_CLASS(QStackedWidget)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(GemCatalogHeaderWidget)
QT_FORWARD_DECLARE_CLASS(GemFilterWidget)
QT_FORWARD_DECLARE_CLASS(GemListView)
QT_FORWARD_DECLARE_CLASS(GemInspector)
QT_FORWARD_DECLARE_CLASS(GemModel)
QT_FORWARD_DECLARE_CLASS(GemSortFilterProxyModel)
QT_FORWARD_DECLARE_CLASS(DownloadController)
class GemCatalogScreen
: public ScreenWidget
{
@@ -62,14 +68,22 @@ namespace O3DE::ProjectManager
private slots:
void HandleOpenGemRepo();
void UpdateAndShowGemCart(QWidget* cartWidget);
void ShowInspector();
private:
enum RightPanelWidgetOrder
{
Inspector = 0,
Cart
};
void FillModel(const QString& projectPath);
AZStd::unique_ptr<AzToolsFramework::ToastNotificationsView> m_notificationsView;
GemListView* m_gemListView = nullptr;
QStackedWidget* m_rightPanelStack = nullptr;
GemInspector* m_gemInspector = nullptr;
GemModel* m_gemModel = nullptr;
GemCatalogHeaderWidget* m_headerWidget = nullptr;
@@ -53,10 +53,13 @@ namespace O3DE::ProjectManager
Update(selectedIndices[0]);
}
void SetLabelElidedText(QLabel* label, QString text)
void SetLabelElidedText(QLabel* label, QString text, int labelWidth = 0)
{
QFontMetrics nameFontMetrics(label->font());
int labelWidth = label->width();
if (!labelWidth)
{
labelWidth = label->width();
}
// Don't elide if the widgets are sized too small (sometimes occurs when loading gem catalog)
if (labelWidth > 100)
@@ -84,7 +87,8 @@ namespace O3DE::ProjectManager
m_summaryLabel->setText(m_model->GetSummary(modelIndex));
m_summaryLabel->adjustSize();
m_licenseLinkLabel->setText(m_model->GetLicenseText(modelIndex));
// Manually define remaining space to elide text because spacer would like to take all of the space
SetLabelElidedText(m_licenseLinkLabel, m_model->GetLicenseText(modelIndex), width() - m_licenseLabel->width() - 35);
m_licenseLinkLabel->SetUrl(m_model->GetLicenseLink(modelIndex));
m_directoryLinkLabel->SetUrl(m_model->GetDirectoryLink(modelIndex));
@@ -175,8 +179,8 @@ namespace O3DE::ProjectManager
licenseHLayout->setAlignment(Qt::AlignLeft);
m_mainLayout->addLayout(licenseHLayout);
QLabel* licenseLabel = CreateStyledLabel(licenseHLayout, s_baseFontSize, s_headerColor);
licenseLabel->setText(tr("License: "));
m_licenseLabel = CreateStyledLabel(licenseHLayout, s_baseFontSize, s_headerColor);
m_licenseLabel->setText(tr("License: "));
m_licenseLinkLabel = new LinkLabel("", QUrl(), s_baseFontSize);
licenseHLayout->addWidget(m_licenseLinkLabel);
@@ -64,6 +64,7 @@ namespace O3DE::ProjectManager
QLabel* m_nameLabel = nullptr;
QLabel* m_creatorLabel = nullptr;
QLabel* m_summaryLabel = nullptr;
QLabel* m_licenseLabel = nullptr;
LinkLabel* m_licenseLinkLabel = nullptr;
LinkLabel* m_directoryLinkLabel = nullptr;
LinkLabel* m_documentationLinkLabel = nullptr;
@@ -120,7 +120,7 @@ namespace O3DE::ProjectManager
{
QString repoUri = GetRepoUri(modelIndex);
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& gemInfosResult = PythonBindingsInterface::Get()->GetGemRepoGemInfos(repoUri);
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& gemInfosResult = PythonBindingsInterface::Get()->GetGemInfosForRepo(repoUri);
if (gemInfosResult.IsSuccess())
{
return gemInfosResult.GetValue();
@@ -203,6 +203,7 @@ namespace O3DE::ProjectManager
QMenu* menu = new QMenu(this);
menu->addAction(tr("Edit Project Settings..."), this, [this]() { emit EditProject(m_projectInfo.m_path); });
menu->addAction(tr("Configure Gems..."), this, [this]() { emit EditProjectGems(m_projectInfo.m_path); });
menu->addAction(tr("Build"), this, [this]() { emit BuildProject(m_projectInfo); });
menu->addAction(tr("Open CMake GUI..."), this, [this]() { emit OpenCMakeGUI(m_projectInfo); });
menu->addSeparator();
@@ -95,6 +95,7 @@ namespace O3DE::ProjectManager
signals:
void OpenProject(const QString& projectName);
void EditProject(const QString& projectName);
void EditProjectGems(const QString& projectName);
void CopyProject(const ProjectInfo& projectInfo);
void RemoveProject(const QString& projectName);
void DeleteProject(const QString& projectName);
@@ -19,6 +19,7 @@
#include <QLabel>
#include <QLineEdit>
#include <QStandardPaths>
#include <QScrollArea>
namespace O3DE::ProjectManager
{
@@ -33,11 +34,23 @@ namespace O3DE::ProjectManager
// 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");
m_verticalLayout = new QVBoxLayout();
// you cannot remove content margins in qss
m_verticalLayout->setContentsMargins(0, 0, 0, 0);
QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setMargin(0);
vLayout->setAlignment(Qt::AlignTop);
projectSettingsFrame->setLayout(vLayout);
QScrollArea* scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true);
vLayout->addWidget(scrollArea);
QWidget* scrollWidget = new QWidget(this);
scrollArea->setWidget(scrollWidget);
m_verticalLayout = new QVBoxLayout();
m_verticalLayout->setMargin(0);
m_verticalLayout->setAlignment(Qt::AlignTop);
scrollWidget->setLayout(m_verticalLayout);
m_projectName = new FormLineEditWidget(tr("Project name"), "", this);
connect(m_projectName->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectNameUpdated);
@@ -183,6 +183,7 @@ namespace O3DE::ProjectManager
connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsScreen::HandleOpenProject);
connect(projectButton, &ProjectButton::EditProject, this, &ProjectsScreen::HandleEditProject);
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);
@@ -469,6 +470,14 @@ namespace O3DE::ProjectManager
emit ChangeScreenRequest(ProjectManagerScreen::UpdateProject);
}
}
void ProjectsScreen::HandleEditProjectGems(const QString& projectPath)
{
if (!WarnIfInBuildQueue(projectPath))
{
emit NotifyCurrentProject(projectPath);
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
}
}
void ProjectsScreen::HandleCopyProject(const ProjectInfo& projectInfo)
{
if (!WarnIfInBuildQueue(projectInfo.m_path))
@@ -46,6 +46,7 @@ namespace O3DE::ProjectManager
void HandleAddProjectButton();
void HandleOpenProject(const QString& projectPath);
void HandleEditProject(const QString& projectPath);
void HandleEditProjectGems(const QString& projectPath);
void HandleCopyProject(const ProjectInfo& projectInfo);
void HandleRemoveProject(const QString& projectPath);
void HandleDeleteProject(const QString& projectPath);
@@ -1206,7 +1206,7 @@ namespace O3DE::ProjectManager
return AZ::Success(AZStd::move(gemRepos));
}
AZ::Outcome<QVector<GemInfo>, AZStd::string> PythonBindings::GetGemRepoGemInfos(const QString& repoUri)
AZ::Outcome<QVector<GemInfo>, AZStd::string> PythonBindings::GetGemInfosForRepo(const QString& repoUri)
{
QVector<GemInfo> gemInfos;
AZ::Outcome<void, AZStd::string> result = ExecuteWithLockErrorHandling(
@@ -1234,7 +1234,7 @@ namespace O3DE::ProjectManager
return AZ::Success(AZStd::move(gemInfos));
}
AZ::Outcome<QVector<GemInfo>, AZStd::string> PythonBindings::GetAllGemReposGemInfos()
AZ::Outcome<QVector<GemInfo>, AZStd::string> PythonBindings::GetGemInfosForAllRepos()
{
QVector<GemInfo> gemInfos;
AZ::Outcome<void, AZStd::string> result = ExecuteWithLockErrorHandling(
@@ -65,8 +65,8 @@ namespace O3DE::ProjectManager
AZ::Outcome<void, AZStd::pair<AZStd::string, AZStd::string>> AddGemRepo(const QString& repoUri) override;
bool RemoveGemRepo(const QString& repoUri) override;
AZ::Outcome<QVector<GemRepoInfo>, AZStd::string> GetAllGemRepoInfos() override;
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetGemRepoGemInfos(const QString& repoUri) override;
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemReposGemInfos() override;
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetGemInfosForRepo(const QString& repoUri) override;
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetGemInfosForAllRepos() override;
AZ::Outcome<void, AZStd::pair<AZStd::string, AZStd::string>> DownloadGem(
const QString& gemName, std::function<void(int, int)> gemProgressCallback, bool force = false) override;
void CancelDownload() override;
@@ -218,17 +218,17 @@ namespace O3DE::ProjectManager
virtual AZ::Outcome<QVector<GemRepoInfo>, AZStd::string> GetAllGemRepoInfos() = 0;
/**
* Gathers all gem infos for repos
* Gathers all gem infos from the provided repo
* @param repoUri the absolute filesystem path or url to the gem repo.
* @return A list of gem infos.
*/
virtual AZ::Outcome<QVector<GemInfo>, AZStd::string> GetGemRepoGemInfos(const QString& repoUri) = 0;
virtual AZ::Outcome<QVector<GemInfo>, AZStd::string> GetGemInfosForRepo(const QString& repoUri) = 0;
/**
* Gathers all gem infos for all gems registered from repos.
* @return A list of gem infos.
*/
virtual AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemReposGemInfos() = 0;
virtual AZ::Outcome<QVector<GemInfo>, AZStd::string> GetGemInfosForAllRepos() = 0;
/**
* Downloads and registers a Gem.
@@ -47,9 +47,9 @@ namespace O3DE::ProjectManager
return tr("Missing");
}
virtual bool ContainsScreen([[maybe_unused]] ProjectManagerScreen screen)
virtual bool ContainsScreen(ProjectManagerScreen screen)
{
return false;
return GetScreenEnum() == screen;
}
virtual void GoToScreen([[maybe_unused]] ProjectManagerScreen screen)
{
@@ -58,7 +58,6 @@ namespace O3DE::ProjectManager
//! Notify this screen it is the current screen
virtual void NotifyCurrentScreen()
{
}
signals:
@@ -15,8 +15,8 @@
#include <UpdateProjectCtrl.h>
#include <UpdateProjectSettingsScreen.h>
#include <ProjectUtils.h>
#include <DownloadController.h>
#include <ProjectManagerSettings.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <QDialogButtonBox>
@@ -97,6 +97,17 @@ namespace O3DE::ProjectManager
return ProjectManagerScreen::UpdateProject;
}
bool UpdateProjectCtrl::ContainsScreen(ProjectManagerScreen screen)
{
// Do not include GemRepos because we don't want to advertise jumping to it from all other screens here
return screen == GetScreenEnum() || screen == ProjectManagerScreen::GemCatalog;
}
void UpdateProjectCtrl::GoToScreen(ProjectManagerScreen screen)
{
OnChangeScreenRequest(screen);
}
// Called when pressing "Edit Project Settings..."
void UpdateProjectCtrl::NotifyCurrentScreen()
{
@@ -117,6 +128,16 @@ namespace O3DE::ProjectManager
m_stack->setCurrentWidget(m_gemRepoScreen);
Update();
}
else if (screen == ProjectManagerScreen::GemCatalog)
{
m_stack->setCurrentWidget(m_gemCatalogScreen);
Update();
}
else if (screen == ProjectManagerScreen::UpdateProjectSettings)
{
m_stack->setCurrentWidget(m_updateSettingsScreen);
Update();
}
else
{
emit ChangeScreenRequest(screen);
@@ -24,7 +24,8 @@ namespace O3DE::ProjectManager
QT_FORWARD_DECLARE_CLASS(GemCatalogScreen)
QT_FORWARD_DECLARE_CLASS(GemRepoScreen)
class UpdateProjectCtrl : public ScreenWidget
class UpdateProjectCtrl
: public ScreenWidget
{
Q_OBJECT
public:
@@ -32,7 +33,8 @@ namespace O3DE::ProjectManager
~UpdateProjectCtrl() = default;
ProjectManagerScreen GetScreenEnum() override;
protected:
bool ContainsScreen(ProjectManagerScreen screen) override;
void GoToScreen(ProjectManagerScreen screen) override;
void NotifyCurrentScreen() override;
protected slots:
@@ -35,7 +35,7 @@ namespace O3DE::ProjectManager
previewExtrasLayout->setContentsMargins(50, 0, 0, 0);
QLabel* projectPreviewLabel = new QLabel(tr("Select an image (PNG). Minimum %1 x %2 pixels.")
.arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight)));
.arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight)));
projectPreviewLabel->setObjectName("projectPreviewLabel");
previewExtrasLayout->addWidget(projectPreviewLabel);