Resizable Headers for Gem Catalog and Gem Repo Screen (#6885)

* Initial mostly working attempt at resizable headers

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Add const and constexpr to variables

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Add header tracking for buttons, display items based on header scrollbar position, fix some spacing issues

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Correct styling for adjustable header, and intending header section and alingned item content with header text

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Prevent header resizing larger than table width.

Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com>

* Fix resize graphical glitching

Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com>

* Remove unecessary qss

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Removed necessary headers

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Remove extra nl and old comment

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Address PR feedback

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Removed unused variables

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Change variable to constexpr

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Remove AUTOMOC from headers, set background color of Gem Catalog to 333333 and adjustable header to transparent

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Change to using update instead of repaint when sections are resized

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

* Change temp directory creation on for gradle

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>

Co-authored-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com>
This commit is contained in:
AMZN-nggieber
2022-01-28 10:05:03 -08:00
committed by GitHub
parent 0ba1cff08e
commit 24086ab394
41 changed files with 437 additions and 158 deletions
@@ -0,0 +1,118 @@
/*
* 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 <AdjustableHeaderWidget.h>
#include <AzCore/Debug/Trace.h>
#include <QHeaderView>
#include <QTimer>
namespace O3DE::ProjectManager
{
AdjustableHeaderWidget::AdjustableHeaderWidget( const QStringList& headerLabels,
const QVector<int>& defaultHeaderWidths, int minHeaderWidth,
const QVector<QHeaderView::ResizeMode>& resizeModes, QWidget* parent)
: QTableWidget(parent)
{
setObjectName("adjustableHeaderWidget");
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
setFixedHeight(s_headerWidgetHeight);
m_header = horizontalHeader();
m_header->setDefaultAlignment(Qt::AlignLeft);
setColumnCount(headerLabels.count());
setHorizontalHeaderLabels(headerLabels);
AZ_Assert(defaultHeaderWidths.count() == columnCount(), "Default header widths does not match number of columns");
AZ_Assert(resizeModes.count() == columnCount(), "Resize modesdoes not match number of columns");
for (int column = 0; column < columnCount(); ++column)
{
m_header->resizeSection(column, defaultHeaderWidths[column]);
m_header->setSectionResizeMode(column, resizeModes[column]);
}
m_header->setMinimumSectionSize(minHeaderWidth);
m_header->setCascadingSectionResizes(true);
connect(m_header, &QHeaderView::sectionResized, this, &AdjustableHeaderWidget::OnSectionResized);
}
void AdjustableHeaderWidget::OnSectionResized(int logicalIndex, int oldSize, int newSize)
{
const int headerCount = columnCount();
const int headerWidth = m_header->width();
const int totalSectionWidth = m_header->length();
if (totalSectionWidth > headerWidth && newSize > oldSize)
{
int xPos = 0;
int requiredWidth = 0;
for (int i = 0; i < headerCount; i++)
{
if (i < logicalIndex)
{
xPos += m_header->sectionSize(i);
}
else if (i == logicalIndex)
{
xPos += newSize;
}
else if (i > logicalIndex)
{
if (m_header->sectionResizeMode(i) == QHeaderView::ResizeMode::Fixed)
{
requiredWidth += m_header->sectionSize(i);
}
else
{
requiredWidth += m_header->minimumSectionSize();
}
}
}
if (xPos + requiredWidth > headerWidth)
{
m_header->resizeSection(logicalIndex, oldSize);
}
}
// wait till all columns resized
QTimer::singleShot(0, [&]()
{
// only re-paint when the header and section widths have settled
const int headerWidth = m_header->width();
const int totalSectionWidth = m_header->length();
if (totalSectionWidth == headerWidth)
{
emit sectionsResized();
}
});
}
QPair<int, int> AdjustableHeaderWidget::CalcColumnXBounds(int headerIndex) const
{
// Total the widths of all headers before this one in first and including it in second
QPair<int, int> bounds(0, 0);
for (int curIndex = 0; curIndex <= headerIndex; ++curIndex)
{
if (curIndex == headerIndex)
{
bounds.first = bounds.second;
}
bounds.second += m_header->sectionSize(curIndex);
}
return bounds;
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,52 @@
/*
* 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 <QTableWidget>
#include <QHeaderView>
#include <QStringList>
#include <QVector>
#include <QPair>
#endif
namespace O3DE::ProjectManager
{
// Using a QTableWidget for its header
// Using a seperate model allows the setup of a header exactly as needed
class AdjustableHeaderWidget
: public QTableWidget
{
Q_OBJECT
public:
explicit AdjustableHeaderWidget(const QStringList& headerLabels,
const QVector<int>& defaultHeaderWidths, int minHeaderWidth,
const QVector<QHeaderView::ResizeMode>& resizeModes,
QWidget* parent = nullptr);
~AdjustableHeaderWidget() = default;
QPair<int, int> CalcColumnXBounds(int headerIndex) const;
inline constexpr static int s_headerTextIndent = 7;
inline constexpr static int s_headerWidgetHeight = 24;
QHeaderView* m_header;
signals:
void sectionsResized();
protected slots:
void OnSectionResized(int logicalIndex, int oldSize, int newSize);
private:
inline constexpr static int s_headerIndentSection = 11;
};
} // namespace O3DE::ProjectManager
@@ -17,7 +17,7 @@ namespace O3DE::ProjectManager
class ExternalLinkDialog
: public QDialog
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit ExternalLinkDialog(const QUrl& url, QWidget* parent = nullptr);
~ExternalLinkDialog() = default;
@@ -33,7 +33,7 @@ namespace O3DE::ProjectManager
class GemCartWidget
: public QScrollArea
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
GemCartWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr);
@@ -19,8 +19,10 @@
#include <GemCatalog/GemDependenciesDialog.h>
#include <GemCatalog/GemUpdateDialog.h>
#include <GemCatalog/GemUninstallDialog.h>
#include <GemCatalog/GemItemDelegate.h>
#include <DownloadController.h>
#include <ProjectUtils.h>
#include <AdjustableHeaderWidget.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
@@ -40,6 +42,13 @@ namespace O3DE::ProjectManager
GemCatalogScreen::GemCatalogScreen(QWidget* parent)
: ScreenWidget(parent)
{
// The width of either side panel (filters, inspector) in the catalog
constexpr int sidePanelWidth = 240;
// Querying qApp about styling reports the scroll bar being larger than it is so define it manually
constexpr int verticalScrollBarWidth = 8;
setObjectName("GemCatalogScreen");
m_gemModel = new GemModel(this);
m_proxyModel = new GemSortFilterProxyModel(m_gemModel, this);
@@ -69,10 +78,8 @@ namespace O3DE::ProjectManager
hLayout->setMargin(0);
vLayout->addLayout(hLayout);
m_gemListView = new GemListView(m_proxyModel, m_proxyModel->GetSelectionModel(), this);
m_rightPanelStack = new QStackedWidget(this);
m_rightPanelStack->setFixedWidth(240);
m_rightPanelStack->setFixedWidth(sidePanelWidth);
m_gemInspector = new GemInspector(m_gemModel, this);
@@ -81,18 +88,45 @@ namespace O3DE::ProjectManager
connect(m_gemInspector, &GemInspector::UninstallGem, this, &GemCatalogScreen::UninstallGem);
QWidget* filterWidget = new QWidget(this);
filterWidget->setFixedWidth(240);
filterWidget->setFixedWidth(sidePanelWidth);
m_filterWidgetLayout = new QVBoxLayout();
m_filterWidgetLayout->setMargin(0);
m_filterWidgetLayout->setSpacing(0);
filterWidget->setLayout(m_filterWidgetLayout);
GemListHeaderWidget* listHeaderWidget = new GemListHeaderWidget(m_proxyModel);
GemListHeaderWidget* catalogHeaderWidget = new GemListHeaderWidget(m_proxyModel);
constexpr int minHeaderSectionWidth = 100;
AdjustableHeaderWidget* listHeaderWidget = new AdjustableHeaderWidget(
QStringList{ tr("Gem Name"), tr("Gem Summary"), tr("Status") },
QVector<int>{
GemItemDelegate::s_defaultSummaryStartX - 30,
0, // Section is set to stretch to fit
GemItemDelegate::s_buttonWidth + GemItemDelegate::s_itemMargins.left() + GemItemDelegate::s_itemMargins.right() + GemItemDelegate::s_contentMargins.right()
},
minHeaderSectionWidth,
QVector<QHeaderView::ResizeMode>
{
QHeaderView::ResizeMode::Interactive,
QHeaderView::ResizeMode::Stretch,
QHeaderView::ResizeMode::Fixed
},
this);
m_gemListView = new GemListView(m_proxyModel, m_proxyModel->GetSelectionModel(), listHeaderWidget, this);
QHBoxLayout* listHeaderLayout = new QHBoxLayout();
listHeaderLayout->setMargin(0);
listHeaderLayout->setSpacing(0);
listHeaderLayout->addSpacing(GemItemDelegate::s_itemMargins.left());
listHeaderLayout->addWidget(listHeaderWidget);
listHeaderLayout->addSpacing(GemItemDelegate::s_itemMargins.right() + verticalScrollBarWidth);
QVBoxLayout* middleVLayout = new QVBoxLayout();
middleVLayout->setMargin(0);
middleVLayout->setSpacing(0);
middleVLayout->addWidget(listHeaderWidget);
middleVLayout->addWidget(catalogHeaderWidget);
middleVLayout->addLayout(listHeaderLayout);
middleVLayout->addWidget(m_gemListView);
hLayout->addWidget(filterWidget);
@@ -19,7 +19,7 @@ namespace O3DE::ProjectManager
class GemDependenciesDialog
: public QDialog
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemDependenciesDialog(GemModel* gemModel, QWidget *parent = nullptr);
~GemDependenciesDialog() = default;
@@ -26,7 +26,7 @@ namespace O3DE::ProjectManager
class FilterCategoryWidget
: public QWidget
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit FilterCategoryWidget(const QString& header,
@@ -28,7 +28,7 @@ namespace O3DE::ProjectManager
class GemInspector
: public QScrollArea
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemInspector(GemModel* model, QWidget* parent = nullptr);
@@ -9,6 +9,8 @@
#include <GemCatalog/GemItemDelegate.h>
#include <GemCatalog/GemModel.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <AdjustableHeaderWidget.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <QEvent>
@@ -22,12 +24,14 @@
#include <QAbstractTextDocumentLayout>
#include <QDesktopServices>
#include <QMovie>
#include <QHeaderView>
namespace O3DE::ProjectManager
{
GemItemDelegate::GemItemDelegate(QAbstractItemModel* model, QObject* parent)
GemItemDelegate::GemItemDelegate(QAbstractItemModel* model, AdjustableHeaderWidget* header, QObject* parent)
: QStyledItemDelegate(parent)
, m_model(model)
, m_headerWidget(header)
{
AddPlatformIcon(GemInfo::Android, ":/Android.svg");
AddPlatformIcon(GemInfo::iOS, ":/iOS.svg");
@@ -116,12 +120,15 @@ namespace O3DE::ProjectManager
// Gem name
QString gemName = GemModel::GetDisplayName(modelIndex);
QFont gemNameFont(options.font);
const int firstColumnMaxTextWidth = s_summaryStartX - 30;
QPair<int, int> nameXBounds = CalcColumnXBounds(HeaderOrder::Name);
const int nameStartX = nameXBounds.first;
const int firstColumnTextStartX = s_itemMargins.left() + nameStartX + AdjustableHeaderWidget::s_headerTextIndent;
const int firstColumnMaxTextWidth = nameXBounds.second - nameStartX - AdjustableHeaderWidget::s_headerTextIndent;
gemNameFont.setPixelSize(static_cast<int>(s_gemNameFontSize));
gemNameFont.setBold(true);
gemName = QFontMetrics(gemNameFont).elidedText(gemName, Qt::TextElideMode::ElideRight, firstColumnMaxTextWidth);
QRect gemNameRect = GetTextRect(gemNameFont, gemName, s_gemNameFontSize);
gemNameRect.moveTo(contentRect.left(), contentRect.top());
gemNameRect.moveTo(firstColumnTextStartX, contentRect.top());
painter->setFont(gemNameFont);
painter->setPen(m_textColor);
gemNameRect = painter->boundingRect(gemNameRect, Qt::TextSingleLine, gemName);
@@ -131,7 +138,7 @@ namespace O3DE::ProjectManager
QString gemCreator = GemModel::GetCreator(modelIndex);
gemCreator = standardFontMetrics.elidedText(gemCreator, Qt::TextElideMode::ElideRight, firstColumnMaxTextWidth);
QRect gemCreatorRect = GetTextRect(standardFont, gemCreator, s_fontSize);
gemCreatorRect.moveTo(contentRect.left(), contentRect.top() + gemNameRect.height());
gemCreatorRect.moveTo(firstColumnTextStartX, contentRect.top() + gemNameRect.height());
painter->setFont(standardFont);
gemCreatorRect = painter->boundingRect(gemCreatorRect, Qt::TextSingleLine, gemCreator);
@@ -157,10 +164,13 @@ namespace O3DE::ProjectManager
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,
const auto [summaryStartX, summaryEndX] = CalcColumnXBounds(HeaderOrder::Summary);
const QSize summarySize =
QSize(summaryEndX - summaryStartX - AdjustableHeaderWidget::s_headerTextIndent - s_extraSummarySpacing,
summaryHeight);
return QRect(QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize);
return QRect(
QPoint(s_itemMargins.left() + summaryStartX + AdjustableHeaderWidget::s_headerTextIndent, contentRect.top()), summarySize);
}
QSize GemItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const
@@ -169,7 +179,7 @@ namespace O3DE::ProjectManager
initStyleOption(&options, modelIndex);
int marginsHorizontal = s_itemMargins.left() + s_itemMargins.right() + s_contentMargins.left() + s_contentMargins.right();
return QSize(marginsHorizontal + s_buttonWidth + s_summaryStartX, s_height);
return QSize(marginsHorizontal + s_buttonWidth + s_defaultSummaryStartX, s_height);
}
bool GemItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex)
@@ -299,9 +309,17 @@ namespace O3DE::ProjectManager
return QFontMetrics(font).boundingRect(text);
}
QPair<int, int> GemItemDelegate::CalcColumnXBounds(HeaderOrder header) const
{
return m_headerWidget->CalcColumnXBounds(static_cast<int>(header));
}
QRect GemItemDelegate::CalcButtonRect(const QRect& contentRect) const
{
const QPoint topLeft = QPoint(contentRect.right() - s_buttonWidth, contentRect.center().y() - s_buttonHeight / 2);
const QPoint topLeft = QPoint(
s_itemMargins.left() + CalcColumnXBounds(HeaderOrder::Status).first + AdjustableHeaderWidget::s_headerTextIndent + s_statusIconSize +
s_statusButtonSpacing,
contentRect.center().y() - s_buttonHeight / 2);
const QSize size = QSize(s_buttonWidth, s_buttonHeight);
return QRect(topLeft, size);
}
@@ -331,18 +349,23 @@ namespace O3DE::ProjectManager
}
}
void GemItemDelegate::DrawFeatureTags(QPainter* painter, const QRect& contentRect, const QStringList& featureTags, const QFont& standardFont, const QRect& summaryRect) const
void GemItemDelegate::DrawFeatureTags(
QPainter* painter,
const QRect& contentRect,
const QStringList& featureTags,
const QFont& standardFont,
const QRect& summaryRect) const
{
QFont gemFeatureTagFont(standardFont);
gemFeatureTagFont.setPixelSize(s_featureTagFontSize);
gemFeatureTagFont.setBold(false);
painter->setFont(gemFeatureTagFont);
int x = s_summaryStartX;
int x = CalcColumnXBounds(HeaderOrder::Summary).first + AdjustableHeaderWidget::s_headerTextIndent;
for (const QString& featureTag : featureTags)
{
QRect featureTagRect = GetTextRect(gemFeatureTagFont, featureTag, s_featureTagFontSize);
featureTagRect.moveTo(contentRect.left() + x + s_featureTagBorderMarginX,
featureTagRect.moveTo(s_itemMargins.left() + x + s_featureTagBorderMarginX,
contentRect.top() + 47);
featureTagRect = painter->boundingRect(featureTagRect, Qt::TextSingleLine, featureTag);
@@ -19,13 +19,15 @@ QT_FORWARD_DECLARE_CLASS(QEvent)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(AdjustableHeaderWidget)
class GemItemDelegate
: public QStyledItemDelegate
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemItemDelegate(QAbstractItemModel* model, QObject* parent = nullptr);
explicit GemItemDelegate(QAbstractItemModel* model, AdjustableHeaderWidget* header, QObject* parent = nullptr);
~GemItemDelegate() = default;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
@@ -45,12 +47,13 @@ namespace O3DE::ProjectManager
inline constexpr static int s_height = 105; // Gem item total height
inline constexpr static qreal s_gemNameFontSize = 13.0;
inline constexpr static qreal s_fontSize = 12.0;
inline constexpr static int s_summaryStartX = 150;
inline constexpr static int s_defaultSummaryStartX = 190;
// Margin and borders
inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/16, /*top=*/8, /*right=*/16, /*bottom=*/8); // Item border distances
inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/20, /*top=*/12, /*right=*/20, /*bottom=*/12); // Distances of the elements within an item to the item borders
inline constexpr static int s_borderWidth = 4;
inline constexpr static int s_extraSummarySpacing = s_itemMargins.right();
// Button
inline constexpr static int s_buttonWidth = 32;
@@ -65,6 +68,13 @@ namespace O3DE::ProjectManager
inline constexpr static int s_featureTagBorderMarginY = 3;
inline constexpr static int s_featureTagSpacing = 7;
enum class HeaderOrder
{
Name,
Summary,
Status
};
signals:
void MovieStartedPlaying(const QMovie* playingMovie) const;
@@ -74,13 +84,20 @@ 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;
QPair<int, int> CalcColumnXBounds(HeaderOrder header) 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& buttonRect, const QModelIndex& modelIndex) const;
void DrawFeatureTags(QPainter* painter, const QRect& contentRect, const QStringList& featureTags, const QFont& standardFont, const QRect& summaryRect) 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;
void DrawDownloadStatusIcon(QPainter* painter, const QRect& contentRect, const QRect& buttonRect, const QModelIndex& modelIndex) const;
void DrawDownloadStatusIcon(
QPainter* painter, const QRect& contentRect, const QRect& buttonRect, const QModelIndex& modelIndex) const;
QAbstractItemModel* m_model = nullptr;
@@ -100,5 +117,7 @@ namespace O3DE::ProjectManager
QPixmap m_downloadSuccessfulPixmap;
QPixmap m_downloadFailedPixmap;
QMovie* m_downloadingMovie = nullptr;
AdjustableHeaderWidget* m_headerWidget = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -78,37 +78,9 @@ namespace O3DE::ProjectManager
// Separating line
QFrame* hLine = new QFrame();
hLine->setFrameShape(QFrame::HLine);
hLine->setStyleSheet("color: #666666;");
hLine->setObjectName("horizontalSeparatingLine");
vLayout->addWidget(hLine);
vLayout->addSpacing(GemItemDelegate::s_contentMargins.top());
// Bottom section
QHBoxLayout* columnHeaderLayout = new QHBoxLayout();
columnHeaderLayout->setAlignment(Qt::AlignLeft);
const int gemNameStartX = GemItemDelegate::s_itemMargins.left() + GemItemDelegate::s_contentMargins.left() - 1;
columnHeaderLayout->addSpacing(gemNameStartX);
QLabel* gemNameLabel = new QLabel(tr("Gem Name"));
gemNameLabel->setObjectName("GemCatalogHeaderLabel");
columnHeaderLayout->addWidget(gemNameLabel);
columnHeaderLayout->addSpacing(89);
QLabel* gemSummaryLabel = new QLabel(tr("Gem Summary"));
gemSummaryLabel->setObjectName("GemCatalogHeaderLabel");
columnHeaderLayout->addWidget(gemSummaryLabel);
QSpacerItem* horizontalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
columnHeaderLayout->addSpacerItem(horizontalSpacer);
QLabel* gemSelectedLabel = new QLabel(tr("Status"));
gemSelectedLabel->setObjectName("GemCatalogHeaderLabel");
columnHeaderLayout->addWidget(gemSelectedLabel);
columnHeaderLayout->addSpacing(72);
vLayout->addLayout(columnHeaderLayout);
}
} // namespace O3DE::ProjectManager
@@ -19,7 +19,7 @@ namespace O3DE::ProjectManager
class GemListHeaderWidget
: public QFrame
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemListHeaderWidget(GemSortFilterProxyModel* proxyModel, QWidget* parent = nullptr);
@@ -8,12 +8,15 @@
#include <GemCatalog/GemListView.h>
#include <GemCatalog/GemItemDelegate.h>
#include <AdjustableHeaderWidget.h>
#include <QMovie>
#include <QHeaderView>
namespace O3DE::ProjectManager
{
GemListView::GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent)
GemListView::GemListView(
QAbstractItemModel* model, QItemSelectionModel* selectionModel, AdjustableHeaderWidget* header, QWidget* parent)
: QListView(parent)
{
setObjectName("GemCatalogListView");
@@ -21,7 +24,7 @@ namespace O3DE::ProjectManager
setModel(model);
setSelectionModel(selectionModel);
GemItemDelegate* itemDelegate = new GemItemDelegate(model, this);
GemItemDelegate* itemDelegate = new GemItemDelegate(model, header, this);
connect(itemDelegate, &GemItemDelegate::MovieStartedPlaying, [=](const QMovie* playingMovie)
{
@@ -31,6 +34,8 @@ namespace O3DE::ProjectManager
this->viewport()->repaint();
});
});
connect(header, &AdjustableHeaderWidget::sectionsResized, [=] { update(); });
setItemDelegate(itemDelegate);
}
@@ -16,13 +16,15 @@
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(AdjustableHeaderWidget)
class GemListView
: public QListView
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent = nullptr);
explicit GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, AdjustableHeaderWidget* header, QWidget* parent = nullptr);
~GemListView() = default;
};
} // namespace O3DE::ProjectManager
@@ -21,7 +21,7 @@ namespace O3DE::ProjectManager
class GemModel
: public QStandardItemModel
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemModel(QObject* parent = nullptr);
@@ -16,7 +16,7 @@
namespace O3DE::ProjectManager
{
GemRequirementDelegate::GemRequirementDelegate(QAbstractItemModel* model, QObject* parent)
: GemItemDelegate(model, parent)
: GemItemDelegate(model, nullptr, parent)
{
}
@@ -54,7 +54,7 @@ namespace O3DE::ProjectManager
// Gem name
QString gemName = GemModel::GetDisplayName(modelIndex);
QFont gemNameFont(options.font);
const int firstColumnMaxTextWidth = s_summaryStartX - 30;
const int firstColumnMaxTextWidth = s_defaultSummaryStartX - 30;
gemName = QFontMetrics(gemNameFont).elidedText(gemName, Qt::TextElideMode::ElideRight, firstColumnMaxTextWidth);
gemNameFont.setPixelSize(static_cast<int>(s_gemNameFontSize));
gemNameFont.setBold(true);
@@ -75,8 +75,8 @@ namespace O3DE::ProjectManager
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);
const QSize requirementSize = QSize(contentRect.width() - s_defaultSummaryStartX - s_itemMargins.right(), contentRect.height());
return QRect(QPoint(contentRect.left() + s_defaultSummaryStartX, contentRect.top()), requirementSize);
}
bool GemRequirementDelegate::editorEvent(
@@ -18,7 +18,7 @@ namespace O3DE::ProjectManager
class GemRequirementDelegate
: public GemItemDelegate
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemRequirementDelegate(QAbstractItemModel* model, QObject* parent = nullptr);
@@ -19,7 +19,7 @@ namespace O3DE::ProjectManager
class GemRequirementDialog
: public QDialog
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemRequirementDialog(GemModel* model, QWidget *parent = nullptr);
~GemRequirementDialog() = default;
@@ -22,7 +22,7 @@ namespace O3DE::ProjectManager
class GemRequirementFilterProxyModel
: public QSortFilterProxyModel
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
GemRequirementFilterProxyModel(GemModel* sourceModel, QObject* parent = nullptr);
@@ -19,7 +19,7 @@ namespace O3DE::ProjectManager
class GemRequirementListView
: public QListView
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemRequirementListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent = nullptr);
@@ -22,7 +22,7 @@ namespace O3DE::ProjectManager
class GemSortFilterProxyModel
: public QSortFilterProxyModel
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
enum class GemSelected
@@ -17,7 +17,7 @@ namespace O3DE::ProjectManager
class GemUninstallDialog
: public QDialog
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemUninstallDialog(const QString& gemName, QWidget *parent = nullptr);
~GemUninstallDialog() = default;
@@ -17,7 +17,7 @@ namespace O3DE::ProjectManager
class GemUpdateDialog
: public QDialog
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public :
explicit GemUpdateDialog(const QString& gemName, bool updateAvaliable = true, QWidget* parent = nullptr);
~GemUpdateDialog() = default;
@@ -26,7 +26,7 @@ namespace O3DE::ProjectManager
{
class GemRepoInspector : public QScrollArea
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public : explicit GemRepoInspector(GemRepoModel* model, QWidget* parent = nullptr);
~GemRepoInspector() = default;
@@ -9,16 +9,19 @@
#include <GemRepo/GemRepoItemDelegate.h>
#include <GemRepo/GemRepoModel.h>
#include <ProjectManagerDefs.h>
#include <AdjustableHeaderWidget.h>
#include <QEvent>
#include <QPainter>
#include <QMouseEvent>
#include <QHeaderView>
namespace O3DE::ProjectManager
{
GemRepoItemDelegate::GemRepoItemDelegate(QAbstractItemModel* model, QObject* parent)
GemRepoItemDelegate::GemRepoItemDelegate(QAbstractItemModel* model, AdjustableHeaderWidget* header, QObject* parent)
: QStyledItemDelegate(parent)
, m_model(model)
, m_headerWidget(header)
{
m_refreshIcon = QIcon(":/Refresh.svg").pixmap(s_refreshIconSize, s_refreshIconSize);
m_editIcon = QIcon(":/Edit.svg").pixmap(s_iconSize, s_iconSize);
@@ -69,44 +72,55 @@ namespace O3DE::ProjectManager
painter->restore();
}
int currentHorizontalOffset = CalcColumnXBounds(HeaderOrder::Name).first;
// Repo name
QString repoName = GemRepoModel::GetName(modelIndex);
repoName = QFontMetrics(standardFont).elidedText(repoName, Qt::TextElideMode::ElideRight, s_nameMaxWidth);
int sectionSize = m_headerWidget->m_header->sectionSize(static_cast<int>(HeaderOrder::Name));
repoName = standardFontMetrics.elidedText(repoName, Qt::TextElideMode::ElideRight,
sectionSize - AdjustableHeaderWidget::s_headerTextIndent);
QRect repoNameRect = GetTextRect(standardFont, repoName, s_fontSize);
int currentHorizontalOffset = contentRect.left();
repoNameRect.moveTo(currentHorizontalOffset, contentRect.center().y() - repoNameRect.height() / 2);
repoNameRect.moveTo(currentHorizontalOffset + AdjustableHeaderWidget::s_headerTextIndent,
contentRect.center().y() - repoNameRect.height() / 2);
repoNameRect = painter->boundingRect(repoNameRect, Qt::TextSingleLine, repoName);
painter->drawText(repoNameRect, Qt::TextSingleLine, repoName);
// Rem repo creator
currentHorizontalOffset += sectionSize;
sectionSize = m_headerWidget->m_header->sectionSize(static_cast<int>(HeaderOrder::Creator));
QString repoCreator = GemRepoModel::GetCreator(modelIndex);
repoCreator = standardFontMetrics.elidedText(repoCreator, Qt::TextElideMode::ElideRight, s_creatorMaxWidth);
repoCreator = standardFontMetrics.elidedText(repoCreator, Qt::TextElideMode::ElideRight,
sectionSize - AdjustableHeaderWidget::s_headerTextIndent);
QRect repoCreatorRect = GetTextRect(standardFont, repoCreator, s_fontSize);
currentHorizontalOffset += s_nameMaxWidth + s_contentSpacing;
repoCreatorRect.moveTo(currentHorizontalOffset, contentRect.center().y() - repoCreatorRect.height() / 2);
repoCreatorRect.moveTo(currentHorizontalOffset + AdjustableHeaderWidget::s_headerTextIndent,
contentRect.center().y() - repoCreatorRect.height() / 2);
repoCreatorRect = painter->boundingRect(repoCreatorRect, Qt::TextSingleLine, repoCreator);
painter->drawText(repoCreatorRect, Qt::TextSingleLine, repoCreator);
// Repo update
currentHorizontalOffset += sectionSize;
sectionSize = m_headerWidget->m_header->sectionSize(static_cast<int>(HeaderOrder::Update));
QString repoUpdatedDate = GemRepoModel::GetLastUpdated(modelIndex).toString(RepoTimeFormat);
repoUpdatedDate = standardFontMetrics.elidedText(repoUpdatedDate, Qt::TextElideMode::ElideRight, s_updatedMaxWidth);
repoUpdatedDate = standardFontMetrics.elidedText(
repoUpdatedDate, Qt::TextElideMode::ElideRight,
sectionSize - GemRepoItemDelegate::s_refreshIconSpacing - GemRepoItemDelegate::s_refreshIconSize - AdjustableHeaderWidget::s_headerTextIndent);
QRect repoUpdatedDateRect = GetTextRect(standardFont, repoUpdatedDate, s_fontSize);
currentHorizontalOffset += s_creatorMaxWidth + s_contentSpacing;
repoUpdatedDateRect.moveTo(currentHorizontalOffset, contentRect.center().y() - repoUpdatedDateRect.height() / 2);
repoUpdatedDateRect.moveTo(currentHorizontalOffset + AdjustableHeaderWidget::s_headerTextIndent,
contentRect.center().y() - repoUpdatedDateRect.height() / 2);
repoUpdatedDateRect = painter->boundingRect(repoUpdatedDateRect, Qt::TextSingleLine, repoUpdatedDate);
painter->drawText(repoUpdatedDateRect, Qt::TextSingleLine, repoUpdatedDate);
// Draw refresh button
painter->drawPixmap(
repoUpdatedDateRect.left() + s_updatedMaxWidth + s_refreshIconSpacing,
contentRect.center().y() - s_refreshIconSize / 3, // Dividing size by 3 centers much better
m_refreshIcon);
const QRect refreshButtonRect = CalcRefreshButtonRect(contentRect);
painter->drawPixmap(refreshButtonRect.topLeft(), m_refreshIcon);
if (options.state & QStyle::State_MouseOver)
{
@@ -121,8 +135,8 @@ namespace O3DE::ProjectManager
QStyleOptionViewItem options(option);
initStyleOption(&options, modelIndex);
int marginsHorizontal = s_itemMargins.left() + s_itemMargins.right() + s_contentMargins.left() + s_contentMargins.right();
return QSize(marginsHorizontal + s_nameMaxWidth + s_creatorMaxWidth + s_updatedMaxWidth + s_contentSpacing * 3, s_height);
const int marginsHorizontal = s_itemMargins.left() + s_itemMargins.right() + s_contentMargins.left() + s_contentMargins.right();
return QSize(marginsHorizontal + s_nameDefaultWidth + s_creatorDefaultWidth + s_updatedDefaultWidth, s_height);
}
bool GemRepoItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex)
@@ -185,22 +199,31 @@ namespace O3DE::ProjectManager
return QFontMetrics(font).boundingRect(text);
}
QPair<int, int> GemRepoItemDelegate::CalcColumnXBounds(HeaderOrder header) const
{
return m_headerWidget->CalcColumnXBounds(static_cast<int>(header));
}
QRect GemRepoItemDelegate::CalcDeleteButtonRect(const QRect& contentRect) const
{
const QPoint topLeft = QPoint(contentRect.right() - s_iconSize, contentRect.center().y() - s_iconSize / 2);
const int deleteHeaderEndX = CalcColumnXBounds(HeaderOrder::Delete).second;
const QPoint topLeft = QPoint(deleteHeaderEndX - s_iconSize - s_contentMargins.right(), contentRect.center().y() - s_iconSize / 2);
return QRect(topLeft, QSize(s_iconSize, s_iconSize));
}
QRect GemRepoItemDelegate::CalcRefreshButtonRect(const QRect& contentRect) const
{
const int topLeftX = contentRect.left() + s_nameMaxWidth + s_creatorMaxWidth + s_updatedMaxWidth + s_contentSpacing * 2 + s_refreshIconSpacing;
const QPoint topLeft = QPoint(topLeftX, contentRect.center().y() - s_refreshIconSize / 3);
const int headerEndX = CalcColumnXBounds(HeaderOrder::Update).second;
const int leftX = headerEndX - s_refreshIconSize - s_refreshIconSpacing;
// Dividing size by 3 centers much better
const QPoint topLeft = QPoint(leftX, contentRect.center().y() - s_refreshIconSize / 3);
return QRect(topLeft, QSize(s_refreshIconSize, s_refreshIconSize));
}
void GemRepoItemDelegate::DrawEditButtons(QPainter* painter, const QRect& contentRect) const
{
painter->drawPixmap(contentRect.right() - s_iconSize, contentRect.center().y() - s_iconSize / 2, m_deleteIcon);
const QRect deleteButtonRect = CalcDeleteButtonRect(contentRect);
painter->drawPixmap(deleteButtonRect, m_deleteIcon);
}
} // namespace O3DE::ProjectManager
@@ -18,13 +18,15 @@ QT_FORWARD_DECLARE_CLASS(QEvent)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(AdjustableHeaderWidget)
class GemRepoItemDelegate
: public QStyledItemDelegate
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemRepoItemDelegate(QAbstractItemModel* model, QObject* parent = nullptr);
explicit GemRepoItemDelegate(QAbstractItemModel* model, AdjustableHeaderWidget* header, QObject* parent = nullptr);
~GemRepoItemDelegate() = default;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
@@ -42,15 +44,14 @@ namespace O3DE::ProjectManager
inline constexpr static qreal s_fontSize = 12.0;
// Margin and borders
inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/0, /*top=*/8, /*right=*/60, /*bottom=*/8); // Item border distances
inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/0, /*top=*/8, /*right=*/0, /*bottom=*/8); // Item border distances
inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/20, /*top=*/20, /*right=*/20, /*bottom=*/20); // Distances of the elements within an item to the item borders
inline constexpr static int s_borderWidth = 4;
// Content
inline constexpr static int s_contentSpacing = 5;
inline constexpr static int s_nameMaxWidth = 145;
inline constexpr static int s_creatorMaxWidth = 115;
inline constexpr static int s_updatedMaxWidth = 125;
inline constexpr static int s_nameDefaultWidth = 150;
inline constexpr static int s_creatorDefaultWidth = 120;
inline constexpr static int s_updatedDefaultWidth = 130;
// Icon
inline constexpr static int s_iconSize = 24;
@@ -58,6 +59,14 @@ namespace O3DE::ProjectManager
inline constexpr static int s_refreshIconSize = 14;
inline constexpr static int s_refreshIconSpacing = 10;
enum class HeaderOrder
{
Name,
Creator,
Update,
Delete
};
signals:
void RemoveRepo(const QModelIndex& modelIndex);
void RefreshRepo(const QModelIndex& modelIndex);
@@ -65,13 +74,15 @@ namespace O3DE::ProjectManager
protected:
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;
QPair<int, int> CalcColumnXBounds(HeaderOrder header) const;
QRect CalcDeleteButtonRect(const QRect& contentRect) const;
QRect CalcRefreshButtonRect(const QRect& contentRect) const;
void DrawEditButtons(QPainter* painter, const QRect& contentRect) const;
QAbstractItemModel* m_model = nullptr;
AdjustableHeaderWidget* m_headerWidget = nullptr;
QPixmap m_refreshIcon;
QPixmap m_editIcon;
QPixmap m_deleteIcon;
@@ -8,12 +8,15 @@
#include <GemRepo/GemRepoListView.h>
#include <GemRepo/GemRepoItemDelegate.h>
#include <AdjustableHeaderWidget.h>
#include <QShortcut>
#include <QHeaderView>
namespace O3DE::ProjectManager
{
GemRepoListView::GemRepoListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent)
GemRepoListView::GemRepoListView(
QAbstractItemModel* model, QItemSelectionModel* selectionModel, AdjustableHeaderWidget* header, QWidget* parent)
: QListView(parent)
{
setObjectName("gemRepoListView");
@@ -22,9 +25,10 @@ namespace O3DE::ProjectManager
setModel(model);
setSelectionModel(selectionModel);
GemRepoItemDelegate* itemDelegate = new GemRepoItemDelegate(model, this);
GemRepoItemDelegate* itemDelegate = new GemRepoItemDelegate(model, header, this);
connect(itemDelegate, &GemRepoItemDelegate::RemoveRepo, this, &GemRepoListView::RemoveRepo);
connect(itemDelegate, &GemRepoItemDelegate::RefreshRepo, this, &GemRepoListView::RefreshRepo);
connect(header, &AdjustableHeaderWidget::sectionsResized, [=] { update(); });
setItemDelegate(itemDelegate);
}
} // namespace O3DE::ProjectManager
@@ -17,13 +17,19 @@ QT_FORWARD_DECLARE_CLASS(QAbstractItemModel)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(AdjustableHeaderWidget)
class GemRepoListView
: public QListView
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemRepoListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent = nullptr);
explicit GemRepoListView(
QAbstractItemModel* model,
QItemSelectionModel* selectionModel,
AdjustableHeaderWidget* header,
QWidget* parent = nullptr);
~GemRepoListView() = default;
signals:
@@ -21,7 +21,7 @@ namespace O3DE::ProjectManager
class GemRepoModel
: public QStandardItemModel
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit GemRepoModel(QObject* parent = nullptr);
@@ -15,6 +15,8 @@
#include <PythonBindingsInterface.h>
#include <ProjectManagerDefs.h>
#include <ProjectUtils.h>
#include <AdjustableHeaderWidget.h>
#include <ProjectManagerDefs.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
@@ -248,6 +250,9 @@ namespace O3DE::ProjectManager
QFrame* GemRepoScreen::CreateReposContent()
{
constexpr int inspectorWidth = 240;
constexpr int middleLayoutIndent = 60;
QFrame* contentFrame = new QFrame(this);
QHBoxLayout* hLayout = new QHBoxLayout();
@@ -255,7 +260,7 @@ namespace O3DE::ProjectManager
hLayout->setSpacing(0);
contentFrame->setLayout(hLayout);
hLayout->addSpacing(60);
hLayout->addSpacing(middleLayoutIndent);
QVBoxLayout* middleVLayout = new QVBoxLayout();
middleVLayout->setMargin(0);
@@ -287,37 +292,34 @@ namespace O3DE::ProjectManager
connect(addRepoButton, &QPushButton::clicked, this, &GemRepoScreen::HandleAddRepoButton);
topMiddleHLayout->addSpacing(30);
middleVLayout->addLayout(topMiddleHLayout);
middleVLayout->addSpacing(30);
// Create a QTableWidget just for its header
// Using a seperate model allows the setup of a header exactly as needed
m_gemRepoHeaderTable = new QTableWidget(this);
m_gemRepoHeaderTable->setObjectName("gemRepoHeaderTable");
m_gemRepoListHeader = m_gemRepoHeaderTable->horizontalHeader();
m_gemRepoListHeader->setObjectName("gemRepoListHeader");
m_gemRepoListHeader->setDefaultAlignment(Qt::AlignLeft);
m_gemRepoListHeader->setSectionResizeMode(QHeaderView::ResizeMode::Fixed);
constexpr int minHeaderSectionWidth = 120;
// Insert columns so the header labels will show up
m_gemRepoHeaderTable->insertColumn(0);
m_gemRepoHeaderTable->insertColumn(1);
m_gemRepoHeaderTable->insertColumn(2);
m_gemRepoHeaderTable->setHorizontalHeaderLabels({ tr("Repository Name"), tr("Creator"), tr("Updated") });
m_gemRepoHeaderTable = new AdjustableHeaderWidget(
QStringList{ tr("Repository Name"), tr("Creator"), tr("Updated"), "" },
QVector<int>{
GemRepoItemDelegate::s_nameDefaultWidth,
GemRepoItemDelegate::s_creatorDefaultWidth,
GemRepoItemDelegate::s_updatedDefaultWidth + GemRepoItemDelegate::s_refreshIconSpacing + GemRepoItemDelegate::s_refreshIconSize,
// Include invisible header for delete button
GemRepoItemDelegate::s_iconSize + GemRepoItemDelegate::s_contentMargins.right()
},
minHeaderSectionWidth,
QVector<QHeaderView::ResizeMode>
{
QHeaderView::ResizeMode::Interactive,
QHeaderView::ResizeMode::Stretch,
QHeaderView::ResizeMode::Fixed,
QHeaderView::ResizeMode::Fixed
},
this);
const int headerExtraMargin = 18;
m_gemRepoListHeader->resizeSection(0, GemRepoItemDelegate::s_nameMaxWidth + GemRepoItemDelegate::s_contentSpacing + headerExtraMargin);
m_gemRepoListHeader->resizeSection(1, GemRepoItemDelegate::s_creatorMaxWidth + GemRepoItemDelegate::s_contentSpacing);
m_gemRepoListHeader->resizeSection(2, GemRepoItemDelegate::s_updatedMaxWidth + GemRepoItemDelegate::s_contentSpacing);
// Required to set stylesheet in code as it will not be respected if set in qss
m_gemRepoHeaderTable->horizontalHeader()->setStyleSheet("QHeaderView::section { background-color:transparent; color:white; font-size:12px; border-style:none; }");
middleVLayout->addWidget(m_gemRepoHeaderTable);
m_gemRepoListView = new GemRepoListView(m_gemRepoModel, m_gemRepoModel->GetSelectionModel(), this);
m_gemRepoListView = new GemRepoListView(m_gemRepoModel, m_gemRepoModel->GetSelectionModel(), m_gemRepoHeaderTable, this);
middleVLayout->addWidget(m_gemRepoListView);
connect(m_gemRepoListView, &GemRepoListView::RemoveRepo, this, &GemRepoScreen::HandleRemoveRepoButton);
@@ -325,8 +327,10 @@ namespace O3DE::ProjectManager
hLayout->addLayout(middleVLayout);
hLayout->addSpacing(middleLayoutIndent);
m_gemRepoInspector = new GemRepoInspector(m_gemRepoModel, this);
m_gemRepoInspector->setFixedWidth(240);
m_gemRepoInspector->setFixedWidth(inspectorWidth);
hLayout->addWidget(m_gemRepoInspector);
return contentFrame;
@@ -24,6 +24,7 @@ namespace O3DE::ProjectManager
QT_FORWARD_DECLARE_CLASS(GemRepoInspector)
QT_FORWARD_DECLARE_CLASS(GemRepoListView)
QT_FORWARD_DECLARE_CLASS(GemRepoModel)
QT_FORWARD_DECLARE_CLASS(AdjustableHeaderWidget)
class GemRepoScreen
: public ScreenWidget
@@ -59,7 +60,7 @@ namespace O3DE::ProjectManager
QFrame* m_noRepoContent;
QFrame* m_repoContent;
QTableWidget* m_gemRepoHeaderTable = nullptr;
AdjustableHeaderWidget* m_gemRepoHeaderTable = nullptr;
QHeaderView* m_gemRepoListHeader = nullptr;
GemRepoListView* m_gemRepoListView = nullptr;
GemRepoInspector* m_gemRepoInspector = nullptr;
@@ -22,7 +22,7 @@ namespace O3DE::ProjectManager
class GemsSubWidget
: public QWidget
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
GemsSubWidget(QWidget* parent = nullptr);
@@ -22,7 +22,7 @@ namespace O3DE::ProjectManager
class LinkLabel
: public QLabel
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
LinkLabel(const QString& text = {}, const QUrl& url = {}, int fontSize = 10, QWidget* parent = nullptr);
@@ -31,7 +31,7 @@ namespace O3DE::ProjectManager
class LabelButton
: public QLabel
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit LabelButton(QWidget* parent = nullptr);
@@ -11,6 +11,7 @@
namespace O3DE::ProjectManager
{
inline constexpr static int MinWindowWidth = 1200;
inline constexpr static int ProjectPreviewImageWidth = 210;
inline constexpr static int ProjectPreviewImageHeight = 280;
inline constexpr static int ProjectTemplateImageWidth = 92;
@@ -20,7 +20,7 @@ namespace O3DE::ProjectManager
class ScreenHeader
: public QFrame
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
ScreenHeader(QWidget* parent = nullptr);
+1 -1
View File
@@ -27,7 +27,7 @@ namespace O3DE::ProjectManager
class TagWidget
: public QLabel
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit TagWidget(const Tag& id, QWidget* parent = nullptr);
@@ -17,7 +17,7 @@ namespace O3DE::ProjectManager
class TemplateButton
: public QPushButton
{
Q_OBJECT // AUTOMOC
Q_OBJECT
public:
explicit TemplateButton(const QString& imagePath, const QString& labelText, QWidget* parent = nullptr);