Dependency confirmation screen and URL display fix

Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com>
monroegm-disable-blank-issue-2
Alex Peterson 4 years ago committed by GitHub
parent c759bc9cd0
commit ef3470b0a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -496,13 +496,34 @@ QProgressBar::chunk {
background-color: #333333;
}
/************** Filter tag widget **************/
#GemDependenciesDialog QLabel {
margin-bottom:10px;
}
#GemDependenciesDialog QCheckBox {
background-color: #333333;
border-radius: 3px;
spacing:3px;
margin-right:5px;
padding:4px;
margin-top:5px;
}
/************** Filter Tag widget **************/
#FilterTagWidgetTextLabel {
color: #94D2FF;
font-size: 10px;
}
#TagWidget {
background-color: #333333;
padding:3px;
font-size:12px;
border-radius: 3px;
margin-right: 3px;
}
/************** Gems SubWidget **************/
#gemSubWidgetTitleLabel {

@ -238,9 +238,13 @@ namespace O3DE::ProjectManager
PythonBindingsInterface::Get()->AddProject(projectInfo.m_path);
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
if (!m_gemCatalogScreen->EnableDisableGemsForProject(projectInfo.m_path))
const GemCatalogScreen::EnableDisableGemsResult gemResult = m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path);
if (gemResult == GemCatalogScreen::EnableDisableGemsResult::Failed)
{
QMessageBox::critical(this, tr("Failed to configure gems"), tr("Failed to configure gems for template."));
}
if (gemResult != GemCatalogScreen::EnableDisableGemsResult::Success)
{
return;
}
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED

@ -11,6 +11,7 @@
#include <GemCatalog/GemListHeaderWidget.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <GemCatalog/GemRequirementDialog.h>
#include <GemCatalog/GemDependenciesDialog.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
@ -134,7 +135,7 @@ namespace O3DE::ProjectManager
}
}
bool GemCatalogScreen::EnableDisableGemsForProject(const QString& projectPath)
GemCatalogScreen::EnableDisableGemsResult GemCatalogScreen::EnableDisableGemsForProject(const QString& projectPath)
{
IPythonBindings* pythonBindings = PythonBindingsInterface::Get();
QVector<QModelIndex> toBeAdded = m_gemModel->GatherGemsToBeAdded();
@ -142,13 +143,23 @@ namespace O3DE::ProjectManager
if (m_gemModel->DoGemsToBeAddedHaveRequirements())
{
GemRequirementDialog* confirmRequirementsDialog = new GemRequirementDialog(m_gemModel, toBeAdded, this);
confirmRequirementsDialog->exec();
GemRequirementDialog* confirmRequirementsDialog = new GemRequirementDialog(m_gemModel, this);
if(confirmRequirementsDialog->exec() == QDialog::Rejected)
{
return EnableDisableGemsResult::Cancel;
}
}
if (confirmRequirementsDialog->GetButtonResult() != QDialogButtonBox::ApplyRole)
if (m_gemModel->HasDependentGemsToRemove())
{
GemDependenciesDialog* dependenciesDialog = new GemDependenciesDialog(m_gemModel, this);
if(dependenciesDialog->exec() == QDialog::Rejected)
{
return false;
return EnableDisableGemsResult::Cancel;
}
toBeAdded = m_gemModel->GatherGemsToBeAdded();
toBeRemoved = m_gemModel->GatherGemsToBeRemoved();
}
for (const QModelIndex& modelIndex : toBeAdded)
@ -160,7 +171,7 @@ namespace O3DE::ProjectManager
QMessageBox::critical(nullptr, "Operation failed",
QString("Cannot add gem %1 to project.\n\nError:\n%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str()));
return false;
return EnableDisableGemsResult::Failed;
}
}
@ -173,11 +184,11 @@ namespace O3DE::ProjectManager
QMessageBox::critical(nullptr, "Operation failed",
QString("Cannot remove gem %1 from project.\n\nError:\n%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str()));
return false;
return EnableDisableGemsResult::Failed;
}
}
return true;
return EnableDisableGemsResult::Success;
}
ProjectManagerScreen GemCatalogScreen::GetScreenEnum()

