From 08255d2eda03bb65c2fea0358e1bbb76c707b74c Mon Sep 17 00:00:00 2001 From: nggieber Date: Fri, 29 Oct 2021 13:20:11 -0700 Subject: [PATCH] Clicking tag now select gem and scrolls to it, it also resets filters if gem is filtered out, also gem filter creation was refactored Signed-off-by: nggieber --- .../Source/GemCatalog/GemCatalogScreen.cpp | 38 ++- .../Source/GemCatalog/GemCatalogScreen.h | 3 +- .../Source/GemCatalog/GemFilterWidget.cpp | 295 ++++++++---------- .../Source/GemCatalog/GemFilterWidget.h | 32 +- .../Source/GemCatalog/GemModel.cpp | 1 + .../GemCatalog/GemSortFilterProxyModel.cpp | 2 + 6 files changed, 187 insertions(+), 184 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index deea46b582..6e377a5041 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -30,7 +30,7 @@ namespace O3DE::ProjectManager : ScreenWidget(parent) { m_gemModel = new GemModel(this); - m_proxModel = new GemSortFilterProxyModel(m_gemModel, this); + m_proxyModel = new GemSortFilterProxyModel(m_gemModel, this); QVBoxLayout* vLayout = new QVBoxLayout(); vLayout->setMargin(0); @@ -39,7 +39,7 @@ namespace O3DE::ProjectManager m_downloadController = new DownloadController(); - m_headerWidget = new GemCatalogHeaderWidget(m_gemModel, m_proxModel, m_downloadController); + m_headerWidget = new GemCatalogHeaderWidget(m_gemModel, m_proxyModel, m_downloadController); vLayout->addWidget(m_headerWidget); connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged); @@ -50,11 +50,11 @@ namespace O3DE::ProjectManager hLayout->setMargin(0); vLayout->addLayout(hLayout); - m_gemListView = new GemListView(m_proxModel, m_proxModel->GetSelectionModel(), this); + m_gemListView = new GemListView(m_proxyModel, m_proxyModel->GetSelectionModel(), this); m_gemInspector = new GemInspector(m_gemModel, this); m_gemInspector->setFixedWidth(240); - connect(m_gemInspector, &GemInspector::TagClicked, m_headerWidget, &GemCatalogHeaderWidget::SetSearchFilter); + connect(m_gemInspector, &GemInspector::TagClicked, this, &GemCatalogScreen::SelectGem); QWidget* filterWidget = new QWidget(this); filterWidget->setFixedWidth(240); @@ -63,7 +63,7 @@ namespace O3DE::ProjectManager m_filterWidgetLayout->setSpacing(0); filterWidget->setLayout(m_filterWidgetLayout); - GemListHeaderWidget* listHeaderWidget = new GemListHeaderWidget(m_proxModel); + GemListHeaderWidget* listHeaderWidget = new GemListHeaderWidget(m_proxyModel); QVBoxLayout* middleVLayout = new QVBoxLayout(); middleVLayout->setMargin(0); @@ -86,15 +86,17 @@ namespace O3DE::ProjectManager m_gemsToRegisterWithProject.clear(); FillModel(projectPath); + m_proxyModel->ResetFilters(); + if (m_filterWidget) { - m_filterWidget->hide(); - m_filterWidget->deleteLater(); + m_filterWidget->ResetAllFilters(); + } + else + { + m_filterWidget = new GemFilterWidget(m_proxyModel); + m_filterWidgetLayout->addWidget(m_filterWidget); } - - m_proxModel->ResetFilters(); - m_filterWidget = new GemFilterWidget(m_proxModel); - m_filterWidgetLayout->addWidget(m_filterWidget); m_headerWidget->ReinitForProject(); @@ -193,6 +195,20 @@ namespace O3DE::ProjectManager } } + void GemCatalogScreen::SelectGem(const QString& gemName) + { + QModelIndex modelIndex = m_gemModel->FindIndexByNameString(gemName); + if (!m_proxyModel->filterAcceptsRow(modelIndex.row(), QModelIndex())) + { + m_proxyModel->ResetFilters(); + m_filterWidget->ResetAllFilters(); + } + + QModelIndex proxyIndex = m_proxyModel->mapFromSource(modelIndex); + m_proxyModel->GetSelectionModel()->select(proxyIndex, QItemSelectionModel::ClearAndSelect); + m_gemListView->scrollTo(proxyIndex); + } + void GemCatalogScreen::hideEvent(QHideEvent* event) { ScreenWidget::hideEvent(event); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h index 1ade87af0c..cfcd77e67c 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h @@ -48,6 +48,7 @@ namespace O3DE::ProjectManager public slots: void OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies); void OnAddGemClicked(); + void SelectGem(const QString& gemName); protected: void hideEvent(QHideEvent* event) override; @@ -68,7 +69,7 @@ namespace O3DE::ProjectManager GemInspector* m_gemInspector = nullptr; GemModel* m_gemModel = nullptr; GemCatalogHeaderWidget* m_headerWidget = nullptr; - GemSortFilterProxyModel* m_proxModel = nullptr; + GemSortFilterProxyModel* m_proxyModel = nullptr; QVBoxLayout* m_filterWidgetLayout = nullptr; GemFilterWidget* m_filterWidget = nullptr; DownloadController* m_downloadController = nullptr; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp index 4f737d8629..b608445d0f 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp @@ -213,11 +213,99 @@ namespace O3DE::ProjectManager m_filterLayout->setContentsMargins(0, 0, 0, 0); filterSection->setLayout(m_filterLayout); + ResetAllFilters(); + } + + void GemFilterWidget::ResetAllFilters() + { ResetGemStatusFilter(); - AddGemOriginFilter(); - AddTypeFilter(); - AddPlatformFilter(); - AddFeatureFilter(); + ResetGemOriginFilter(); + ResetTypeFilter(); + ResetPlatformFilter(); + ResetFeatureFilter(); + } + + void GemFilterWidget::ResetFilterWidget( + FilterCategoryWidget*& filterPtr, + const QString& filterName, + const QVector& elementNames, + const QVector& elementCounts, + int defaultShowCount) + { + bool wasCollapsed = false; + if (filterPtr) + { + wasCollapsed = filterPtr->IsCollapsed(); + } + + FilterCategoryWidget* filterWidget = new FilterCategoryWidget( + filterName, elementNames, elementCounts, /*showAllLessButton=*/defaultShowCount != 4, /*collapsed*/ wasCollapsed, + /*defaultShowCount=*/defaultShowCount); + if (filterPtr) + { + m_filterLayout->replaceWidget(filterPtr, filterWidget); + } + else + { + m_filterLayout->addWidget(filterWidget); + } + + filterPtr->deleteLater(); + filterPtr = filterWidget; + } + + template + void GemFilterWidget::ResetSimpleOrFilter( + FilterCategoryWidget*& filterPtr, + const QString& filterName, + int numFilterElements, + bool (*filterMatcher)(GemModel*, filterType, int), + QString (*typeStringGetter)(filterType), + filterFlagsType (GemSortFilterProxyModel::*filterFlagsGetter)() const, + void (GemSortFilterProxyModel::*filterFlagsSetter)(const filterFlagsType&)) + { + QVector elementNames; + QVector elementCounts; + const int numGems = m_gemModel->rowCount(); + for (int filterIndex = 0; filterIndex < numFilterElements; ++filterIndex) + { + const filterType gemFilterToBeCounted = static_cast(1 << filterIndex); + + int gemFilterCount = 0; + for (int gemIndex = 0; gemIndex < numGems; ++gemIndex) + { + // If filter matches increment filter count + gemFilterCount += filterMatcher(m_gemModel, gemFilterToBeCounted, gemIndex); + } + elementNames.push_back(typeStringGetter(gemFilterToBeCounted)); + elementCounts.push_back(gemFilterCount); + } + + // Replace existing filter and delete old one + ResetFilterWidget(filterPtr, filterName, elementNames, elementCounts); + + const QList buttons = filterPtr->GetButtonGroup()->buttons(); + for (int i = 0; i < buttons.size(); ++i) + { + const filterType gemFilter = static_cast(1 << i); + QAbstractButton* button = buttons[i]; + + connect( + button, &QAbstractButton::toggled, this, + [=](bool checked) + { + filterFlagsType gemFilters = (m_filterProxyModel->*filterFlagsGetter)(); + if (checked) + { + gemFilters |= gemFilter; + } + else + { + gemFilters &= ~gemFilter; + } + (m_filterProxyModel->*filterFlagsSetter)(gemFilters); + }); + } } void GemFilterWidget::ResetGemStatusFilter() @@ -241,25 +329,7 @@ namespace O3DE::ProjectManager elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive)); elementCounts.push_back(totalGems - enabledGemTotal); - bool wasCollapsed = false; - if (m_statusFilter) - { - wasCollapsed = m_statusFilter->IsCollapsed(); - } - - FilterCategoryWidget* filterWidget = - new FilterCategoryWidget("Status", elementNames, elementCounts, /*showAllLessButton=*/false, /*collapsed*/wasCollapsed); - if (m_statusFilter) - { - m_filterLayout->replaceWidget(m_statusFilter, filterWidget); - } - else - { - m_filterLayout->addWidget(filterWidget); - } - - m_statusFilter->deleteLater(); - m_statusFilter = filterWidget; + ResetFilterWidget(m_statusFilter, "Status", elementNames, elementCounts); const QList buttons = m_statusFilter->GetButtonGroup()->buttons(); @@ -317,157 +387,42 @@ namespace O3DE::ProjectManager connect(activeButton, &QAbstractButton::toggled, this, updateGemActive); } - void GemFilterWidget::AddGemOriginFilter() + void GemFilterWidget::ResetGemOriginFilter() { - QVector elementNames; - QVector elementCounts; - const int numGems = m_gemModel->rowCount(); - for (int originIndex = 0; originIndex < GemInfo::NumGemOrigins; ++originIndex) - { - const GemInfo::GemOrigin gemOriginToBeCounted = static_cast(1 << originIndex); - - int gemOriginCount = 0; - for (int gemIndex = 0; gemIndex < numGems; ++gemIndex) + ResetSimpleOrFilter + ( + m_originFilter, "Provider", GemInfo::NumGemOrigins, + [](GemModel* gemModel, GemInfo::GemOrigin origin, int 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_filterLayout->addWidget(filterWidget); - - const QList buttons = filterWidget->GetButtonGroup()->buttons(); - for (int i = 0; i < buttons.size(); ++i) - { - const GemInfo::GemOrigin gemOrigin = static_cast(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); - }); - } + return origin == gemModel->GetGemOrigin(gemModel->index(gemIndex, 0)); + }, + &GemInfo::GetGemOriginString, &GemSortFilterProxyModel::GetGemOrigins, &GemSortFilterProxyModel::SetGemOrigins + ); } - void GemFilterWidget::AddTypeFilter() + void GemFilterWidget::ResetTypeFilter() { - QVector elementNames; - QVector elementCounts; - const int numGems = m_gemModel->rowCount(); - for (int typeIndex = 0; typeIndex < GemInfo::NumTypes; ++typeIndex) - { - const GemInfo::Type type = static_cast(1 << typeIndex); - - int typeGemCount = 0; - for (int gemIndex = 0; gemIndex < numGems; ++gemIndex) + ResetSimpleOrFilter( + m_typeFilter, "Type", GemInfo::NumTypes, + [](GemModel* gemModel, GemInfo::Type type, int 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_filterLayout->addWidget(filterWidget); - - const QList buttons = filterWidget->GetButtonGroup()->buttons(); - for (int i = 0; i < buttons.size(); ++i) - { - const GemInfo::Type type = static_cast(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); - }); - } + return static_cast(type & gemModel->GetTypes(gemModel->index(gemIndex, 0))); + }, + &GemInfo::GetTypeString, &GemSortFilterProxyModel::GetTypes, &GemSortFilterProxyModel::SetTypes); } - void GemFilterWidget::AddPlatformFilter() + void GemFilterWidget::ResetPlatformFilter() { - QVector elementNames; - QVector elementCounts; - const int numGems = m_gemModel->rowCount(); - for (int platformIndex = 0; platformIndex < GemInfo::NumPlatforms; ++platformIndex) - { - const GemInfo::Platform platform = static_cast(1 << platformIndex); - - int platformGemCount = 0; - for (int gemIndex = 0; gemIndex < numGems; ++gemIndex) + ResetSimpleOrFilter( + m_platformFilter, "Supported Platforms", GemInfo::NumPlatforms, + [](GemModel* gemModel, GemInfo::Platform platform, int 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_filterLayout->addWidget(filterWidget); - - const QList buttons = filterWidget->GetButtonGroup()->buttons(); - for (int i = 0; i < buttons.size(); ++i) - { - const GemInfo::Platform platform = static_cast(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); - }); - } + return static_cast(platform & gemModel->GetPlatforms(gemModel->index(gemIndex, 0))); + }, + &GemInfo::GetPlatformString, &GemSortFilterProxyModel::GetPlatforms, &GemSortFilterProxyModel::SetPlatforms); } - void GemFilterWidget::AddFeatureFilter() + void GemFilterWidget::ResetFeatureFilter() { // Alphabetically sorted, unique features and their number of occurrences in the gem database. QMap uniqueFeatureCounts; @@ -497,11 +452,15 @@ namespace O3DE::ProjectManager elementCounts.push_back(iterator.value()); } - FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Features", elementNames, elementCounts, - /*showAllLessButton=*/true, false, /*defaultShowCount=*/5); - m_filterLayout->addWidget(filterWidget); + ResetFilterWidget(m_featureFilter, "Features", elementNames, elementCounts, /*defaultShowCount=*/5); - const QList buttons = filterWidget->GetButtonGroup()->buttons(); + for (QMetaObject::Connection& connection : m_featureTagConnections) + { + disconnect(connection); + } + m_featureTagConnections.clear(); + + const QList buttons = m_featureFilter->GetButtonGroup()->buttons(); for (int i = 0; i < buttons.size(); ++i) { const QString& feature = elementNames[i]; @@ -523,13 +482,13 @@ namespace O3DE::ProjectManager }); // Sync the UI state with the proxy model filtering. - connect(m_filterProxyModel, &GemSortFilterProxyModel::OnInvalidated, this, [=] + m_featureTagConnections.push_back(connect(m_filterProxyModel, &GemSortFilterProxyModel::OnInvalidated, this, [=] { const QSet& filteredFeatureTags = m_filterProxyModel->GetFeatures(); const bool isChecked = filteredFeatureTags.contains(button->text()); QSignalBlocker signalsBlocker(button); button->setChecked(isChecked); - }); + })); } } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.h index 6340f8309b..e422178d08 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.h @@ -66,17 +66,41 @@ namespace O3DE::ProjectManager ~GemFilterWidget() = default; public slots: + void ResetAllFilters(); void ResetGemStatusFilter(); private: - void AddGemOriginFilter(); - void AddTypeFilter(); - void AddPlatformFilter(); - void AddFeatureFilter(); + void ResetGemOriginFilter(); + void ResetTypeFilter(); + void ResetPlatformFilter(); + void ResetFeatureFilter(); + + void ResetFilterWidget( + FilterCategoryWidget*& filterPtr, + const QString& filterName, + const QVector& elementNames, + const QVector& elementCounts, + int defaultShowCount = 4); + + template + void ResetSimpleOrFilter( + FilterCategoryWidget*& filterPtr, + const QString& filterName, + int numFilterElements, + bool (*filterMatcher)(GemModel*, filterType, int), + QString (*typeStringGetter)(filterType), + filterFlagsType (GemSortFilterProxyModel::*filterFlagsGetter)() const, + void (GemSortFilterProxyModel::*filterFlagsSetter)(const filterFlagsType&)); QVBoxLayout* m_filterLayout = nullptr; GemModel* m_gemModel = nullptr; GemSortFilterProxyModel* m_filterProxyModel = nullptr; FilterCategoryWidget* m_statusFilter = nullptr; + FilterCategoryWidget* m_originFilter = nullptr; + FilterCategoryWidget* m_typeFilter = nullptr; + FilterCategoryWidget* m_platformFilter = nullptr; + FilterCategoryWidget* m_featureFilter = nullptr; + + QVector m_featureTagConnections; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp index acdef483ae..47f45b5559 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp @@ -54,6 +54,7 @@ namespace O3DE::ProjectManager appendRow(item); const QModelIndex modelIndex = index(rowCount()-1, 0); + m_nameToIndexMap[gemInfo.m_displayName] = modelIndex; m_nameToIndexMap[gemInfo.m_name] = modelIndex; } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp index 7ec45ac721..32d0e2fee9 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp @@ -207,6 +207,8 @@ namespace O3DE::ProjectManager void GemSortFilterProxyModel::ResetFilters() { m_searchString.clear(); + m_gemSelectedFilter = GemSelected::NoFilter; + m_gemActiveFilter = GemActive::NoFilter; m_gemOriginFilter = {}; m_platformFilter = {}; m_typeFilter = {};