From d03f946609f3d4beb53a4a13d677ca42409fd9a6 Mon Sep 17 00:00:00 2001
From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com>
Date: Mon, 10 May 2021 11:32:13 +0200
Subject: [PATCH] [LYN-2515] Project Manager Gem List (#642)
* [LYN-2515] Project Manager Gem List Base
* Added gem model based on a standard item model
* Added list view using the gem model
* Added item delegate for a gem according to the UX design
* Removed th gem catalog ui file and replaced it with code
* Moved the gem catalog files into a sub folder
* Added drawing the Added/Get button and the platform icons
---
.../ProjectManager/Resources/Android.svg | 10 ++
Code/Tools/ProjectManager/Resources/Linux.svg | 14 +++
.../ProjectManager/Resources/Windows.svg | 7 ++
Code/Tools/ProjectManager/Resources/iOS.svg | 3 +
Code/Tools/ProjectManager/Resources/macOS.svg | 3 +
.../Source/GemCatalog/GemCatalog.cpp | 18 ++--
.../Source/GemCatalog/GemInfo.h | 11 +-
.../Source/GemCatalog/GemItemDelegate.cpp | 101 +++++++++++++++++-
.../Source/GemCatalog/GemItemDelegate.h | 19 +++-
.../Source/GemCatalog/GemModel.cpp | 2 +-
.../Source/GemCatalog/GemModel.h | 2 +-
Code/Tools/ProjectManager/project_manager.qrc | 11 +-
12 files changed, 178 insertions(+), 23 deletions(-)
create mode 100644 Code/Tools/ProjectManager/Resources/Android.svg
create mode 100644 Code/Tools/ProjectManager/Resources/Linux.svg
create mode 100644 Code/Tools/ProjectManager/Resources/Windows.svg
create mode 100644 Code/Tools/ProjectManager/Resources/iOS.svg
create mode 100644 Code/Tools/ProjectManager/Resources/macOS.svg
diff --git a/Code/Tools/ProjectManager/Resources/Android.svg b/Code/Tools/ProjectManager/Resources/Android.svg
new file mode 100644
index 0000000000..a4b610a3d6
--- /dev/null
+++ b/Code/Tools/ProjectManager/Resources/Android.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/Code/Tools/ProjectManager/Resources/Linux.svg b/Code/Tools/ProjectManager/Resources/Linux.svg
new file mode 100644
index 0000000000..843d60cd82
--- /dev/null
+++ b/Code/Tools/ProjectManager/Resources/Linux.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/Code/Tools/ProjectManager/Resources/Windows.svg b/Code/Tools/ProjectManager/Resources/Windows.svg
new file mode 100644
index 0000000000..46da6693a1
--- /dev/null
+++ b/Code/Tools/ProjectManager/Resources/Windows.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/Code/Tools/ProjectManager/Resources/iOS.svg b/Code/Tools/ProjectManager/Resources/iOS.svg
new file mode 100644
index 0000000000..871d36f657
--- /dev/null
+++ b/Code/Tools/ProjectManager/Resources/iOS.svg
@@ -0,0 +1,3 @@
+
diff --git a/Code/Tools/ProjectManager/Resources/macOS.svg b/Code/Tools/ProjectManager/Resources/macOS.svg
new file mode 100644
index 0000000000..4d433be6a3
--- /dev/null
+++ b/Code/Tools/ProjectManager/Resources/macOS.svg
@@ -0,0 +1,3 @@
+
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalog.cpp
index 6ceb443df8..6bb1e4959f 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalog.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalog.cpp
@@ -21,8 +21,6 @@ namespace O3DE::ProjectManager
GemCatalog::GemCatalog(ProjectManagerWindow* window)
: ScreenWidget(window)
{
- ConnectSlotsAndSignals();
-
m_gemModel = new GemModel(this);
QVBoxLayout* vLayout = new QVBoxLayout();
@@ -56,36 +54,36 @@ namespace O3DE::ProjectManager
m_gemModel->AddGem(GemInfo("EMotion FX",
"O3DE Foundation",
"EMFX is a real-time character animation system. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
- (GemInfo::Android | GemInfo::iOS | GemInfo::Windows | GemInfo::Linux),
+ (GemInfo::Android | GemInfo::iOS | GemInfo::macOS | GemInfo::Windows | GemInfo::Linux),
true));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Atom",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
- GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
+ GemInfo::Android | GemInfo::Windows | GemInfo::Linux | GemInfo::macOS,
true));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("PhysX",
- "O3DE Foundation",
+ "O3DE London",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
- GemInfo::Android | GemInfo::Linux,
+ GemInfo::Android | GemInfo::Linux | GemInfo::macOS,
false));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Certificate Manager",
- "O3DE Foundation",
+ "O3DE Irvine",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
GemInfo::Windows,
false));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Cloud Gem Framework",
- "O3DE Foundation",
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
+ "O3DE Seattle",
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
GemInfo::iOS | GemInfo::Linux,
false));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Achievements",
"O3DE Foundation",
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
false));
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h
index e5aa9c41f7..8c5040eb84 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h
@@ -26,11 +26,12 @@ namespace O3DE::ProjectManager
public:
enum Platform
{
- Android = 0x0,
- iOS = 0x1,
- Linux = 0x2,
- macOS = 0x3,
- Windows = 0x4
+ Android = 1 << 0,
+ iOS = 1 << 1,
+ Linux = 1 << 2,
+ macOS = 1 << 3,
+ Windows = 1 << 4,
+ NumPlatforms = 5
};
Q_DECLARE_FLAGS(Platforms, Platform)
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
index 22e77ed40e..434a4aeef2 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
@@ -22,6 +22,18 @@ namespace O3DE::ProjectManager
: QStyledItemDelegate(parent)
, m_gemModel(gemModel)
{
+ AddPlatformIcon(GemInfo::Android, ":/Resources/Android.svg");
+ AddPlatformIcon(GemInfo::iOS, ":/Resources/iOS.svg");
+ AddPlatformIcon(GemInfo::Linux, ":/Resources/Linux.svg");
+ AddPlatformIcon(GemInfo::macOS, ":/Resources/macOS.svg");
+ AddPlatformIcon(GemInfo::Windows, ":/Resources/Windows.svg");
+ }
+
+ void GemItemDelegate::AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath)
+ {
+ QPixmap pixmap(iconPath);
+ qreal aspectRatio = static_cast(pixmap.width()) / pixmap.height();
+ m_platformIcons.insert(platform, QIcon(iconPath).pixmap(s_platformIconSize * aspectRatio, s_platformIconSize));
}
void GemItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const
@@ -87,7 +99,7 @@ namespace O3DE::ProjectManager
painter->drawText(gemCreatorRect, Qt::TextSingleLine, gemCreator);
// Gem summary
- const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_itemMargins.right() * 4, contentRect.height());
+ const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 4, contentRect.height());
const QRect summaryRect = QRect(/*topLeft=*/QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize);
painter->setFont(standardFont);
@@ -96,6 +108,10 @@ namespace O3DE::ProjectManager
const QString summary = m_gemModel->GetSummary(modelIndex);
painter->drawText(summaryRect, Qt::AlignLeft | Qt::TextWordWrap, summary);
+
+ DrawButton(painter, contentRect, modelIndex);
+ DrawPlatformIcons(painter, contentRect, modelIndex);
+
painter->restore();
}
@@ -105,7 +121,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_summaryStartX, s_height);
+ return QSize(marginsHorizontal + s_buttonWidth + s_summaryStartX, s_height);
}
bool GemItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex)
@@ -132,4 +148,85 @@ namespace O3DE::ProjectManager
font.setPixelSize(fontSize);
return QFontMetrics(font).boundingRect(text);
}
+
+ QRect GemItemDelegate::CalcButtonRect(const QRect& contentRect) const
+ {
+ const QPoint topLeft = QPoint(contentRect.right() - s_buttonWidth - s_itemMargins.right(), contentRect.top() + contentRect.height() / 2 - s_buttonHeight / 2);
+ const QSize size = QSize(s_buttonWidth, s_buttonHeight);
+ return QRect(topLeft, size);
+ }
+
+ void GemItemDelegate::DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const
+ {
+ const GemInfo::Platforms platforms = m_gemModel->GetPlatforms(modelIndex);
+ int startX = 0;
+
+ // Iterate and draw the platforms in the order they are defined in the enum.
+ for (int i = 0; i < GemInfo::NumPlatforms; ++i)
+ {
+ // Check if the platform is supported by the given gem.
+ const GemInfo::Platform platform = static_cast(1 << i);
+ if (platforms & platform)
+ {
+ // Get the icon for the platform and draw it.
+ const auto iterator = m_platformIcons.find(platform);
+ if (iterator != m_platformIcons.end())
+ {
+ const QPixmap& pixmap = iterator.value();
+ painter->drawPixmap(contentRect.left() + startX, contentRect.bottom() - s_platformIconSize, pixmap);
+ qreal aspectRatio = static_cast(pixmap.width()) / pixmap.height();
+ startX += s_platformIconSize * aspectRatio + s_platformIconSize / 2.5;
+ }
+ }
+ }
+ }
+
+ void GemItemDelegate::DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const
+ {
+ painter->save();
+ const QRect buttonRect = CalcButtonRect(contentRect);
+ QPoint circleCenter;
+ QString buttonText;
+
+ const bool isAdded = m_gemModel->IsAdded(modelIndex);
+ if (isAdded)
+ {
+ painter->setBrush(m_buttonEnabledColor);
+ painter->setPen(m_buttonEnabledColor);
+
+ circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius, 1);
+ buttonText = "Added";
+ }
+ else
+ {
+ circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius + 1, 1);
+ buttonText = "Get";
+ }
+
+ // Rounded rect
+ painter->drawRoundedRect(buttonRect, s_buttonBorderRadius, s_buttonBorderRadius);
+
+ // Text
+ QFont font;
+ QRect textRect = GetTextRect(font, buttonText, s_buttonFontSize);
+ if (isAdded)
+ {
+ textRect = QRect(buttonRect.left(), buttonRect.top(), buttonRect.width() - s_buttonCircleRadius * 2.0, buttonRect.height());
+ }
+ else
+ {
+ textRect = QRect(buttonRect.left() + s_buttonCircleRadius * 2.0, buttonRect.top(), buttonRect.width() - s_buttonCircleRadius * 2.0, buttonRect.height());
+ }
+
+ font.setPixelSize(s_buttonFontSize);
+ painter->setFont(font);
+ painter->setPen(m_textColor);
+ painter->drawText(textRect, Qt::AlignCenter, buttonText);
+
+ // Circle
+ painter->setBrush(m_textColor);
+ painter->drawEllipse(circleCenter, s_buttonCircleRadius, s_buttonCircleRadius);
+
+ painter->restore();
+ }
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
index 3528d07d78..ee0392e188 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
@@ -16,6 +16,7 @@
#include
#include "GemInfo.h"
#include "GemModel.h"
+#include
#endif
QT_FORWARD_DECLARE_CLASS(QEvent)
@@ -38,6 +39,9 @@ namespace O3DE::ProjectManager
private:
void CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
+ QRect CalcButtonRect(const QRect& contentRect) const;
+ void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
+ void DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
GemModel* m_gemModel = nullptr;
@@ -47,9 +51,10 @@ namespace O3DE::ProjectManager
const QColor m_backgroundColor = QColor("#333333"); // Outside of the actual gem item
const QColor m_itemBackgroundColor = QColor("#404040"); // Background color of the gem item
const QColor m_borderColor = QColor("#1E70EB");
+ const QColor m_buttonEnabledColor = QColor("#00B931");
// Item
- inline constexpr static int s_height = 140; // Gem item total height
+ inline constexpr static int s_height = 135; // Gem item total height
inline constexpr static qreal s_gemNameFontSize = 16.0;
inline constexpr static qreal s_fontSize = 15.0;
inline constexpr static int s_summaryStartX = 200;
@@ -58,5 +63,17 @@ namespace O3DE::ProjectManager
inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/20, /*top=*/10, /*right=*/20, /*bottom=*/10); // Item border distances
inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/15, /*top=*/12, /*right=*/12, /*bottom=*/12); // Distances of the elements within an item to the item borders
inline constexpr static int s_borderWidth = 4;
+
+ // Button
+ inline constexpr static int s_buttonWidth = 70;
+ inline constexpr static int s_buttonHeight = 24;
+ inline constexpr static int s_buttonBorderRadius = 12;
+ inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 3;
+ inline constexpr static qreal s_buttonFontSize = 12.0;
+
+ // Platform icons
+ void AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath);
+ inline constexpr static int s_platformIconSize = 16;
+ QHash m_platformIcons;
};
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
index 89e629cf5f..27905fd4d2 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
@@ -55,7 +55,7 @@ namespace O3DE::ProjectManager
return modelIndex.data(RoleCreator).toString();
}
- int GemModel::GetPlatforms(const QModelIndex& modelIndex) const
+ GemInfo::Platforms GemModel::GetPlatforms(const QModelIndex& modelIndex) const
{
return static_cast(modelIndex.data(RolePlatforms).toInt());
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
index 33ae02dc8a..4ce9de32fc 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
@@ -34,7 +34,7 @@ namespace O3DE::ProjectManager
QString GetName(const QModelIndex& modelIndex) const;
QString GetCreator(const QModelIndex& modelIndex) const;
- int GetPlatforms(const QModelIndex& modelIndex) const;
+ GemInfo::Platforms GetPlatforms(const QModelIndex& modelIndex) const;
QString GetSummary(const QModelIndex& modelIndex) const;
bool IsAdded(const QModelIndex& modelIndex) const;
diff --git a/Code/Tools/ProjectManager/project_manager.qrc b/Code/Tools/ProjectManager/project_manager.qrc
index 408398584b..6509a9f940 100644
--- a/Code/Tools/ProjectManager/project_manager.qrc
+++ b/Code/Tools/ProjectManager/project_manager.qrc
@@ -1,8 +1,13 @@
-
-
+
+
Resources/ProjectManager.qss
Resources/Add.svg
Resources/Select_Folder.svg
Resources/o3de_editor.ico
+ Resources/Windows.svg
+ Resources/Android.svg
+ Resources/iOS.svg
+ Resources/Linux.svg
+ Resources/macOS.svg
-
\ No newline at end of file
+