@ -29,7 +29,14 @@ namespace O3DE::ProjectManager
ProjectManagerScreen GetScreenEnum() override;
void ReinitForProject(const QString& projectPath);
bool EnableDisableGemsForProject(const QString& projectPath);
enum class EnableDisableGemsResult
{
Failed = 0,
Success,
Cancel
};
EnableDisableGemsResult EnableDisableGemsForProject(const QString& projectPath);
GemModel* GetGemModel() const { return m_gemModel; }

@ -0,0 +1,80 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <GemCatalog/GemDependenciesDialog.h>
#include <GemCatalog/GemModel.h>
#include <AzQtComponents/Components/FlowLayout.h>
#include <QVBoxLayout>
#include <QLabel>
#include <QDialogButtonBox>
#include <QCheckBox>
namespace O3DE::ProjectManager
{
GemDependenciesDialog::GemDependenciesDialog(GemModel* gemModel, QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("Dependent Gems"));
setObjectName("GemDependenciesDialog");
setAttribute(Qt::WA_DeleteOnClose);
setModal(true);
QVBoxLayout* layout = new QVBoxLayout();
// layout margin/alignment cannot be set with qss
layout->setMargin(15);
layout->setAlignment(Qt::AlignTop);
setLayout(layout);
// message
QLabel* instructionLabel = new QLabel(
tr("The following gem dependencies are no longer needed and will be deactivated.<br><br>"
"To keep these Gems enabled, select the checkbox next to it."));
layout->addWidget(instructionLabel);
// checkboxes
FlowLayout* flowLayout = new FlowLayout();
QVector<QModelIndex> gemsToRemove = gemModel->GatherGemsToBeRemoved(/*includeDependencies=*/true);
for (const QModelIndex& gem : gemsToRemove)
{
if (GemModel::WasPreviouslyAddedDependency(gem))
{
QCheckBox* checkBox = new QCheckBox(GemModel::GetName(gem));
connect(checkBox, &QCheckBox::stateChanged, this,
[=](int state)
{
GemModel::SetIsAdded(*gemModel, gem, /*isAdded=*/state == Qt::Checked);
});
flowLayout->addWidget(checkBox);
}
}
layout->addLayout(flowLayout);
layout->addSpacing(10);
layout->addStretch(1);
// buttons
QDialogButtonBox* dialogButtons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
connect(dialogButtons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(dialogButtons, &QDialogButtonBox::rejected, this,
[=]()
{
// de-select any Gems the user selected because they're canceling
for (const QModelIndex& gem : gemsToRemove)
{
if (GemModel::WasPreviouslyAddedDependency(gem) && GemModel::IsAdded(gem))
{
GemModel::SetIsAdded(*gemModel, gem, /*isAdded=*/false);
}
}
reject();
});
layout->addWidget(dialogButtons);
}
} // namespace O3DE::ProjectManager

@ -0,0 +1,27 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QDialog>
#endif
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(GemModel)
class GemDependenciesDialog
: public QDialog
{
Q_OBJECT // AUTOMOC
public:
explicit GemDependenciesDialog(GemModel* gemModel, QWidget *parent = nullptr);
~GemDependenciesDialog() = default;
};
} // namespace O3DE::ProjectManager

