Merge branch 'main' of https://github.com/aws-lumberyard/o3de into ly-as-sdk/LYN-2948-phistere

This commit is contained in:
lumberyard-employee-dm
2021-05-25 23:48:55 -05:00
1623 changed files with 54998 additions and 47910 deletions
@@ -11,10 +11,15 @@
*/
#include <GemCatalog/GemCatalogScreen.h>
#include <PythonBindingsInterface.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <GemCatalog/GemFilterWidget.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <PythonBindingsInterface.h>
#include <QTimer>
//#define USE_TESTGEMDATA
namespace O3DE::ProjectManager
{
@@ -22,62 +27,29 @@ namespace O3DE::ProjectManager
: ScreenWidget(parent)
{
m_gemModel = new GemModel(this);
GemSortFilterProxyModel* proxyModel = new GemSortFilterProxyModel(m_gemModel, this);
QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setMargin(0);
vLayout->setSpacing(0);
setLayout(vLayout);
QHBoxLayout* hLayout = new QHBoxLayout();
hLayout->setMargin(0);
vLayout->addLayout(hLayout);
QWidget* filterPlaceholderWidget = new QWidget();
filterPlaceholderWidget->setFixedWidth(250);
hLayout->addWidget(filterPlaceholderWidget);
m_gemListView = new GemListView(m_gemModel, this);
hLayout->addWidget(m_gemListView);
QWidget* inspectorPlaceholderWidget = new QWidget();
inspectorPlaceholderWidget->setFixedWidth(250);
hLayout->addWidget(inspectorPlaceholderWidget);
m_gemListView = new GemListView(proxyModel, proxyModel->GetSelectionModel(), this);
m_gemInspector = new GemInspector(m_gemModel, this);
m_gemInspector->setFixedWidth(320);
// Start: Temporary gem test data
#ifdef USE_TESTGEMDATA
QVector<GemInfo> testGemData = GenerateTestData();
for (const GemInfo& gemInfo : testGemData)
{
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::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::macOS,
true));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("PhysX",
"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::macOS,
false));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Certificate Manager",
"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 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.",
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
false));
m_gemModel->AddGem(gemInfo);
}
#else
// End: Temporary gem test data
auto result = PythonBindingsInterface::Get()->GetGems();
if (result.IsSuccess())
@@ -87,15 +59,115 @@ namespace O3DE::ProjectManager
m_gemModel->AddGem(gemInfo);
}
}
#endif
GemFilterWidget* filterWidget = new GemFilterWidget(proxyModel);
filterWidget->setFixedWidth(250);
QVBoxLayout* middleVLayout = new QVBoxLayout();
middleVLayout->setMargin(0);
middleVLayout->setSpacing(0);
middleVLayout->addWidget(m_gemListView);
hLayout->addWidget(filterWidget);
hLayout->addLayout(middleVLayout);
hLayout->addWidget(m_gemInspector);
proxyModel->InvalidateFilter();
}
QVector<GemInfo> GemCatalogScreen::GenerateTestData()
{
QVector<GemInfo> result;
GemInfo gem("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::macOS | GemInfo::Windows | GemInfo::Linux),
true);
gem.m_directoryLink = "C:/";
gem.m_documentationLink = "http://www.amazon.com";
gem.m_dependingGemUuids = QStringList({"EMotionFX", "Atom"});
gem.m_conflictingGemUuids = QStringList({"Vegetation", "Camera", "ScriptCanvas", "CloudCanvas", "Networking"});
gem.m_types = (GemInfo::Code | GemInfo::Asset);
gem.m_version = "v1.01";
gem.m_lastUpdatedDate = "24th April 2021";
gem.m_binarySizeInKB = 40;
gem.m_features = QStringList({"Animation", "Assets", "Physics"});
gem.m_gemOrigin = GemInfo::O3DEFoundation;
result.push_back(gem);
gem.m_name = "Atom";
gem.m_creator = "O3DE Seattle";
gem.m_summary = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
gem.m_platforms = (GemInfo::Android | GemInfo::Windows | GemInfo::Linux | GemInfo::macOS);
gem.m_isAdded = true;
gem.m_directoryLink = "C:/";
gem.m_documentationLink = "https://aws.amazon.com/gametech/";
gem.m_dependingGemUuids = QStringList({"EMotionFX", "Core", "AudioSystem", "Camera", "Particles"});
gem.m_conflictingGemUuids = QStringList({"CloudCanvas", "NovaNet"});
gem.m_version = "v2.31";
gem.m_lastUpdatedDate = "24th November 2020";
gem.m_features = QStringList({"Assets", "Rendering", "UI", "VR", "Debug", "Environment"});
gem.m_binarySizeInKB = 2087;
result.push_back(gem);
gem.m_name = "Physics";
gem.m_creator = "O3DE London";
gem.m_summary = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
gem.m_platforms = (GemInfo::Android | GemInfo::Linux | GemInfo::macOS);
gem.m_isAdded = true;
gem.m_directoryLink = "C:/";
gem.m_documentationLink = "https://aws.amazon.com/gametech/";
gem.m_dependingGemUuids = QStringList({"GraphCanvas", "ExpressionEvaluation", "UI Lib", "Multiplayer", "GameStateSamples"});
gem.m_conflictingGemUuids = QStringList({"Cloud Canvas", "EMotion FX", "Streaming", "MessagePopup", "Cloth", "Graph Canvas", "Twitch Integration"});
gem.m_version = "v1.5.102145";
gem.m_lastUpdatedDate = "1st January 2021";
gem.m_binarySizeInKB = 2000000;
gem.m_features = QStringList({"Physics", "Gameplay", "Debug", "Assets"});
result.push_back(gem);
result.push_back(O3DE::ProjectManager::GemInfo("Certificate Manager",
"O3DE Irvine",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
GemInfo::Windows,
false));
result.push_back(O3DE::ProjectManager::GemInfo("Cloud Gem Framework",
"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));
result.push_back(O3DE::ProjectManager::GemInfo("Cloud Gem Core",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
true));
result.push_back(O3DE::ProjectManager::GemInfo("Gestures",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
false));
result.push_back(O3DE::ProjectManager::GemInfo("Effects System",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
true));
result.push_back(O3DE::ProjectManager::GemInfo("Microphone",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus euismod ligula vitae dui dictum, a sodales dolor luctus. Sed id elit dapibus, finibus neque sed, efficitur mi. Nam facilisis ligula at eleifend pellentesque. Praesent non ex consectetur, blandit tellus in, venenatis lacus. Duis nec neque in urna ullamcorper euismod id eu leo. Nam efficitur dolor sed odio vehicula venenatis. Suspendisse nec est non velit commodo cursus in sit amet dui. Ut bibendum nisl et libero hendrerit dapibus. Vestibulum ultrices ullamcorper urna, placerat porttitor est lobortis in. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer a magna ac tellus sollicitudin porttitor. Phasellus lobortis viverra justo id bibendum. Etiam ac pharetra risus. Nulla vitae justo nibh. Nulla viverra leo et molestie interdum. Duis sit amet bibendum nulla, sit amet vehicula augue.",
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
false));
return result;
}
ProjectManagerScreen GemCatalogScreen::GetScreenEnum()
{
return ProjectManagerScreen::GemCatalog;
}
QString GemCatalogScreen::GetNextButtonText()
{
return "Create Project";
}
} // namespace O3DE::ProjectManager
@@ -9,11 +9,13 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <ScreenWidget.h>
#include <GemCatalog/GemListView.h>
#include <GemCatalog/GemInspector.h>
#include <GemCatalog/GemModel.h>
#endif
@@ -26,10 +28,12 @@ namespace O3DE::ProjectManager
explicit GemCatalogScreen(QWidget* parent = nullptr);
~GemCatalogScreen() = default;
ProjectManagerScreen GetScreenEnum() override;
QString GetNextButtonText() override;
private:
QVector<GemInfo> GenerateTestData();
GemListView* m_gemListView = nullptr;
GemInspector* m_gemInspector = nullptr;
GemModel* m_gemModel = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -0,0 +1,412 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <GemCatalog/GemFilterWidget.h>
#include <QButtonGroup>
#include <QCheckBox>
#include <QLabel>
#include <QMap>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
namespace O3DE::ProjectManager
{
FilterCategoryWidget::FilterCategoryWidget(const QString& header,
const QVector<QString>& elementNames,
const QVector<int>& elementCounts,
bool showAllLessButton,
int defaultShowCount,
QWidget* parent)
: QWidget(parent)
, m_defaultShowCount(defaultShowCount)
{
AZ_Assert(elementNames.size() == elementCounts.size(), "Number of element names needs to match the counts.");
QVBoxLayout* vLayout = new QVBoxLayout();
setLayout(vLayout);
// Collapse button
QHBoxLayout* collapseLayout = new QHBoxLayout();
m_collapseButton = new QPushButton();
m_collapseButton->setCheckable(true);
m_collapseButton->setFlat(true);
m_collapseButton->setFocusPolicy(Qt::NoFocus);
m_collapseButton->setFixedWidth(s_collapseButtonSize);
m_collapseButton->setStyleSheet("border: 0px; border-radius: 0px;");
connect(m_collapseButton, &QPushButton::clicked, this, [=]()
{
UpdateCollapseState();
});
collapseLayout->addWidget(m_collapseButton);
// Category title
QLabel* headerLabel = new QLabel(header);
headerLabel->setStyleSheet("font-size: 11pt;");
collapseLayout->addWidget(headerLabel);
vLayout->addLayout(collapseLayout);
vLayout->addSpacing(5);
// Everything in the main widget will be collapsed/uncollapsed
{
m_mainWidget = new QWidget();
vLayout->addWidget(m_mainWidget);
QVBoxLayout* mainLayout = new QVBoxLayout();
mainLayout->setMargin(0);
mainLayout->setAlignment(Qt::AlignTop);
m_mainWidget->setLayout(mainLayout);
// Elements
m_buttonGroup = new QButtonGroup();
m_buttonGroup->setExclusive(false);
for (int i = 0; i < elementNames.size(); ++i)
{
QWidget* elementWidget = new QWidget();
QHBoxLayout* elementLayout = new QHBoxLayout();
elementLayout->setMargin(0);
elementWidget->setLayout(elementLayout);
QCheckBox* checkbox = new QCheckBox(elementNames[i]);
checkbox->setStyleSheet("font-size: 11pt;");
m_buttonGroup->addButton(checkbox);
elementLayout->addWidget(checkbox);
elementLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
QLabel* countLabel = new QLabel(QString::number(elementCounts[i]));
countLabel->setStyleSheet("font-size: 11pt; background-color: #333333; border-radius: 3px; color: #94D2FF;");
elementLayout->addWidget(countLabel);
m_elementWidgets.push_back(elementWidget);
mainLayout->addWidget(elementWidget);
}
// See more / less
if (showAllLessButton)
{
m_seeAllLessLabel = new LinkLabel();
connect(m_seeAllLessLabel, &LinkLabel::clicked, this, [=]()
{
m_seeAll = !m_seeAll;
UpdateSeeMoreLess();
});
mainLayout->addWidget(m_seeAllLessLabel);
}
else
{
mainLayout->addSpacing(5);
}
}
// Separating line
QFrame* hLine = new QFrame();
hLine->setFrameShape(QFrame::HLine);
hLine->setStyleSheet("color: #666666;");
vLayout->addWidget(hLine);
UpdateCollapseState();
UpdateSeeMoreLess();
}
void FilterCategoryWidget::UpdateCollapseState()
{
if (m_collapseButton->isChecked())
{
m_collapseButton->setIcon(QIcon(":/Resources/ArrowDownLine.svg"));
m_mainWidget->hide();
}
else
{
m_collapseButton->setIcon(QIcon(":/Resources/ArrowUpLine.svg"));
m_mainWidget->show();
}
}
void FilterCategoryWidget::UpdateSeeMoreLess()
{
if (!m_seeAllLessLabel)
{
return;
}
if (m_elementWidgets.isEmpty())
{
m_seeAllLessLabel->hide();
return;
}
else
{
m_seeAllLessLabel->show();
}
if (!m_seeAll)
{
m_seeAllLessLabel->setText("See all");
}
else
{
m_seeAllLessLabel->setText("See less");
}
int showCount = m_seeAll ? m_elementWidgets.size() : m_defaultShowCount;
showCount = AZ::GetMin(showCount, m_elementWidgets.size());
for (int i = 0; i < showCount; ++i)
{
m_elementWidgets[i]->show();
}
for (int i = showCount; i < m_elementWidgets.size(); ++i)
{
m_elementWidgets[i]->hide();
}
}
QButtonGroup* FilterCategoryWidget::GetButtonGroup()
{
return m_buttonGroup;
}
GemFilterWidget::GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent)
: QScrollArea(parent)
, m_filterProxyModel(filterProxyModel)
{
m_gemModel = m_filterProxyModel->GetSourceModel();
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
QWidget* mainWidget = new QWidget();
setWidget(mainWidget);
m_mainLayout = new QVBoxLayout();
m_mainLayout->setAlignment(Qt::AlignTop);
mainWidget->setLayout(m_mainLayout);
QLabel* filterByLabel = new QLabel("Filter by");
filterByLabel->setStyleSheet("font-size: 15pt;");
m_mainLayout->addWidget(filterByLabel);
AddGemOriginFilter();
AddTypeFilter();
AddPlatformFilter();
AddFeatureFilter();
}
void GemFilterWidget::AddGemOriginFilter()
{
QVector<QString> elementNames;
QVector<int> elementCounts;
const int numGems = m_gemModel->rowCount();
for (int originIndex = 0; originIndex < GemInfo::NumGemOrigins; ++originIndex)
{
const GemInfo::GemOrigin gemOriginToBeCounted = static_cast<GemInfo::GemOrigin>(1 << originIndex);
int gemOriginCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
const GemInfo::GemOrigin gemOrigin = m_gemModel->GetGemOrigin(m_gemModel->index(gemIndex, 0));
// Is the gem of the given origin?
if (gemOriginToBeCounted == gemOrigin)
{
gemOriginCount++;
}
}
elementNames.push_back(GemInfo::GetGemOriginString(gemOriginToBeCounted));
elementCounts.push_back(gemOriginCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Provider", elementNames, elementCounts, /*showAllLessButton=*/false);
m_mainLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::GemOrigin gemOrigin = static_cast<GemInfo::GemOrigin>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::GemOrigins gemOrigins = m_filterProxyModel->GetGemOrigins();
if (checked)
{
gemOrigins |= gemOrigin;
}
else
{
gemOrigins &= ~gemOrigin;
}
m_filterProxyModel->SetGemOrigins(gemOrigins);
});
}
}
void GemFilterWidget::AddTypeFilter()
{
QVector<QString> elementNames;
QVector<int> elementCounts;
const int numGems = m_gemModel->rowCount();
for (int typeIndex = 0; typeIndex < GemInfo::NumTypes; ++typeIndex)
{
const GemInfo::Type type = static_cast<GemInfo::Type>(1 << typeIndex);
int typeGemCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
const GemInfo::Types types = m_gemModel->GetTypes(m_gemModel->index(gemIndex, 0));
// Is type (Asset, Code, Tool) part of the gem?
if (types & type)
{
typeGemCount++;
}
}
elementNames.push_back(GemInfo::GetTypeString(type));
elementCounts.push_back(typeGemCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Type", elementNames, elementCounts, /*showAllLessButton=*/false);
m_mainLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::Type type = static_cast<GemInfo::Type>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::Types types = m_filterProxyModel->GetTypes();
if (checked)
{
types |= type;
}
else
{
types &= ~type;
}
m_filterProxyModel->SetTypes(types);
});
}
}
void GemFilterWidget::AddPlatformFilter()
{
QVector<QString> elementNames;
QVector<int> elementCounts;
const int numGems = m_gemModel->rowCount();
for (int platformIndex = 0; platformIndex < GemInfo::NumPlatforms; ++platformIndex)
{
const GemInfo::Platform platform = static_cast<GemInfo::Platform>(1 << platformIndex);
int platformGemCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
const GemInfo::Platforms platforms = m_gemModel->GetPlatforms(m_gemModel->index(gemIndex, 0));
// Is platform supported?
if (platforms & platform)
{
platformGemCount++;
}
}
elementNames.push_back(GemInfo::GetPlatformString(platform));
elementCounts.push_back(platformGemCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Supported Platforms", elementNames, elementCounts, /*showAllLessButton=*/false);
m_mainLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::Platform platform = static_cast<GemInfo::Platform>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::Platforms platforms = m_filterProxyModel->GetPlatforms();
if (checked)
{
platforms |= platform;
}
else
{
platforms &= ~platform;
}
m_filterProxyModel->SetPlatforms(platforms);
});
}
}
void GemFilterWidget::AddFeatureFilter()
{
// Alphabetically sorted, unique features and their number of occurrences in the gem database.
QMap<QString, int> uniqueFeatureCounts;
const int numGems = m_gemModel->rowCount();
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
const QStringList features = m_gemModel->GetFeatures(m_gemModel->index(gemIndex, 0));
for (const QString& feature : features)
{
if (!uniqueFeatureCounts.contains(feature))
{
uniqueFeatureCounts.insert(feature, 1);
}
else
{
int& featureeCount = uniqueFeatureCounts[feature];
featureeCount++;
}
}
}
QVector<QString> elementNames;
QVector<int> elementCounts;
for (auto iterator = uniqueFeatureCounts.begin(); iterator != uniqueFeatureCounts.end(); iterator++)
{
elementNames.push_back(iterator.key());
elementCounts.push_back(iterator.value());
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Features", elementNames, elementCounts,
/*showAllLessButton=*/true, /*defaultShowCount=*/5);
m_mainLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const QString& feature = elementNames[i];
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
QSet<QString> features = m_filterProxyModel->GetFeatures();
if (checked)
{
features.insert(feature);
}
else
{
features.remove(feature);
}
m_filterProxyModel->SetFeatures(features);
});
}
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,79 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <LinkWidget.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
#include <QCheckBox>
#include <QVector>
#include <QPushButton>
#endif
QT_FORWARD_DECLARE_CLASS(QButtonGroup)
namespace O3DE::ProjectManager
{
class FilterCategoryWidget
: public QWidget
{
Q_OBJECT // AUTOMOC
public:
explicit FilterCategoryWidget(const QString& header,
const QVector<QString>& elementNames,
const QVector<int>& elementCounts,
bool showAllLessButton = true,
int defaultShowCount = 4,
QWidget* parent = nullptr);
QButtonGroup* GetButtonGroup();
private:
void UpdateCollapseState();
void UpdateSeeMoreLess();
inline constexpr static int s_collapseButtonSize = 16;
QPushButton* m_collapseButton = nullptr;
QWidget* m_mainWidget = nullptr;
QButtonGroup* m_buttonGroup = nullptr;
QVector<QWidget*> m_elementWidgets; //! Includes checkbox and the count labl.
LinkLabel* m_seeAllLessLabel = nullptr;
int m_defaultShowCount = 0;
bool m_seeAll = false;
};
class GemFilterWidget
: public QScrollArea
{
Q_OBJECT // AUTOMOC
public:
explicit GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent = nullptr);
~GemFilterWidget() = default;
private:
void AddGemOriginFilter();
void AddTypeFilter();
void AddPlatformFilter();
void AddFeatureFilter();
QVBoxLayout* m_mainLayout = nullptr;
GemModel* m_gemModel = nullptr;
GemSortFilterProxyModel* m_filterProxyModel = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -22,10 +22,61 @@ namespace O3DE::ProjectManager
, m_isAdded(isAdded)
{
}
bool GemInfo::IsValid() const
{
return !m_path.isEmpty();
}
QString GemInfo::GetPlatformString(Platform platform)
{
switch (platform)
{
case Android:
return "Android";
case iOS:
return "iOS";
case Linux:
return "Linux";
case macOS:
return "macOS";
case Windows:
return "Windows";
default:
return "<Unknown Platform>";
}
}
QString GemInfo::GetTypeString(Type type)
{
switch (type)
{
case Asset:
return "Asset";
case Code:
return "Code";
case Tool:
return "Tool";
default:
return "<Unknown Type>";
}
}
QString GemInfo::GetGemOriginString(GemOrigin origin)
{
switch (origin)
{
case O3DEFoundation:
return "Open 3D Foundation";
case Local:
return "Local";
default:
return "<Unknown Gem Origin>";
}
}
bool GemInfo::IsPlatformSupported(Platform platform) const
{
return (m_platforms & platform);
}
} // namespace O3DE::ProjectManager
@@ -34,9 +34,30 @@ namespace O3DE::ProjectManager
NumPlatforms = 5
};
Q_DECLARE_FLAGS(Platforms, Platform)
static QString GetPlatformString(Platform platform);
enum Type
{
Asset = 1 << 0,
Code = 1 << 1,
Tool = 1 << 2,
NumTypes = 3
};
Q_DECLARE_FLAGS(Types, Type)
static QString GetTypeString(Type type);
enum GemOrigin
{
O3DEFoundation = 1 << 0,
Local = 1 << 1,
NumGemOrigins = 2
};
Q_DECLARE_FLAGS(GemOrigins, GemOrigin)
static QString GetGemOriginString(GemOrigin origin);
GemInfo() = default;
GemInfo(const QString& name, const QString& creator, const QString& summary, Platforms platforms, bool isAdded);
bool IsPlatformSupported(Platform platform) const;
bool IsValid() const;
@@ -44,16 +65,22 @@ namespace O3DE::ProjectManager
QString m_name;
QString m_displayName;
QString m_creator;
GemOrigin m_gemOrigin = Local;
bool m_isAdded = false; //! Is the gem currently added and enabled in the project?
QString m_summary;
Platforms m_platforms;
Types m_types; //! Asset and/or Code and/or Tool
QStringList m_features;
QString m_directoryLink;
QString m_documentationLink;
QString m_version;
QString m_lastUpdatedDate;
QString m_documentationUrl;
QVector<AZ::Uuid> m_dependingGemUuids;
QVector<AZ::Uuid> m_conflictingGemUuids;
int m_binarySizeInKB = 0;
QStringList m_dependingGemUuids;
QStringList m_conflictingGemUuids;
};
} // namespace O3DE::ProjectManager
Q_DECLARE_OPERATORS_FOR_FLAGS(O3DE::ProjectManager::GemInfo::Platforms)
Q_DECLARE_OPERATORS_FOR_FLAGS(O3DE::ProjectManager::GemInfo::Types)
Q_DECLARE_OPERATORS_FOR_FLAGS(O3DE::ProjectManager::GemInfo::GemOrigins)
@@ -0,0 +1,176 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <GemCatalog/GemInspector.h>
#include <GemCatalog/GemItemDelegate.h>
#include <QFrame>
#include <QLabel>
#include <QSpacerItem>
#include <QVBoxLayout>
namespace O3DE::ProjectManager
{
GemInspector::GemInspector(GemModel* model, QWidget* parent)
: QScrollArea(parent)
, m_model(model)
{
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_mainWidget = new QWidget();
setWidget(m_mainWidget);
m_mainLayout = new QVBoxLayout();
m_mainLayout->setMargin(15);
m_mainLayout->setAlignment(Qt::AlignTop);
m_mainWidget->setLayout(m_mainLayout);
InitMainWidget();
connect(m_model->GetSelectionModel(), &QItemSelectionModel::selectionChanged, this, &GemInspector::OnSelectionChanged);
Update({});
}
void GemInspector::OnSelectionChanged(const QItemSelection& selected, [[maybe_unused]] const QItemSelection& deselected)
{
const QModelIndexList selectedIndices = selected.indexes();
if (selectedIndices.empty())
{
Update({});
return;
}
Update(selectedIndices[0]);
}
void GemInspector::Update(const QModelIndex& modelIndex)
{
if (!modelIndex.isValid())
{
m_mainWidget->hide();
}
m_nameLabel->setText(m_model->GetName(modelIndex));
m_creatorLabel->setText(m_model->GetCreator(modelIndex));
m_summaryLabel->setText(m_model->GetSummary(modelIndex));
m_summaryLabel->adjustSize();
m_directoryLinkLabel->SetUrl(m_model->GetDirectoryLink(modelIndex));
m_documentationLinkLabel->SetUrl(m_model->GetDocLink(modelIndex));
// Depending and conflicting gems
m_dependingGems->Update("Depending Gems", "The following Gems will be automatically enabled with this Gem.", m_model->GetDependingGemNames(modelIndex));
m_conflictingGems->Update("Conflicting Gems", "The following Gems will be automatically disabled with this Gem.", m_model->GetConflictingGemNames(modelIndex));
// Additional information
m_versionLabel->setText(QString("Gem Version: %1").arg(m_model->GetVersion(modelIndex)));
m_lastUpdatedLabel->setText(QString("Last Updated: %1").arg(m_model->GetLastUpdated(modelIndex)));
m_binarySizeLabel->setText(QString("Binary Size: %1 KB").arg(QString::number(m_model->GetBinarySizeInKB(modelIndex))));
m_mainWidget->adjustSize();
m_mainWidget->show();
}
QLabel* GemInspector::CreateStyledLabel(QLayout* layout, int fontSize, const QString& colorCodeString)
{
QLabel* result = new QLabel();
result->setStyleSheet(QString("font-size: %1pt; color: %2;").arg(QString::number(fontSize), colorCodeString));
layout->addWidget(result);
return result;
}
void GemInspector::InitMainWidget()
{
// Gem name, creator and summary
m_nameLabel = CreateStyledLabel(m_mainLayout, 17, s_headerColor);
m_creatorLabel = CreateStyledLabel(m_mainLayout, 12, s_creatorColor);
m_mainLayout->addSpacing(5);
// TODO: QLabel seems to have issues determining the right sizeHint() for our font with the given font size.
// This results into squeezed elements in the layout in case the text is a little longer than a sentence.
m_summaryLabel = new QLabel();//CreateLabel(m_mainLayout, 12, s_textColor);
m_mainLayout->addWidget(m_summaryLabel);
m_summaryLabel->setWordWrap(true);
m_mainLayout->addSpacing(5);
// Directory and documentation links
{
QHBoxLayout* linksHLayout = new QHBoxLayout();
linksHLayout->setMargin(0);
m_mainLayout->addLayout(linksHLayout);
QSpacerItem* spacerLeft = new QSpacerItem(0, 0, QSizePolicy::Expanding);
linksHLayout->addSpacerItem(spacerLeft);
m_directoryLinkLabel = new LinkLabel("View in Directory");
linksHLayout->addWidget(m_directoryLinkLabel);
linksHLayout->addWidget(new QLabel("|"));
m_documentationLinkLabel = new LinkLabel("Read Documentation");
linksHLayout->addWidget(m_documentationLinkLabel);
QSpacerItem* spacerRight = new QSpacerItem(0, 0, QSizePolicy::Expanding);
linksHLayout->addSpacerItem(spacerRight);
m_mainLayout->addSpacing(8);
}
// Separating line
QFrame* hLine = new QFrame();
hLine->setFrameShape(QFrame::HLine);
hLine->setStyleSheet("color: #666666;");
m_mainLayout->addWidget(hLine);
m_mainLayout->addSpacing(10);
// Depending and conflicting gems
m_dependingGems = new GemsSubWidget();
m_mainLayout->addWidget(m_dependingGems);
m_mainLayout->addSpacing(20);
m_conflictingGems = new GemsSubWidget();
m_mainLayout->addWidget(m_conflictingGems);
m_mainLayout->addSpacing(20);
// Additional information
QLabel* additionalInfoLabel = CreateStyledLabel(m_mainLayout, 14, s_headerColor);
additionalInfoLabel->setText("Additional Information");
m_versionLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
m_lastUpdatedLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
m_binarySizeLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
}
GemInspector::GemsSubWidget::GemsSubWidget(QWidget* parent)
: QWidget(parent)
{
m_layout = new QVBoxLayout();
m_layout->setAlignment(Qt::AlignTop);
m_layout->setMargin(0);
setLayout(m_layout);
m_titleLabel = GemInspector::CreateStyledLabel(m_layout, 15, s_headerColor);
m_textLabel = GemInspector::CreateStyledLabel(m_layout, 9, s_textColor);
m_textLabel->setWordWrap(true);
m_tagWidget = new TagContainerWidget();
m_layout->addWidget(m_tagWidget);
}
void GemInspector::GemsSubWidget::Update(const QString& title, const QString& text, const QStringList& gemNames)
{
m_titleLabel->setText(title);
m_textLabel->setText(text);
m_tagWidget->Update(gemNames);
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,88 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <LinkWidget.h>
#include <TagWidget.h>
#include <GemCatalog/GemInfo.h>
#include <GemCatalog/GemModel.h>
#include <QItemSelection>
#include <QScrollArea>
#include <QWidget>
#endif
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
QT_FORWARD_DECLARE_CLASS(QLabel)
namespace O3DE::ProjectManager
{
class GemInspector
: public QScrollArea
{
Q_OBJECT // AUTOMOC
public:
explicit GemInspector(GemModel* model, QWidget* parent = nullptr);
~GemInspector() = default;
void Update(const QModelIndex& modelIndex);
static QLabel* CreateStyledLabel(QLayout* layout, int fontSize, const QString& colorCodeString);
// Colors
inline constexpr static const char* s_headerColor = "#FFFFFF";
inline constexpr static const char* s_textColor = "#DDDDDD";
inline constexpr static const char* s_creatorColor = "#94D2FF";
private slots:
void OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
private:
// Title, description and tag widget container used for the depending and conflicting gems
class GemsSubWidget
: public QWidget
{
public:
GemsSubWidget(QWidget* parent = nullptr);
void Update(const QString& title, const QString& text, const QStringList& gemNames);
private:
QLabel* m_titleLabel = nullptr;
QLabel* m_textLabel = nullptr;
QVBoxLayout* m_layout = nullptr;
TagContainerWidget* m_tagWidget = nullptr;
};
void InitMainWidget();
GemModel* m_model = nullptr;
QWidget* m_mainWidget = nullptr;
QVBoxLayout* m_mainLayout = nullptr;
// General info (top) section
QLabel* m_nameLabel = nullptr;
QLabel* m_creatorLabel = nullptr;
QLabel* m_summaryLabel = nullptr;
LinkLabel* m_directoryLinkLabel = nullptr;
LinkLabel* m_documentationLinkLabel = nullptr;
// Depending and conflicting gems
GemsSubWidget* m_dependingGems = nullptr;
GemsSubWidget* m_conflictingGems = nullptr;
// Additional information
QLabel* m_versionLabel = nullptr;
QLabel* m_lastUpdatedLabel = nullptr;
QLabel* m_binarySizeLabel = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -10,7 +10,7 @@
*
*/
#include "GemItemDelegate.h"
#include <GemCatalog/GemItemDelegate.h>
#include "GemModel.h"
#include <QEvent>
#include <QPainter>
@@ -18,15 +18,15 @@
namespace O3DE::ProjectManager
{
GemItemDelegate::GemItemDelegate(GemModel* gemModel, QObject* parent)
GemItemDelegate::GemItemDelegate(QAbstractItemModel* model, QObject* parent)
: QStyledItemDelegate(parent)
, m_gemModel(gemModel)
, m_model(model)
{
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");
AddPlatformIcon(GemInfo::Android, ":/Android.svg");
AddPlatformIcon(GemInfo::iOS, ":/iOS.svg");
AddPlatformIcon(GemInfo::Linux, ":/Linux.svg");
AddPlatformIcon(GemInfo::macOS, ":/macOS.svg");
AddPlatformIcon(GemInfo::Windows, ":/Windows.svg");
}
void GemItemDelegate::AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath)
@@ -78,7 +78,7 @@ namespace O3DE::ProjectManager
}
// Gem name
const QString gemName = m_gemModel->GetName(modelIndex);
const QString gemName = GemModel::GetName(modelIndex);
QFont gemNameFont(options.font);
gemNameFont.setPixelSize(s_gemNameFontSize);
gemNameFont.setBold(true);
@@ -90,7 +90,7 @@ namespace O3DE::ProjectManager
painter->drawText(gemNameRect, Qt::TextSingleLine, gemName);
// Gem creator
const QString gemCreator = m_gemModel->GetCreator(modelIndex);
const QString gemCreator = GemModel::GetCreator(modelIndex);
QRect gemCreatorRect = GetTextRect(standardFont, gemCreator, s_fontSize);
gemCreatorRect.moveTo(contentRect.left(), contentRect.top() + gemNameRect.height());
@@ -105,7 +105,7 @@ namespace O3DE::ProjectManager
painter->setFont(standardFont);
painter->setPen(m_textColor);
const QString summary = m_gemModel->GetSummary(modelIndex);
const QString summary = GemModel::GetSummary(modelIndex);
painter->drawText(summaryRect, Qt::AlignLeft | Qt::TextWordWrap, summary);
@@ -158,7 +158,7 @@ namespace O3DE::ProjectManager
void GemItemDelegate::DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const
{
const GemInfo::Platforms platforms = m_gemModel->GetPlatforms(modelIndex);
const GemInfo::Platforms platforms = GemModel::GetPlatforms(modelIndex);
int startX = 0;
// Iterate and draw the platforms in the order they are defined in the enum.
@@ -188,7 +188,7 @@ namespace O3DE::ProjectManager
QPoint circleCenter;
QString buttonText;
const bool isAdded = m_gemModel->IsAdded(modelIndex);
const bool isAdded = GemModel::IsAdded(modelIndex);
if (isAdded)
{
painter->setBrush(m_buttonEnabledColor);
@@ -15,7 +15,7 @@
#if !defined(Q_MOC_RUN)
#include <QStyledItemDelegate>
#include "GemInfo.h"
#include "GemModel.h"
#include <QAbstractItemModel>
#include <QHash>
#endif
@@ -29,22 +29,13 @@ namespace O3DE::ProjectManager
Q_OBJECT // AUTOMOC
public:
explicit GemItemDelegate(GemModel* gemModel, QObject* parent = nullptr);
explicit GemItemDelegate(QAbstractItemModel* model, QObject* parent = nullptr);
~GemItemDelegate() = default;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) override;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
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;
// Colors
const QColor m_textColor = QColor("#FFFFFF");
const QColor m_linkColor = QColor("#94D2FF");
@@ -71,6 +62,15 @@ namespace O3DE::ProjectManager
inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 3;
inline constexpr static qreal s_buttonFontSize = 12.0;
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;
QAbstractItemModel* m_model = nullptr;
// Platform icons
void AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath);
inline constexpr static int s_platformIconSize = 16;
@@ -18,17 +18,15 @@
namespace O3DE::ProjectManager
{
GemListView::GemListView(GemModel* model, QWidget *parent) :
QListView(parent)
GemListView::GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent)
: QListView(parent)
{
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QPalette palette;
palette.setColor(QPalette::Window, QColor("#333333"));
setPalette(palette);
setStyleSheet("background-color: #333333;");
setModel(model);
setSelectionModel(model->GetSelectionModel());
setSelectionModel(selectionModel);
setItemDelegate(new GemItemDelegate(model, this));
}
} // namespace O3DE::ProjectManager
@@ -14,7 +14,8 @@
#if !defined(Q_MOC_RUN)
#include "GemInfo.h"
#include "GemModel.h"
#include <QAbstractItemModel>
#include <QItemSelectionModel>
#include <QListView>
#endif
@@ -24,8 +25,9 @@ namespace O3DE::ProjectManager
: public QListView
{
Q_OBJECT // AUTOMOC
public:
explicit GemListView(GemModel* model, QWidget *parent = nullptr);
explicit GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent = nullptr);
~GemListView() = default;
};
} // namespace O3DE::ProjectManager
@@ -10,7 +10,8 @@
*
*/
#include "GemModel.h"
#include <AzCore/std/string/string.h>
#include <GemCatalog/GemModel.h>
namespace O3DE::ProjectManager
{
@@ -32,12 +33,27 @@ namespace O3DE::ProjectManager
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
item->setData(gemInfo.m_name, RoleName);
const QString uuidString = gemInfo.m_uuid.ToString<AZStd::string>().c_str();
item->setData(uuidString, RoleUuid);
item->setData(gemInfo.m_creator, RoleCreator);
item->setData(static_cast<int>(gemInfo.m_platforms), RolePlatforms);
item->setData(gemInfo.m_gemOrigin, RoleGemOrigin);
item->setData(aznumeric_cast<int>(gemInfo.m_platforms), RolePlatforms);
item->setData(aznumeric_cast<int>(gemInfo.m_types), RoleTypes);
item->setData(gemInfo.m_summary, RoleSummary);
item->setData(gemInfo.m_isAdded, RoleIsAdded);
item->setData(gemInfo.m_directoryLink, RoleDirectoryLink);
item->setData(gemInfo.m_documentationLink, RoleDocLink);
item->setData(gemInfo.m_dependingGemUuids, RoleDependingGems);
item->setData(gemInfo.m_conflictingGemUuids, RoleConflictingGems);
item->setData(gemInfo.m_version, RoleVersion);
item->setData(gemInfo.m_lastUpdatedDate, RoleLastUpdated);
item->setData(gemInfo.m_binarySizeInKB, RoleBinarySize);
item->setData(gemInfo.m_features, RoleFeatures);
appendRow(item);
const QModelIndex modelIndex = index(rowCount()-1, 0);
m_uuidToIndexMap[uuidString] = modelIndex;
}
void GemModel::Clear()
@@ -45,28 +61,130 @@ namespace O3DE::ProjectManager
clear();
}
QString GemModel::GetName(const QModelIndex& modelIndex) const
QString GemModel::GetName(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleName).toString();
}
QString GemModel::GetCreator(const QModelIndex& modelIndex) const
QString GemModel::GetCreator(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleCreator).toString();
}
GemInfo::Platforms GemModel::GetPlatforms(const QModelIndex& modelIndex) const
GemInfo::GemOrigin GemModel::GetGemOrigin(const QModelIndex& modelIndex)
{
return static_cast<GemInfo::GemOrigin>(modelIndex.data(RoleGemOrigin).toInt());
}
QString GemModel::GetUuidString(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleUuid).toString();
}
GemInfo::Platforms GemModel::GetPlatforms(const QModelIndex& modelIndex)
{
return static_cast<GemInfo::Platforms>(modelIndex.data(RolePlatforms).toInt());
}
QString GemModel::GetSummary(const QModelIndex& modelIndex) const
GemInfo::Types GemModel::GetTypes(const QModelIndex& modelIndex)
{
return static_cast<GemInfo::Types>(modelIndex.data(RoleTypes).toInt());
}
QString GemModel::GetSummary(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleSummary).toString();
}
bool GemModel::IsAdded(const QModelIndex& modelIndex) const
bool GemModel::IsAdded(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleIsAdded).toBool();
}
QString GemModel::GetDirectoryLink(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleDirectoryLink).toString();
}
QString GemModel::GetDocLink(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleDocLink).toString();
}
QModelIndex GemModel::FindIndexByUuidString(const QString& uuidString) const
{
const auto iterator = m_uuidToIndexMap.find(uuidString);
if (iterator != m_uuidToIndexMap.end())
{
return iterator.value();
}
return {};
}
void GemModel::FindGemNamesByUuidStrings(QStringList& inOutGemNames)
{
for (QString& dependingGemString : inOutGemNames)
{
QModelIndex modelIndex = FindIndexByUuidString(dependingGemString);
if (modelIndex.isValid())
{
dependingGemString = GetName(modelIndex);
}
}
}
QStringList GemModel::GetDependingGemUuids(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleDependingGems).toStringList();
}
QStringList GemModel::GetDependingGemNames(const QModelIndex& modelIndex)
{
QStringList result = GetDependingGemUuids(modelIndex);
if (result.isEmpty())
{
return {};
}
FindGemNamesByUuidStrings(result);
return result;
}
QStringList GemModel::GetConflictingGemUuids(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleConflictingGems).toStringList();
}
QStringList GemModel::GetConflictingGemNames(const QModelIndex& modelIndex)
{
QStringList result = GetConflictingGemUuids(modelIndex);
if (result.isEmpty())
{
return {};
}
FindGemNamesByUuidStrings(result);
return result;
}
QString GemModel::GetVersion(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleVersion).toString();
}
QString GemModel::GetLastUpdated(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleLastUpdated).toString();
}
int GemModel::GetBinarySizeInKB(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleBinarySize).toInt();
}
QStringList GemModel::GetFeatures(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleFeatures).toStringList();
}
} // namespace O3DE::ProjectManager
@@ -13,7 +13,8 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include "GemInfo.h"
#include <GemCatalog/GemInfo.h>
#include <QAbstractItemModel>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#endif
@@ -32,22 +33,50 @@ namespace O3DE::ProjectManager
void AddGem(const GemInfo& gemInfo);
void Clear();
QString GetName(const QModelIndex& modelIndex) const;
QString GetCreator(const QModelIndex& modelIndex) const;
GemInfo::Platforms GetPlatforms(const QModelIndex& modelIndex) const;
QString GetSummary(const QModelIndex& modelIndex) const;
bool IsAdded(const QModelIndex& modelIndex) const;
QModelIndex FindIndexByUuidString(const QString& uuidString) const;
void FindGemNamesByUuidStrings(QStringList& inOutGemNames);
QStringList GetDependingGemUuids(const QModelIndex& modelIndex);
QStringList GetDependingGemNames(const QModelIndex& modelIndex);
QStringList GetConflictingGemUuids(const QModelIndex& modelIndex);
QStringList GetConflictingGemNames(const QModelIndex& modelIndex);
static QString GetName(const QModelIndex& modelIndex);
static QString GetCreator(const QModelIndex& modelIndex);
static GemInfo::GemOrigin GetGemOrigin(const QModelIndex& modelIndex);
static QString GetUuidString(const QModelIndex& modelIndex);
static GemInfo::Platforms GetPlatforms(const QModelIndex& modelIndex);
static GemInfo::Types GetTypes(const QModelIndex& modelIndex);
static QString GetSummary(const QModelIndex& modelIndex);
static bool IsAdded(const QModelIndex& modelIndex);
static QString GetDirectoryLink(const QModelIndex& modelIndex);
static QString GetDocLink(const QModelIndex& modelIndex);
static QString GetVersion(const QModelIndex& modelIndex);
static QString GetLastUpdated(const QModelIndex& modelIndex);
static int GetBinarySizeInKB(const QModelIndex& modelIndex);
static QStringList GetFeatures(const QModelIndex& modelIndex);
private:
enum UserRole
{
RoleName = Qt::UserRole,
RoleUuid,
RoleCreator,
RoleGemOrigin,
RolePlatforms,
RoleSummary,
RoleIsAdded
RoleIsAdded,
RoleDirectoryLink,
RoleDocLink,
RoleDependingGems,
RoleConflictingGems,
RoleVersion,
RoleLastUpdated,
RoleBinarySize,
RoleFeatures,
RoleTypes
};
QHash<QString, QModelIndex> m_uuidToIndexMap;
QItemSelectionModel* m_selectionModel = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -0,0 +1,133 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <QItemSelectionModel>
namespace O3DE::ProjectManager
{
GemSortFilterProxyModel::GemSortFilterProxyModel(GemModel* sourceModel, QObject* parent)
: QSortFilterProxyModel(parent)
, m_sourceModel(sourceModel)
{
setSourceModel(sourceModel);
m_selectionProxyModel = new AzQtComponents::SelectionProxyModel(sourceModel->GetSelectionModel(), this, parent);
}
bool GemSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
// 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_sourceModel->GetName(sourceIndex).contains(m_searchString, Qt::CaseInsensitive))
{
return false;
}
// Gem origins
if (m_gemOriginFilter)
{
bool supportsAnyFilteredGemOrigin = false;
for (int i = 0; i < GemInfo::NumGemOrigins; ++i)
{
const GemInfo::GemOrigin filteredGemOrigin = static_cast<GemInfo::GemOrigin>(1 << i);
if (m_gemOriginFilter & filteredGemOrigin)
{
if ((GemModel::GetGemOrigin(sourceIndex) == filteredGemOrigin))
{
supportsAnyFilteredGemOrigin = true;
break;
}
}
}
if (!supportsAnyFilteredGemOrigin)
{
return false;
}
}
// Platform
if (m_platformFilter)
{
bool supportsAnyFilteredPlatform = false;
for (int i = 0; i < GemInfo::NumPlatforms; ++i)
{
const GemInfo::Platform filteredPlatform = static_cast<GemInfo::Platform>(1 << i);
if (m_platformFilter & filteredPlatform)
{
if ((GemModel::GetPlatforms(sourceIndex) & filteredPlatform))
{
supportsAnyFilteredPlatform = true;
break;
}
}
}
if (!supportsAnyFilteredPlatform)
{
return false;
}
}
// Types (Asset, Code, Tool)
if (m_typeFilter)
{
bool supportsAnyFilteredType = false;
for (int i = 0; i < GemInfo::NumTypes; ++i)
{
const GemInfo::Type filteredType = static_cast<GemInfo::Type>(1 << i);
if (m_typeFilter & filteredType)
{
if ((GemModel::GetTypes(sourceIndex) & filteredType))
{
supportsAnyFilteredType = true;
break;
}
}
}
if (!supportsAnyFilteredType)
{
return false;
}
}
// Features
if (!m_featureFilter.isEmpty())
{
bool containsFilterFeature = false;
const QStringList features = m_sourceModel->GetFeatures(sourceIndex);
for (const QString& feature : features)
{
if (m_featureFilter.contains(feature))
{
containsFilterFeature = true;
break;
}
}
if (!containsFilterFeature)
{
return false;
}
}
return true;
}
void GemSortFilterProxyModel::InvalidateFilter()
{
invalidate();
emit OnInvalidated();
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,68 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzQtComponents/Utilities/SelectionProxyModel.h>
#include <GemCatalog/GemModel.h>
#include <QtCore/QSortFilterProxyModel>
#include <QSet>
#endif
QT_FORWARD_DECLARE_CLASS(QItemSelectionModel)
namespace O3DE::ProjectManager
{
class GemSortFilterProxyModel
: public QSortFilterProxyModel
{
Q_OBJECT // AUTOMOC
public:
GemSortFilterProxyModel(GemModel* sourceModel, QObject* parent = nullptr);
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
GemModel* GetSourceModel() const { return m_sourceModel; }
AzQtComponents::SelectionProxyModel* GetSelectionModel() const { return m_selectionProxyModel; }
void SetSearchString(const QString& searchString) { m_searchString = searchString; InvalidateFilter(); }
GemInfo::GemOrigins GetGemOrigins() const { return m_gemOriginFilter; }
void SetGemOrigins(const GemInfo::GemOrigins& gemOrigins) { m_gemOriginFilter = gemOrigins; InvalidateFilter(); }
GemInfo::Platforms GetPlatforms() const { return m_platformFilter; }
void SetPlatforms(const GemInfo::Platforms& platforms) { m_platformFilter = platforms; InvalidateFilter(); }
GemInfo::Types GetTypes() const { return m_typeFilter; }
void SetTypes(const GemInfo::Types& types) { m_typeFilter = types; InvalidateFilter(); }
const QSet<QString>& GetFeatures() const { return m_featureFilter; }
void SetFeatures(const QSet<QString>& features) { m_featureFilter = features; InvalidateFilter(); }
void InvalidateFilter();
signals:
void OnInvalidated();
private:
GemModel* m_sourceModel = nullptr;
AzQtComponents::SelectionProxyModel* m_selectionProxyModel = nullptr;
QString m_searchString;
GemInfo::GemOrigins m_gemOriginFilter = {};
GemInfo::Platforms m_platformFilter = {};
GemInfo::Types m_typeFilter = {};
QSet<QString> m_featureFilter;
};
} // namespace O3DE::ProjectManager