@ -9,6 +9,7 @@
#include <GemCatalog/GemItemDelegate.h>
#include <GemCatalog/GemModel.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <QEvent>
#include <QAbstractItemView>
#include <QPainter>
@ -16,6 +17,9 @@
#include <QHelpEvent>
#include <QToolTip>
#include <QHoverEvent>
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QDesktopServices>
namespace O3DE::ProjectManager
{
@ -104,22 +108,11 @@ namespace O3DE::ProjectManager
painter->drawText(gemCreatorRect, Qt::TextSingleLine, gemCreator);
// Gem summary
// In case there are feature tags displayed at the bottom, decrease the size of the summary text field.
const QStringList featureTags = GemModel::GetFeatures(modelIndex);
const int featureTagAreaHeight = 30;
const int summaryHeight = contentRect.height() - (!featureTags.empty() * featureTagAreaHeight);
const int additionalSummarySpacing = s_itemMargins.right() * 3;
const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - additionalSummarySpacing,
summaryHeight);
const QRect summaryRect = QRect(/*topLeft=*/QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize);
painter->setFont(standardFont);
painter->setPen(m_textColor);
const bool hasTags = !featureTags.isEmpty();
const QString summary = GemModel::GetSummary(modelIndex);
painter->drawText(summaryRect, Qt::AlignLeft | Qt::TextWordWrap, summary);
const QRect summaryRect = CalcSummaryRect(contentRect, hasTags);
DrawText(summary, painter, summaryRect, standardFont);
DrawButton(painter, contentRect, modelIndex);
DrawPlatformIcons(painter, contentRect, modelIndex);
@ -128,6 +121,17 @@ namespace O3DE::ProjectManager
painter->restore();
}
QRect GemItemDelegate::CalcSummaryRect(const QRect& contentRect, bool hasTags) const
{
const int featureTagAreaHeight = 30;
const int summaryHeight = contentRect.height() - (hasTags * featureTagAreaHeight);
const int additionalSummarySpacing = s_itemMargins.right() * 3;
const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - additionalSummarySpacing,
summaryHeight);
return QRect(QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize);
}
QSize GemItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const
{
QStyleOptionViewItem options(option);
@ -154,7 +158,7 @@ namespace O3DE::ProjectManager
return true;
}
}
else if (event->type() == QEvent::MouseButtonPress )
else if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
@ -168,6 +172,21 @@ namespace O3DE::ProjectManager
GemModel::SetIsAdded(*model, modelIndex, !isAdded);
return true;
}
// we must manually handle html links because we aren't using QLabels
const QStringList featureTags = GemModel::GetFeatures(modelIndex);
const bool hasTags = !featureTags.isEmpty();
const QRect summaryRect = CalcSummaryRect(contentRect, hasTags);
if (summaryRect.contains(mouseEvent->pos()))
{
const QString html = GemModel::GetSummary(modelIndex);
QString anchor = anchorAt(html, mouseEvent->pos(), summaryRect);
if (!anchor.isEmpty())
{
QDesktopServices::openUrl(QUrl(anchor));
return true;
}
}
}
return QStyledItemDelegate::editorEvent(event, model, option, modelIndex);
@ -321,6 +340,44 @@ namespace O3DE::ProjectManager
}
}
AZStd::unique_ptr<QTextDocument> GetTextDocument(const QString& text, int width)
{
// using unique_ptr as a workaround for QTextDocument having a private copy constructor
auto doc = AZStd::make_unique<QTextDocument>();
QTextOption textOption(doc->defaultTextOption());
textOption.setWrapMode(QTextOption::WordWrap);
doc->setDefaultTextOption(textOption);
doc->setHtml(text);
doc->setTextWidth(width);
return doc;
}
void GemItemDelegate::DrawText(const QString& text, QPainter* painter, const QRect& rect, const QFont& standardFont) const
{
painter->save();
if (text.contains('<'))
{
painter->translate(rect.topLeft());
// use QTextDocument because drawText does not support rich text or html
QAbstractTextDocumentLayout::PaintContext paintContext;
paintContext.clip = QRect(0, 0, rect.width(), rect.height());
paintContext.palette.setColor(QPalette::Text, painter->pen().color());
AZStd::unique_ptr<QTextDocument> textDocument = GetTextDocument(text, rect.width());
textDocument->documentLayout()->draw(painter, paintContext);
}
else
{
painter->setFont(standardFont);
painter->setPen(m_textColor);
painter->drawText(rect, Qt::AlignLeft | Qt::TextWordWrap, text);
}
painter->restore();
}
void GemItemDelegate::DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const
{
painter->save();
@ -355,4 +412,19 @@ namespace O3DE::ProjectManager
painter->restore();
}
QString GemItemDelegate::anchorAt(const QString& html, const QPoint& position, const QRect& rect)
{
if (!html.isEmpty())
{
AZStd::unique_ptr<QTextDocument> doc = GetTextDocument(html, rect.width());
QAbstractTextDocumentLayout* layout = doc->documentLayout();
if (layout)
{
return layout->anchorAt(position - rect.topLeft());
}
}
return QString();
}
} // namespace O3DE::ProjectManager

@ -30,6 +30,7 @@ namespace O3DE::ProjectManager
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
virtual QString anchorAt(const QString& html, const QPoint& position, const QRect& rect);
// Colors
const QColor m_textColor = QColor("#FFFFFF");
@ -71,9 +72,11 @@ namespace O3DE::ProjectManager
void CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
QRect CalcButtonRect(const QRect& contentRect) const;
QRect CalcSummaryRect(const QRect& contentRect, bool hasTags) const;
void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
void DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
void DrawFeatureTags(QPainter* painter, const QRect& contentRect, const QStringList& featureTags, const QFont& standardFont, const QRect& summaryRect) const;
void DrawText(const QString& text, QPainter* painter, const QRect& rect, const QFont& standardFont) const;
QAbstractItemModel* m_model = nullptr;

@ -8,27 +8,9 @@
#include <GemCatalog/GemListView.h>
#include <GemCatalog/GemItemDelegate.h>
#include <QStandardItemModel>
#include <QProxyStyle>
namespace O3DE::ProjectManager
{
class GemListViewProxyStyle : public QProxyStyle
{
public:
using QProxyStyle::QProxyStyle;
int styleHint(StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override
{
if (hint == QStyle::SH_ToolTip_WakeUpDelay || hint == QStyle::SH_ToolTip_FallAsleepDelay)
{
// no delay
return 0;
}
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
};
GemListView::GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent)
: QListView(parent)
{
@ -38,8 +20,5 @@ namespace O3DE::ProjectManager
setModel(model);
setSelectionModel(selectionModel);
setItemDelegate(new GemItemDelegate(model, this));
// use a custom proxy style so we get immediate tooltips for gem radio buttons
setStyle(new GemListViewProxyStyle(this->style()));
}
} // namespace O3DE::ProjectManager

@ -391,6 +391,20 @@ namespace O3DE::ProjectManager
return false;
}
bool GemModel::HasDependentGemsToRemove() const
{
for (int row = 0; row < rowCount(); ++row)
{
const QModelIndex modelIndex = index(row, 0);
if (GemModel::NeedsToBeRemoved(modelIndex, /*includeDependencies=*/true) &&
GemModel::WasPreviouslyAddedDependency(modelIndex))
{
return true;
}
}
return false;
}
QVector<QModelIndex> GemModel::GatherGemDependencies(const QModelIndex& modelIndex) const
{
QVector<QModelIndex> result;

@ -66,6 +66,7 @@ namespace O3DE::ProjectManager
static void UpdateDependencies(QAbstractItemModel& model, const QModelIndex& modelIndex);
bool DoGemsToBeAddedHaveRequirements() const;
bool HasDependentGemsToRemove() const;
QVector<QModelIndex> GatherGemDependencies(const QModelIndex& modelIndex) const;
QVector<QModelIndex> GatherDependentGems(const QModelIndex& modelIndex, bool addedOnly = false) const;

@ -10,6 +10,8 @@
#include <GemCatalog/GemModel.h>
#include <QPainter>
#include <QMouseEvent>
#include <QDesktopServices>
namespace O3DE::ProjectManager
{
@ -38,7 +40,6 @@ namespace O3DE::ProjectManager
standardFont.setPixelSize(static_cast<int>(s_fontSize));
QFontMetrics standardFontMetrics(standardFont);
painter->save();
painter->setClipping(true);
painter->setClipRect(fullRect);
painter->setFont(options.font);
@ -65,25 +66,51 @@ namespace O3DE::ProjectManager
painter->drawText(gemNameRect, Qt::TextSingleLine, gemName);
// Gem requirement
const QSize requirementSize = QSize(contentRect.width() - s_summaryStartX - s_itemMargins.right(), contentRect.height());
const QRect requirementRect = QRect(QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), requirementSize);
painter->setFont(standardFont);
painter->setPen(m_textColor);
const QRect requirementRect = CalcRequirementRect(contentRect);
const QString requirement = GemModel::GetRequirement(modelIndex);
painter->drawText(requirementRect, Qt::AlignLeft | Qt::TextWordWrap, requirement);
DrawText(requirement, painter, requirementRect, standardFont);
painter->restore();
}
QRect GemRequirementDelegate::CalcRequirementRect(const QRect& contentRect) const
{
const QSize requirementSize = QSize(contentRect.width() - s_summaryStartX - s_itemMargins.right(), contentRect.height());
return QRect(QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), requirementSize);
}
bool GemRequirementDelegate::editorEvent(
[[maybe_unused]] QEvent* event,
[[maybe_unused]] QAbstractItemModel* model,
[[maybe_unused]] const QStyleOptionViewItem& option,
[[maybe_unused]] const QModelIndex& modelIndex)
{
// Do nothing here
return false;
if (!modelIndex.isValid())
{
return false;
}
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
QRect fullRect, itemRect, contentRect;
CalcRects(option, fullRect, itemRect, contentRect);
const QRect requirementsRect = CalcRequirementRect(contentRect);
if (requirementsRect.contains(mouseEvent->pos()))
{
const QString html = GemModel::GetRequirement(modelIndex);
QString anchor = anchorAt(html, mouseEvent->pos(), requirementsRect);
if (!anchor.isEmpty())
{
QDesktopServices::openUrl(QUrl(anchor));
return true;
}
}
}
return QStyledItemDelegate::editorEvent(event, model, option, modelIndex);
}
} // namespace O3DE::ProjectManager

@ -29,5 +29,8 @@ namespace O3DE::ProjectManager
const QColor m_backgroundColor = QColor("#444444"); // Outside of the actual gem item
const QColor m_itemBackgroundColor = QColor("#393939"); // Background color of the gem item
private:
QRect CalcRequirementRect(const QRect& contentRect) const;
};
} // namespace O3DE::ProjectManager

@ -19,11 +19,12 @@
namespace O3DE::ProjectManager
{
GemRequirementDialog::GemRequirementDialog(GemModel* model, const QVector<QModelIndex>& gemsToAdd, QWidget* parent)
GemRequirementDialog::GemRequirementDialog(GemModel* model, QWidget* parent)
: QDialog(parent)
{
setWindowTitle(tr("Manual setup is required"));
setModal(true);
setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setMargin(0);
@ -51,7 +52,7 @@ namespace O3DE::ProjectManager
vLayout->addSpacing(20);
GemRequirementFilterProxyModel* proxModel = new GemRequirementFilterProxyModel(model, gemsToAdd, this);
GemRequirementFilterProxyModel* proxModel = new GemRequirementFilterProxyModel(model, this);
GemRequirementListView* m_gemListView = new GemRequirementListView(proxModel, proxModel->GetSelectionModel(), this);
vLayout->addWidget(m_gemListView);
@ -62,27 +63,9 @@ namespace O3DE::ProjectManager
QPushButton* cancelButton = dialogButtons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole);
cancelButton->setProperty("secondary", true);
QPushButton* continueButton = dialogButtons->addButton(tr("Continue"), QDialogButtonBox::ApplyRole);
QPushButton* continueButton = dialogButtons->addButton(tr("Continue"), QDialogButtonBox::AcceptRole);
connect(cancelButton, &QPushButton::clicked, this, &GemRequirementDialog::CancelButtonPressed);
connect(continueButton, &QPushButton::clicked, this, &GemRequirementDialog::ContinueButtonPressed);
connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject);
connect(continueButton, &QPushButton::clicked, this, &QDialog::accept);
}
QDialogButtonBox::ButtonRole GemRequirementDialog::GetButtonResult()
{
return m_buttonResult;
}
void GemRequirementDialog::CancelButtonPressed()
{
m_buttonResult = QDialogButtonBox::RejectRole;
close();
}
void GemRequirementDialog::ContinueButtonPressed()
{
m_buttonResult = QDialogButtonBox::ApplyRole;
close();
}
} // namespace O3DE::ProjectManager

@ -10,8 +10,6 @@
#if !defined(Q_MOC_RUN)
#include <QDialog>
#include <QDialogButtonBox>
#endif
namespace O3DE::ProjectManager
@ -23,15 +21,7 @@ namespace O3DE::ProjectManager
{
Q_OBJECT // AUTOMOC
public:
explicit GemRequirementDialog(GemModel* model, const QVector<QModelIndex>& gemsToAdd, QWidget *parent = nullptr);
explicit GemRequirementDialog(GemModel* model, QWidget *parent = nullptr);
~GemRequirementDialog() = default;
QDialogButtonBox::ButtonRole GetButtonResult();
private:
void CancelButtonPressed();
void ContinueButtonPressed();
QDialogButtonBox::ButtonRole m_buttonResult = QDialogButtonBox::RejectRole;
};
} // namespace O3DE::ProjectManager

@ -13,10 +13,8 @@
namespace O3DE::ProjectManager
{
GemRequirementFilterProxyModel::GemRequirementFilterProxyModel(GemModel* sourceModel, const QVector<QModelIndex>& addedGems, QObject* parent)
GemRequirementFilterProxyModel::GemRequirementFilterProxyModel(GemModel* sourceModel, QObject* parent)
: QSortFilterProxyModel(parent)
, m_sourceModel(sourceModel)
, m_addedGems(addedGems)
{
setSourceModel(sourceModel);
m_selectionProxyModel = new AzQtComponents::SelectionProxyModel(sourceModel->GetSelectionModel(), this, parent);
@ -26,22 +24,7 @@ namespace O3DE::ProjectManager
{
// Do not use sourceParent->child because an invalid parent does not produce valid children (which our index function does)
QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
if (!sourceIndex.isValid())
{
return false;
}
if (!m_addedGems.contains(sourceIndex))
{
return false;
}
if (!m_sourceModel->HasRequirement(sourceIndex))
{
return false;
}
return true;
return GemModel::IsAdded(sourceIndex) && GemModel::HasRequirement(sourceIndex);
}
} // namespace O3DE::ProjectManager

@ -25,16 +25,13 @@ namespace O3DE::ProjectManager
Q_OBJECT // AUTOMOC
public:
GemRequirementFilterProxyModel(GemModel* sourceModel, const QVector<QModelIndex>& addedGems, QObject* parent = nullptr);
GemRequirementFilterProxyModel(GemModel* sourceModel, QObject* parent = nullptr);
AzQtComponents::SelectionProxyModel* GetSelectionModel() const { return m_selectionProxyModel; }
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
private:
GemModel* m_sourceModel = nullptr;
AzQtComponents::SelectionProxyModel* m_selectionProxyModel = nullptr;
QVector<QModelIndex> m_addedGems;
};
} // namespace O3DE::ProjectManager

@ -8,7 +8,6 @@
#include <GemCatalog/GemRequirementListView.h>
#include <GemCatalog/GemRequirementDelegate.h>
#include <QStandardItemModel>
namespace O3DE::ProjectManager
{

@ -8,87 +8,44 @@
#include <TagWidget.h>
#include <QVBoxLayout>
#include <AzQtComponents/Components/FlowLayout.h>
namespace O3DE::ProjectManager
{
TagWidget::TagWidget(const QString& text, QWidget* parent)
: QLabel(text, parent)
{
setFixedHeight(24);
setMargin(5);
setStyleSheet("font-size: 12px; background-color: #333333; border-radius: 3px;");
setObjectName("TagWidget");
}
TagContainerWidget::TagContainerWidget(QWidget* parent)
: QWidget(parent)
{
m_layout = new QVBoxLayout();
m_layout->setAlignment(Qt::AlignTop);
m_layout->setMargin(0);
setLayout(m_layout);
setObjectName("TagWidgetContainer");
setLayout(new FlowLayout(this));
// layout margins cannot be set via qss
constexpr int verticalMargin = 10;
constexpr int horizontalMargin = 0;
layout()->setContentsMargins(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin);
setAttribute(Qt::WA_StyledBackground, true);
}
void TagContainerWidget::Update(const QStringList& tags)
{
QWidget* parentWidget = qobject_cast<QWidget*>(parent());
int width = 200;
if (parentWidget)
{
width = parentWidget->width();
}
FlowLayout* flowLayout = static_cast<FlowLayout*>(layout());
if (m_widget)
// remove old tags
QLayoutItem* layoutItem = nullptr;
while ((layoutItem = layout()->takeAt(0)) != nullptr)
{
// Hide the old widget and request deletion.
m_widget->hide();
m_widget->deleteLater();
layoutItem->widget()->deleteLater();
}
QVBoxLayout* vLayout = new QVBoxLayout();
m_widget = new QWidget(this);
m_widget->setLayout(vLayout);
m_layout->addWidget(m_widget);
vLayout->setAlignment(Qt::AlignTop);
vLayout->setMargin(0);
QHBoxLayout* hLayout = nullptr;
int usedSpaceInRow = 0;
const int numTags = tags.count();
for (int i = 0; i < numTags; ++i)
foreach (const QString& tag, tags)
{
// Create the new tag widget.
TagWidget* tagWidget = new TagWidget(tags[i]);
const int tagWidgetWidth = tagWidget->minimumSizeHint().width();
// Calculate the width we're currently using in the current row. Does the new tag still fit in the current row?
const bool isRowFull = width - usedSpaceInRow - tagWidgetWidth < 0;
if (isRowFull || i == 0)
{
// Add a spacer widget after the last tag widget in a row to push the tag widgets to the left.
if (i > 0)
{
QWidget* spacerWidget = new QWidget();
spacerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
hLayout->addWidget(spacerWidget);
}
// Add a new row for the current tag widget.
hLayout = new QHBoxLayout();
hLayout->setAlignment(Qt::AlignLeft);
hLayout->setMargin(0);
vLayout->addLayout(hLayout);
// Reset the used space in the row.
usedSpaceInRow = 0;
}
// Calculate the width of the tag widgets including the spacing between them of the current row.
usedSpaceInRow += tagWidgetWidth + hLayout->spacing();
// Add the tag widget to the current row.
hLayout->addWidget(tagWidget);
flowLayout->addWidget(new TagWidget(tag));
}
}
} // namespace O3DE::ProjectManager

@ -14,8 +14,6 @@
#include <QWidget>
#endif
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
namespace O3DE::ProjectManager
{
// Single tag
@ -40,9 +38,5 @@ namespace O3DE::ProjectManager
~TagContainerWidget() = default;
void Update(const QStringList& tags);
private:
QVBoxLayout* m_layout = nullptr;
QWidget* m_widget = nullptr;
};
} // namespace O3DE::ProjectManager

@ -137,9 +137,13 @@ namespace O3DE::ProjectManager
else if (m_stack->currentIndex() == ScreenOrder::Gems && m_gemCatalogScreen)
{
// Enable or disable the gems that got adjusted in the gem catalog and apply them to the given project.
if (!m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path))
const GemCatalogScreen::EnableDisableGemsResult result = m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path);
if (result == GemCatalogScreen::EnableDisableGemsResult::Failed)
{
QMessageBox::critical(this, tr("Failed to configure gems"), tr("Failed to configure gems for project."));
}
if (result != GemCatalogScreen::EnableDisableGemsResult::Success)
{
return;
}

@ -92,6 +92,8 @@ set(FILES
Source/GemCatalog/GemListHeaderWidget.cpp
Source/GemCatalog/GemModel.h
Source/GemCatalog/GemModel.cpp
Source/GemCatalog/GemDependenciesDialog.h
Source/GemCatalog/GemDependenciesDialog.cpp
Source/GemCatalog/GemRequirementDialog.h
Source/GemCatalog/GemRequirementDialog.cpp
Source/GemCatalog/GemRequirementDelegate.h

Loading…
Cancel
Save