From 781eaabd943ffb7852e5d9481a373a7d28cdd862 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 29 Oct 2021 12:05:42 -0700 Subject: [PATCH 01/10] Access gem repos from catalog non-destructively Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Source/CreateProjectCtrl.cpp | 23 ++++++++++++-- .../ProjectManager/Source/CreateProjectCtrl.h | 2 ++ .../Source/GemCatalog/GemCatalogScreen.cpp | 16 ---------- .../Source/UpdateProjectCtrl.cpp | 30 ++++++++++++++++--- .../ProjectManager/Source/UpdateProjectCtrl.h | 6 +++- 5 files changed, 54 insertions(+), 23 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp index 65e01803aa..c5325bfb42 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -47,8 +48,12 @@ namespace O3DE::ProjectManager m_gemCatalogScreen = new GemCatalogScreen(this); m_stack->addWidget(m_gemCatalogScreen); + + m_gemRepoScreen = new GemRepoScreen(this); + m_stack->addWidget(m_gemRepoScreen); vLayout->addWidget(m_stack); + connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest); // When there are multiple project templates present, we re-gather the gems when changing the selected the project template. @@ -89,6 +94,9 @@ namespace O3DE::ProjectManager buttons->setObjectName("footer"); vLayout->addWidget(buttons); + m_primaryButton = buttons->addButton(tr("Create Project"), QDialogButtonBox::ApplyRole); + connect(m_primaryButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandlePrimaryButton); + #ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED connect(m_newProjectSettingsScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest); @@ -100,8 +108,6 @@ namespace O3DE::ProjectManager Update(); #endif // TEMPLATE_GEM_CONFIGURATION_ENABLED - m_primaryButton = buttons->addButton(tr("Create Project"), QDialogButtonBox::ApplyRole); - connect(m_primaryButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandlePrimaryButton); setLayout(vLayout); } @@ -160,12 +166,21 @@ namespace O3DE::ProjectManager { m_header->setSubTitle(tr("Configure project with Gems")); m_secondaryButton->setVisible(false); + m_primaryButton->setVisible(true); + } + else if (m_stack->currentWidget() == m_gemRepoScreen) + { + m_header->setSubTitle(tr("Gem Repositories")); + m_secondaryButton->setVisible(true); + m_secondaryButton->setText(tr("Back")); + m_primaryButton->setVisible(false); } else { m_header->setSubTitle(tr("Enter Project Details")); m_secondaryButton->setVisible(true); m_secondaryButton->setText(tr("Configure Gems")); + m_primaryButton->setVisible(true); } } @@ -175,6 +190,10 @@ namespace O3DE::ProjectManager { HandleSecondaryButton(); } + else if (screen == ProjectManagerScreen::GemRepos) + { + NextScreen(); + } else { emit ChangeScreenRequest(screen); diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.h b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.h index 40ddb14b83..5352d58082 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.h +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.h @@ -23,6 +23,7 @@ namespace O3DE::ProjectManager QT_FORWARD_DECLARE_CLASS(ScreenHeader) QT_FORWARD_DECLARE_CLASS(NewProjectSettingsScreen) QT_FORWARD_DECLARE_CLASS(GemCatalogScreen) + QT_FORWARD_DECLARE_CLASS(GemRepoScreen) class CreateProjectCtrl : public ScreenWidget @@ -67,6 +68,7 @@ namespace O3DE::ProjectManager NewProjectSettingsScreen* m_newProjectSettingsScreen = nullptr; GemCatalogScreen* m_gemCatalogScreen = nullptr; + GemRepoScreen* m_gemRepoScreen = nullptr; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 98121d7cd2..1d238cf275 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -348,22 +348,6 @@ namespace O3DE::ProjectManager void GemCatalogScreen::HandleOpenGemRepo() { - QVector gemsToBeAdded = m_gemModel->GatherGemsToBeAdded(true); - QVector gemsToBeRemoved = m_gemModel->GatherGemsToBeRemoved(true); - - if (!gemsToBeAdded.empty() || !gemsToBeRemoved.empty()) - { - QMessageBox::StandardButton warningResult = QMessageBox::warning( - nullptr, "Pending Changes", - "There are some unsaved changes to the gem selection,
they will be lost if you change screens.
Are you sure?", - QMessageBox::No | QMessageBox::Yes); - - if (warningResult != QMessageBox::Yes) - { - return; - } - } - emit ChangeScreenRequest(ProjectManagerScreen::GemRepos); } diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 1c8f9a6931..5de3511f84 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -39,10 +40,9 @@ namespace O3DE::ProjectManager m_updateSettingsScreen = new UpdateProjectSettingsScreen(); m_gemCatalogScreen = new GemCatalogScreen(); + m_gemRepoScreen = new GemRepoScreen(this); - connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, [this](ProjectManagerScreen screen){ - emit ChangeScreenRequest(screen); - }); + connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &UpdateProjectCtrl::OnChangeScreenRequest); m_stack = new QStackedWidget(this); m_stack->setObjectName("body"); @@ -69,6 +69,7 @@ namespace O3DE::ProjectManager m_stack->addWidget(topBarFrameWidget); m_stack->addWidget(m_gemCatalogScreen); + m_stack->addWidget(m_gemRepoScreen); QDialogButtonBox* backNextButtons = new QDialogButtonBox(); backNextButtons->setObjectName("footer"); @@ -102,6 +103,19 @@ namespace O3DE::ProjectManager m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path); } + void UpdateProjectCtrl::OnChangeScreenRequest(ProjectManagerScreen screen) + { + if (screen == ProjectManagerScreen::GemRepos) + { + m_stack->setCurrentWidget(m_gemRepoScreen); + Update(); + } + else + { + emit ChangeScreenRequest(screen); + } + } + void UpdateProjectCtrl::HandleGemsButton() { if (UpdateProjectSettings(true)) @@ -181,18 +195,26 @@ namespace O3DE::ProjectManager void UpdateProjectCtrl::Update() { - if (m_stack->currentIndex() == ScreenOrder::Gems) + if (m_stack->currentIndex() == ScreenOrder::GemRepos) + { + m_header->setTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.GetProjectDisplayName())); + m_header->setSubTitle(QString(tr("Gem Repositories"))); + m_nextButton->setVisible(false); + } + else if (m_stack->currentIndex() == ScreenOrder::Gems) { m_header->setTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.GetProjectDisplayName())); m_header->setSubTitle(QString(tr("Configure Gems"))); m_nextButton->setText(tr("Save")); + m_nextButton->setVisible(true); } else { m_header->setTitle(""); m_header->setSubTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.GetProjectDisplayName())); m_nextButton->setText(tr("Save")); + m_nextButton->setVisible(true); } } diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.h b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.h index 3321fad638..5fef296ee7 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.h +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.h @@ -22,6 +22,7 @@ namespace O3DE::ProjectManager QT_FORWARD_DECLARE_CLASS(ScreenHeader) QT_FORWARD_DECLARE_CLASS(UpdateProjectSettingsScreen) QT_FORWARD_DECLARE_CLASS(GemCatalogScreen) + QT_FORWARD_DECLARE_CLASS(GemRepoScreen) class UpdateProjectCtrl : public ScreenWidget { @@ -37,6 +38,7 @@ namespace O3DE::ProjectManager void HandleBackButton(); void HandleNextButton(); void HandleGemsButton(); + void OnChangeScreenRequest(ProjectManagerScreen screen); void UpdateCurrentProject(const QString& projectPath); private: @@ -47,13 +49,15 @@ namespace O3DE::ProjectManager enum ScreenOrder { Settings, - Gems + Gems, + GemRepos }; ScreenHeader* m_header = nullptr; QStackedWidget* m_stack = nullptr; UpdateProjectSettingsScreen* m_updateSettingsScreen = nullptr; GemCatalogScreen* m_gemCatalogScreen = nullptr; + GemRepoScreen* m_gemRepoScreen = nullptr; QPushButton* m_backButton = nullptr; QPushButton* m_nextButton = nullptr; From 259ee654aec3c1793d5e78cc4fdbe443747fa3f6 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Mon, 1 Nov 2021 11:18:38 -0700 Subject: [PATCH 02/10] WIP refresh gem catalog in place Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Source/CreateProjectCtrl.cpp | 7 +++ .../Source/GemCatalog/GemCatalogScreen.cpp | 55 +++++++++++++++++++ .../Source/GemCatalog/GemCatalogScreen.h | 1 + .../Source/GemCatalog/GemModel.cpp | 11 ++++ .../Source/GemCatalog/GemModel.h | 3 + .../Source/GemRepo/GemRepoScreen.cpp | 4 ++ .../Source/GemRepo/GemRepoScreen.h | 4 ++ 7 files changed, 85 insertions(+) diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp index c5325bfb42..e33e9449fe 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp @@ -55,6 +55,13 @@ namespace O3DE::ProjectManager connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest); + connect( + m_gemRepoScreen, &GemRepoScreen::OnRefresh, + [this]() + { + const QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath(); + m_gemCatalogScreen->Refresh(projectTemplatePath + "/Template"); + }); // When there are multiple project templates present, we re-gather the gems when changing the selected the project template. connect(m_newProjectSettingsScreen, &NewProjectSettingsScreen::OnTemplateSelectionChanged, this, [=](int oldIndex, [[maybe_unused]] int newIndex) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 1d238cf275..fb78736a3c 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include namespace O3DE::ProjectManager { @@ -145,6 +147,59 @@ namespace O3DE::ProjectManager } } + void GemCatalogScreen::Refresh(const QString& projectPath) + { + QHash gemInfoHash; + + AZ::Outcome, AZStd::string> allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(projectPath); + if (allGemInfosResult.IsSuccess()) + { + QVector gemInfos = allGemInfosResult.GetValue(); + for (const GemInfo& gemInfo : gemInfos) + { + gemInfoHash.insert(gemInfo.m_name, gemInfo); + } + } + + AZ::Outcome, AZStd::string> allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos(); + if (allRepoGemInfosResult.IsSuccess()) + { + const QVector allRepoGemInfos = allRepoGemInfosResult.GetValue(); + for (const GemInfo& gemInfo : allRepoGemInfos) + { + if (!gemInfoHash.contains(gemInfo.m_name)) + { + gemInfoHash.insert(gemInfo.m_name, gemInfo); + } + } + } + + // remove rows for gems that were removed and not project dependencies + int i = 0; + while (i < m_gemModel->rowCount()) + { + QModelIndex index = m_gemModel->index(i,0); + QString gemName = m_gemModel->GetName(index); + if (!gemInfoHash.contains(gemName) && !m_gemModel->IsAdded(index) && !m_gemModel->IsAddedDependency(index)) + { + m_gemModel->removeRow(i); + } + else + { + gemInfoHash.remove(gemName); + i++; + } + } + + // add new rows + for(auto iter = gemInfoHash.begin(); iter != gemInfoHash.end(); ++iter) + { + m_gemModel->AddGem(iter.value()); + } + + m_gemModel->UpdateGemDependencies(); + } + void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies) { if (m_notificationsEnabled) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h index 1b34019d1a..b866b2d3af 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h @@ -33,6 +33,7 @@ namespace O3DE::ProjectManager ProjectManagerScreen GetScreenEnum() override; void ReinitForProject(const QString& projectPath); + void Refresh(const QString& projectPath); enum class EnableDisableGemsResult { diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp index fb228c0b4a..a059df4cbf 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp @@ -18,6 +18,7 @@ namespace O3DE::ProjectManager : QStandardItemModel(parent) { m_selectionModel = new QItemSelectionModel(this, parent); + connect(this, &QAbstractItemModel::rowsAboutToBeRemoved, this, &GemModel::OnRowsAboutToBeRemoved); } QItemSelectionModel* GemModel::GetSelectionModel() const @@ -359,6 +360,16 @@ namespace O3DE::ProjectManager gemModel->emit gemStatusChanged(gemName, numChangedDependencies); } + void GemModel::OnRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last) + { + for (int i = first; i <= last; ++i) + { + QModelIndex modelIndex = index(i, 0, parent); + const QString& gemName = GetName(modelIndex); + m_nameToIndexMap.remove(gemName); + } + } + void GemModel::SetIsAddedDependency(QAbstractItemModel& model, const QModelIndex& modelIndex, bool isAdded) { model.setData(modelIndex, isAdded, RoleIsAddedDependency); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h index 35231cc105..f4bc1ec502 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h @@ -80,6 +80,9 @@ namespace O3DE::ProjectManager signals: void gemStatusChanged(const QString& gemName, uint32_t numChangedDependencies); + protected slots: + void OnRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last); + private: void FindGemDisplayNamesByNameStrings(QStringList& inOutGemNames); void GetAllDependingGems(const QModelIndex& modelIndex, QSet& inOutGems); diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp index 0ddfe41434..30a57417d2 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp @@ -91,6 +91,7 @@ namespace O3DE::ProjectManager if (addGemRepoResult) { Reinit(); + emit OnRefresh(); } else { @@ -116,6 +117,7 @@ namespace O3DE::ProjectManager if (removeGemRepoResult) { Reinit(); + emit OnRefresh(); } else { @@ -130,6 +132,7 @@ namespace O3DE::ProjectManager { bool refreshResult = PythonBindingsInterface::Get()->RefreshAllGemRepos(); Reinit(); + emit OnRefresh(); if (!refreshResult) { @@ -146,6 +149,7 @@ namespace O3DE::ProjectManager if (refreshResult.IsSuccess()) { Reinit(); + emit OnRefresh(); } else { diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.h b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.h index 46a733362a..0516005eef 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.h +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.h @@ -28,6 +28,7 @@ namespace O3DE::ProjectManager class GemRepoScreen : public ScreenWidget { + Q_OBJECT public: explicit GemRepoScreen(QWidget* parent = nullptr); ~GemRepoScreen() = default; @@ -37,6 +38,9 @@ namespace O3DE::ProjectManager GemRepoModel* GetGemRepoModel() const { return m_gemRepoModel; } + signals: + void OnRefresh(); + public slots: void HandleAddRepoButton(); void HandleRemoveRepoButton(const QModelIndex& modelIndex); From 27c7e715168973e5b7fc175f427844500afbb4b1 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Wed, 3 Nov 2021 12:22:26 -0700 Subject: [PATCH 03/10] WIP default gem sorting Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Source/GemCatalog/GemCatalogScreen.cpp | 6 +++ .../Source/GemCatalog/GemModel.h | 50 +++++++++---------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index fb78736a3c..c76735d4f2 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -34,6 +34,9 @@ namespace O3DE::ProjectManager m_gemModel = new GemModel(this); m_proxModel = new GemSortFilterProxyModel(m_gemModel, this); + // default to sort by gem name + m_proxModel->setSortRole(GemModel::RoleName); + QVBoxLayout* vLayout = new QVBoxLayout(); vLayout->setMargin(0); vLayout->setSpacing(0); @@ -93,6 +96,8 @@ namespace O3DE::ProjectManager } m_proxModel->ResetFilters(); + m_proxModel->sort(/*column=*/0); + m_filterWidget = new GemFilterWidget(m_proxModel); m_filterWidgetLayout->addWidget(m_filterWidget); @@ -198,6 +203,7 @@ namespace O3DE::ProjectManager } m_gemModel->UpdateGemDependencies(); + m_proxModel->sort(/*column=*/0); } void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h index f4bc1ec502..9fac47d18e 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h @@ -26,6 +26,31 @@ namespace O3DE::ProjectManager explicit GemModel(QObject* parent = nullptr); QItemSelectionModel* GetSelectionModel() const; + enum UserRole + { + RoleName = Qt::UserRole, + RoleDisplayName, + RoleCreator, + RoleGemOrigin, + RolePlatforms, + RoleSummary, + RoleWasPreviouslyAdded, + RoleWasPreviouslyAddedDependency, + RoleIsAdded, + RoleIsAddedDependency, + RoleDirectoryLink, + RoleDocLink, + RoleDependingGems, + RoleVersion, + RoleLastUpdated, + RoleBinarySize, + RoleFeatures, + RoleTypes, + RolePath, + RoleRequirement, + RoleDownloadStatus + }; + void AddGem(const GemInfo& gemInfo); void Clear(); void UpdateGemDependencies(); @@ -88,31 +113,6 @@ namespace O3DE::ProjectManager void GetAllDependingGems(const QModelIndex& modelIndex, QSet& inOutGems); QStringList GetDependingGems(const QModelIndex& modelIndex); - enum UserRole - { - RoleName = Qt::UserRole, - RoleDisplayName, - RoleCreator, - RoleGemOrigin, - RolePlatforms, - RoleSummary, - RoleWasPreviouslyAdded, - RoleWasPreviouslyAddedDependency, - RoleIsAdded, - RoleIsAddedDependency, - RoleDirectoryLink, - RoleDocLink, - RoleDependingGems, - RoleVersion, - RoleLastUpdated, - RoleBinarySize, - RoleFeatures, - RoleTypes, - RolePath, - RoleRequirement, - RoleDownloadStatus - }; - QHash m_nameToIndexMap; QItemSelectionModel* m_selectionModel = nullptr; QHash> m_gemDependencyMap; From d8c2088d1dd2e9f3c9e2a70e3d2b60a95427f15f Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 2 Nov 2021 08:59:19 -0700 Subject: [PATCH 04/10] bugifx: resolve crash with project manager (#5151) - system allocator not configured in environment for AZQtComponents - WA_DeleteOnClose will destroy the toast dialog causing a crashing when ToastNotificationsView tries to access the pointer issue: https://github.com/o3de/o3de/issues/5129 Signed-off-by: Michael Pollind --- .../AzQtComponents/Components/ToastNotification.cpp | 1 - .../AzQtComponents/Components/ToastNotification.h | 3 +-- .../AzQtComponents/Components/ToastNotificationConfiguration.h | 1 - .../UI/Notifications/ToastNotificationsView.cpp | 2 +- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotification.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotification.cpp index 8831bef89c..11fd1e60d8 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotification.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotification.cpp @@ -27,7 +27,6 @@ namespace AzQtComponents setProperty("HasNoWindowDecorations", true); setAttribute(Qt::WA_ShowWithoutActivating); - setAttribute(Qt::WA_DeleteOnClose); m_borderRadius = toastConfiguration.m_borderRadius; if (m_borderRadius > 0) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotification.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotification.h index 4343f37df4..81b1cb4055 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotification.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotification.h @@ -31,7 +31,6 @@ namespace AzQtComponents { Q_OBJECT public: - AZ_CLASS_ALLOCATOR(ToastNotification, AZ::SystemAllocator, 0); ToastNotification(QWidget* parent, const ToastConfiguration& toastConfiguration); virtual ~ToastNotification(); @@ -73,7 +72,7 @@ namespace AzQtComponents AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING AZStd::chrono::milliseconds m_fadeDuration; - AZStd::unique_ptr m_ui; + QScopedPointer m_ui; AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING }; } // namespace AzQtComponents diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotificationConfiguration.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotificationConfiguration.h index 5ace9d1be2..2db374640e 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotificationConfiguration.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/ToastNotificationConfiguration.h @@ -27,7 +27,6 @@ namespace AzQtComponents class AZ_QT_COMPONENTS_API ToastConfiguration { public: - AZ_CLASS_ALLOCATOR(ToastConfiguration, AZ::SystemAllocator, 0); ToastConfiguration(ToastType toastType, const QString& title, const QString& description); bool m_closeOnClick = true; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Notifications/ToastNotificationsView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Notifications/ToastNotificationsView.cpp index a88711a9ed..277d3fa3c5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Notifications/ToastNotificationsView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Notifications/ToastNotificationsView.cpp @@ -129,7 +129,7 @@ namespace AzToolsFramework ToastId ToastNotificationsView::CreateToastNotification(const AzQtComponents::ToastConfiguration& toastConfiguration) { - AzQtComponents::ToastNotification* notification = aznew AzQtComponents::ToastNotification(parentWidget(), toastConfiguration); + AzQtComponents::ToastNotification* notification = new AzQtComponents::ToastNotification(this, toastConfiguration); ToastId toastId = AZ::Entity::MakeId(); m_notifications[toastId] = notification; From 861b29ffc7f6c829061e0c64f3cea975e57eef60 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Wed, 3 Nov 2021 13:45:40 -0700 Subject: [PATCH 05/10] Fix spelling change for member variable Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 08669d39a0..8234b80c8e 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -92,7 +92,7 @@ namespace O3DE::ProjectManager FillModel(projectPath); m_proxyModel->ResetFilters(); - m_proxModel->sort(/*column=*/0); + m_proxyModel->sort(/*column=*/0); if (m_filterWidget) { @@ -150,6 +150,7 @@ namespace O3DE::ProjectManager { m_gemModel->AddGem(gemInfoResult.GetValue()); m_gemModel->UpdateGemDependencies(); + m_proxyModel->sort(/*column=*/0); } } } @@ -206,7 +207,7 @@ namespace O3DE::ProjectManager } m_gemModel->UpdateGemDependencies(); - m_proxModel->sort(/*column=*/0); + m_proxyModel->sort(/*column=*/0); } void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies) From 2f8de3e797a40a4126d546c872f750ad55d76161 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Thu, 4 Nov 2021 09:37:26 -0700 Subject: [PATCH 06/10] Keep gem repos pages in sync Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Source/CreateProjectCtrl.cpp | 9 ++++---- .../Source/EngineScreenCtrl.cpp | 18 ++++++++++++++++ .../ProjectManager/Source/EngineScreenCtrl.h | 4 ++++ .../Source/GemCatalog/GemCatalogScreen.cpp | 21 +++++++++++++++---- .../Source/GemRepo/GemRepoScreen.cpp | 5 +++++ .../Source/GemRepo/GemRepoScreen.h | 3 +++ .../Source/UpdateProjectCtrl.cpp | 4 ++++ 7 files changed, 56 insertions(+), 8 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp index 6caa9b8a2b..1aad4a7206 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp @@ -51,13 +51,11 @@ namespace O3DE::ProjectManager m_gemRepoScreen = new GemRepoScreen(this); m_stack->addWidget(m_gemRepoScreen); + vLayout->addWidget(m_stack); - connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest); - connect( - m_gemRepoScreen, &GemRepoScreen::OnRefresh, - [this]() + connect(m_gemRepoScreen, &GemRepoScreen::OnRefresh, [this]() { const QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath(); m_gemCatalogScreen->Refresh(projectTemplatePath + "/Template"); @@ -135,6 +133,9 @@ namespace O3DE::ProjectManager // Gather the enabled gems from the default project template when starting the create new project workflow. ReinitGemCatalogForSelectedTemplate(); + + // make sure the gem repo has the latest details + m_gemRepoScreen->Reinit(); } void CreateProjectCtrl::HandleBackButton() diff --git a/Code/Tools/ProjectManager/Source/EngineScreenCtrl.cpp b/Code/Tools/ProjectManager/Source/EngineScreenCtrl.cpp index f30a8e0daa..9d9110922f 100644 --- a/Code/Tools/ProjectManager/Source/EngineScreenCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/EngineScreenCtrl.cpp @@ -39,6 +39,10 @@ namespace O3DE::ProjectManager m_tabWidget->addTab(m_engineSettingsScreen, tr("General")); m_tabWidget->addTab(m_gemRepoScreen, tr("Gem Repositories")); + + // when tab changes, notify the current screen so it can refresh + connect(m_tabWidget, &QTabWidget::currentChanged, this, &EngineScreenCtrl::TabChanged); + topBarHLayout->addWidget(m_tabWidget); vLayout->addWidget(topBarFrameWidget); @@ -46,6 +50,11 @@ namespace O3DE::ProjectManager setLayout(vLayout); } + void EngineScreenCtrl::TabChanged([[maybe_unused]] int index) + { + NotifyCurrentScreen(); + } + ProjectManagerScreen EngineScreenCtrl::GetScreenEnum() { return ProjectManagerScreen::UpdateProject; @@ -71,6 +80,15 @@ namespace O3DE::ProjectManager return false; } + void EngineScreenCtrl::NotifyCurrentScreen() + { + ScreenWidget* screen = reinterpret_cast(m_tabWidget->currentWidget()); + if (screen) + { + screen->NotifyCurrentScreen(); + } + } + void EngineScreenCtrl::GoToScreen(ProjectManagerScreen screen) { if (screen == m_engineSettingsScreen->GetScreenEnum()) diff --git a/Code/Tools/ProjectManager/Source/EngineScreenCtrl.h b/Code/Tools/ProjectManager/Source/EngineScreenCtrl.h index b7142ba226..cf0d2a24d0 100644 --- a/Code/Tools/ProjectManager/Source/EngineScreenCtrl.h +++ b/Code/Tools/ProjectManager/Source/EngineScreenCtrl.h @@ -30,6 +30,10 @@ namespace O3DE::ProjectManager bool IsTab() override; bool ContainsScreen(ProjectManagerScreen screen) override; void GoToScreen(ProjectManagerScreen screen) override; + void NotifyCurrentScreen() override; + + public slots: + void TabChanged(int index); QTabWidget* m_tabWidget = nullptr; EngineSettingsScreen* m_engineSettingsScreen = nullptr; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 8234b80c8e..915c837da4 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include namespace O3DE::ProjectManager @@ -160,6 +159,7 @@ namespace O3DE::ProjectManager { QHash gemInfoHash; + // create a hash with the gem name as key AZ::Outcome, AZStd::string> allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(projectPath); if (allGemInfosResult.IsSuccess()) { @@ -170,6 +170,7 @@ namespace O3DE::ProjectManager } } + // add all the gem repos into the hash AZ::Outcome, AZStd::string> allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos(); if (allRepoGemInfosResult.IsSuccess()) { @@ -183,24 +184,32 @@ namespace O3DE::ProjectManager } } - // remove rows for gems that were removed and not project dependencies + // remove gems from the model that no longer exist in the hash and are not project dependencies int i = 0; while (i < m_gemModel->rowCount()) { QModelIndex index = m_gemModel->index(i,0); QString gemName = m_gemModel->GetName(index); - if (!gemInfoHash.contains(gemName) && !m_gemModel->IsAdded(index) && !m_gemModel->IsAddedDependency(index)) + const bool gemFound = gemInfoHash.contains(gemName); + if (!gemFound && !m_gemModel->IsAdded(index) && !m_gemModel->IsAddedDependency(index)) { m_gemModel->removeRow(i); } else { + if (!gemFound && (m_gemModel->IsAdded(index) || !m_gemModel->IsAddedDependency(index))) + { + const QString error = tr("Gem %1 was removed or unregistered, but is still used by the project.").arg(gemName); + AZ_Warning("Project Manager", false, error.toUtf8().constData()); + QMessageBox::warning(this, tr("Gem not found"), error.toUtf8().constData()); + } + gemInfoHash.remove(gemName); i++; } } - // add new rows + // add all gems remaining in the hash that were not removed for(auto iter = gemInfoHash.begin(); iter != gemInfoHash.end(); ++iter) { m_gemModel->AddGem(iter.value()); @@ -208,6 +217,10 @@ namespace O3DE::ProjectManager m_gemModel->UpdateGemDependencies(); m_proxyModel->sort(/*column=*/0); + + // temporary, until we can refresh filter counts + m_proxyModel->ResetFilters(); + m_filterWidget->ResetAllFilters(); } void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies) diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp index 30a57417d2..794635a3e3 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp @@ -52,6 +52,11 @@ namespace O3DE::ProjectManager Reinit(); } + void GemRepoScreen::NotifyCurrentScreen() + { + Reinit(); + } + void GemRepoScreen::Reinit() { m_gemRepoModel->clear(); diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.h b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.h index 0516005eef..eed9a5ec4a 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.h +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.h @@ -38,6 +38,8 @@ namespace O3DE::ProjectManager GemRepoModel* GetGemRepoModel() const { return m_gemRepoModel; } + void NotifyCurrentScreen() override; + signals: void OnRefresh(); @@ -47,6 +49,7 @@ namespace O3DE::ProjectManager void HandleRefreshAllButton(); void HandleRefreshRepoButton(const QModelIndex& modelIndex); + private: void FillModel(); QFrame* CreateNoReposContent(); diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 5de3511f84..e76b4093a9 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -43,6 +43,7 @@ namespace O3DE::ProjectManager m_gemRepoScreen = new GemRepoScreen(this); connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &UpdateProjectCtrl::OnChangeScreenRequest); + connect(m_gemRepoScreen, &GemRepoScreen::OnRefresh, [this](){ m_gemCatalogScreen->Refresh(m_projectInfo.m_path); }); m_stack = new QStackedWidget(this); m_stack->setObjectName("body"); @@ -101,6 +102,9 @@ namespace O3DE::ProjectManager // Gather the available gems that will be shown in the gem catalog. m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path); + + // make sure the gem repo has the latest repo details + m_gemRepoScreen->Reinit(); } void UpdateProjectCtrl::OnChangeScreenRequest(ProjectManagerScreen screen) From 774b7c2593ad7c9b03412b2915e9138a6da64278 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Thu, 4 Nov 2021 11:03:36 -0700 Subject: [PATCH 07/10] Fixed minor logic issue with gem removal warning Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 915c837da4..4574e8509b 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -197,7 +197,7 @@ namespace O3DE::ProjectManager } else { - if (!gemFound && (m_gemModel->IsAdded(index) || !m_gemModel->IsAddedDependency(index))) + if (!gemFound && (m_gemModel->IsAdded(index) || m_gemModel->IsAddedDependency(index))) { const QString error = tr("Gem %1 was removed or unregistered, but is still used by the project.").arg(gemName); AZ_Warning("Project Manager", false, error.toUtf8().constData()); From 4ce39ea1675e6ba2b102bef02e4226f5b99ed081 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 5 Nov 2021 17:17:11 -0700 Subject: [PATCH 08/10] Fix tags, downloads, and several vector copies Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Source/CreateProjectCtrl.cpp | 12 +-- .../Source/DownloadController.cpp | 3 +- .../Source/DownloadController.h | 2 +- .../GemCatalog/GemCatalogHeaderWidget.cpp | 24 +++--- .../GemCatalog/GemCatalogHeaderWidget.h | 2 +- .../Source/GemCatalog/GemCatalogScreen.cpp | 78 +++++++++++++++---- .../Source/GemCatalog/GemCatalogScreen.h | 4 +- .../Source/GemCatalog/GemInspector.cpp | 8 +- .../Source/GemCatalog/GemInspector.h | 2 +- .../Source/GemCatalog/GemModel.cpp | 32 ++++---- .../Source/GemCatalog/GemModel.h | 4 +- .../Source/GemRepo/GemRepoInspector.cpp | 2 +- .../Source/GemRepo/GemRepoModel.cpp | 12 +-- .../Source/GemRepo/GemRepoModel.h | 2 +- .../ProjectManager/Source/GemsSubWidget.cpp | 6 +- .../ProjectManager/Source/GemsSubWidget.h | 4 +- .../Tools/ProjectManager/Source/TagWidget.cpp | 39 +++++++--- Code/Tools/ProjectManager/Source/TagWidget.h | 22 +++++- .../Source/UpdateProjectCtrl.cpp | 3 +- .../ProjectManager/Source/UpdateProjectCtrl.h | 1 + 20 files changed, 171 insertions(+), 91 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp index 1aad4a7206..6b19e839d7 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp @@ -55,11 +55,7 @@ namespace O3DE::ProjectManager vLayout->addWidget(m_stack); connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest); - connect(m_gemRepoScreen, &GemRepoScreen::OnRefresh, [this]() - { - const QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath(); - m_gemCatalogScreen->Refresh(projectTemplatePath + "/Template"); - }); + connect(m_gemRepoScreen, &GemRepoScreen::OnRefresh, m_gemCatalogScreen, &GemCatalogScreen::Refresh); // When there are multiple project templates present, we re-gather the gems when changing the selected the project template. connect(m_newProjectSettingsScreen, &NewProjectSettingsScreen::OnTemplateSelectionChanged, this, [=](int oldIndex, [[maybe_unused]] int newIndex) @@ -257,6 +253,12 @@ namespace O3DE::ProjectManager { if (m_newProjectSettingsScreen->Validate()) { + if (!m_gemCatalogScreen->GetDownloadController()->IsDownloadQueueEmpty()) + { + QMessageBox::critical(this, tr("Gems downloading"), tr("You must wait for gems to finish downloading before continuing.")); + return; + } + ProjectInfo projectInfo = m_newProjectSettingsScreen->GetProjectInfo(); QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath(); diff --git a/Code/Tools/ProjectManager/Source/DownloadController.cpp b/Code/Tools/ProjectManager/Source/DownloadController.cpp index 224b90299c..a8eecffd78 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadController.cpp @@ -82,8 +82,9 @@ namespace O3DE::ProjectManager succeeded = false; } + const QString gemName = m_gemNames[0]; m_gemNames.erase(m_gemNames.begin()); - emit Done(succeeded); + emit Done(succeeded, gemName); if (!m_gemNames.empty()) { diff --git a/Code/Tools/ProjectManager/Source/DownloadController.h b/Code/Tools/ProjectManager/Source/DownloadController.h index 11ceaacddb..8afe8ef029 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.h +++ b/Code/Tools/ProjectManager/Source/DownloadController.h @@ -58,7 +58,7 @@ namespace O3DE::ProjectManager signals: void StartGemDownload(const QString& gemName); - void Done(bool success = true); + void Done(bool success, const QString& gemName); void GemDownloadProgress(int percentage); private: diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 5d65c740af..0db2b088c1 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -145,7 +145,7 @@ namespace O3DE::ProjectManager } else { - tagContainer->Update(ConvertFromModelIndices(tagIndices)); + tagContainer->Update(GetTagsFromModelIndices(tagIndices)); label->setText(QString("%1 %2").arg(tagIndices.size()).arg(tagIndices.size() == 1 ? singularTitle : pluralTitle)); widget->show(); } @@ -234,17 +234,23 @@ namespace O3DE::ProjectManager for (int downloadingGemNumber = 0; downloadingGemNumber < downloadQueue.size(); ++downloadingGemNumber) { QHBoxLayout* nameProgressLayout = new QHBoxLayout(); - TagWidget* newTag = new TagWidget(downloadQueue[downloadingGemNumber]); + + const QString& gemName = downloadQueue[downloadingGemNumber]; + TagWidget* newTag = new TagWidget({gemName, gemName}); nameProgressLayout->addWidget(newTag); + QLabel* progress = new QLabel(downloadingGemNumber == 0? QString("%1%").arg(downloadProgress) : tr("Queued")); nameProgressLayout->addWidget(progress); + QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); nameProgressLayout->addSpacerItem(spacer); - QLabel* cancelText = new QLabel(QString("Cancel").arg(downloadQueue[downloadingGemNumber])); + + QLabel* cancelText = new QLabel(QString("Cancel")); cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse); connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated); nameProgressLayout->addWidget(cancelText); downloadingItemLayout->addLayout(nameProgressLayout); + QProgressBar* downloadProgessBar = new QProgressBar(); downloadingItemLayout->addWidget(downloadProgessBar); downloadProgessBar->setValue(downloadingGemNumber == 0 ? downloadProgress : 0); @@ -255,7 +261,7 @@ namespace O3DE::ProjectManager } }; - auto downloadEnded = [=](bool /*success*/) + auto downloadEnded = [=](bool /*success*/, const QString& /*gemName*/) { update(0); // update the list to remove the gem that has finished }; @@ -265,15 +271,15 @@ namespace O3DE::ProjectManager update(0); } - QStringList CartOverlayWidget::ConvertFromModelIndices(const QVector& gems) const + QVector CartOverlayWidget::GetTagsFromModelIndices(const QVector& gems) const { - QStringList gemNames; - gemNames.reserve(gems.size()); + QVector tags; + tags.reserve(gems.size()); for (const QModelIndex& modelIndex : gems) { - gemNames.push_back(GemModel::GetDisplayName(modelIndex)); + tags.push_back({ GemModel::GetDisplayName(modelIndex), GemModel::GetName(modelIndex) }); } - return gemNames; + return tags; } CartButton::CartButton(GemModel* gemModel, DownloadController* downloadController, QWidget* parent) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h index 4d17259840..6da78cce7a 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h @@ -36,7 +36,7 @@ namespace O3DE::ProjectManager CartOverlayWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr); private: - QStringList ConvertFromModelIndices(const QVector& gems) const; + QVector GetTagsFromModelIndices(const QVector& gems) const; using GetTagIndicesCallback = AZStd::function()>; void CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 4574e8509b..b0e4fa73e1 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -49,6 +49,7 @@ namespace O3DE::ProjectManager connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged); connect(m_headerWidget, &GemCatalogHeaderWidget::OpenGemsRepo, this, &GemCatalogScreen::HandleOpenGemRepo); connect(m_headerWidget, &GemCatalogHeaderWidget::AddGem, this, &GemCatalogScreen::OnAddGemClicked); + connect(m_downloadController, &DownloadController::Done, this, &GemCatalogScreen::OnGemDownloadResult); QHBoxLayout* hLayout = new QHBoxLayout(); hLayout->setMargin(0); @@ -58,7 +59,7 @@ namespace O3DE::ProjectManager m_gemInspector = new GemInspector(m_gemModel, this); m_gemInspector->setFixedWidth(240); - connect(m_gemInspector, &GemInspector::TagClicked, this, &GemCatalogScreen::SelectGem); + connect(m_gemInspector, &GemInspector::TagClicked, [=](const Tag& tag) { SelectGem(tag.id); }); QWidget* filterWidget = new QWidget(this); filterWidget->setFixedWidth(240); @@ -86,6 +87,7 @@ namespace O3DE::ProjectManager void GemCatalogScreen::ReinitForProject(const QString& projectPath) { + m_projectPath = projectPath; m_gemModel->Clear(); m_gemsToRegisterWithProject.clear(); FillModel(projectPath); @@ -155,15 +157,15 @@ namespace O3DE::ProjectManager } } - void GemCatalogScreen::Refresh(const QString& projectPath) + void GemCatalogScreen::Refresh() { QHash gemInfoHash; // create a hash with the gem name as key - AZ::Outcome, AZStd::string> allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(projectPath); + const AZ::Outcome, AZStd::string>& allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(m_projectPath); if (allGemInfosResult.IsSuccess()) { - QVector gemInfos = allGemInfosResult.GetValue(); + const QVector& gemInfos = allGemInfosResult.GetValue(); for (const GemInfo& gemInfo : gemInfos) { gemInfoHash.insert(gemInfo.m_name, gemInfo); @@ -171,10 +173,10 @@ namespace O3DE::ProjectManager } // add all the gem repos into the hash - AZ::Outcome, AZStd::string> allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos(); + const AZ::Outcome, AZStd::string>& allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos(); if (allRepoGemInfosResult.IsSuccess()) { - const QVector allRepoGemInfos = allRepoGemInfosResult.GetValue(); + const QVector& allRepoGemInfos = allRepoGemInfosResult.GetValue(); for (const GemInfo& gemInfo : allRepoGemInfos) { if (!gemInfoHash.contains(gemInfo.m_name)) @@ -310,20 +312,22 @@ namespace O3DE::ProjectManager void GemCatalogScreen::FillModel(const QString& projectPath) { - AZ::Outcome, AZStd::string> allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(projectPath); + m_projectPath = projectPath; + + const AZ::Outcome, AZStd::string>& allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(projectPath); if (allGemInfosResult.IsSuccess()) { // Add all available gems to the model. - const QVector allGemInfos = allGemInfosResult.GetValue(); + const QVector& allGemInfos = allGemInfosResult.GetValue(); for (const GemInfo& gemInfo : allGemInfos) { m_gemModel->AddGem(gemInfo); } - AZ::Outcome, AZStd::string> allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos(); + const AZ::Outcome, AZStd::string>& allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos(); if (allRepoGemInfosResult.IsSuccess()) { - const QVector allRepoGemInfos = allRepoGemInfosResult.GetValue(); + const QVector& allRepoGemInfos = allRepoGemInfosResult.GetValue(); for (const GemInfo& gemInfo : allRepoGemInfos) { // do not add gems that have already been downloaded @@ -342,10 +346,10 @@ namespace O3DE::ProjectManager m_notificationsEnabled = false; // Gather enabled gems for the given project. - auto enabledGemNamesResult = PythonBindingsInterface::Get()->GetEnabledGemNames(projectPath); + const auto& enabledGemNamesResult = PythonBindingsInterface::Get()->GetEnabledGemNames(projectPath); if (enabledGemNamesResult.IsSuccess()) { - const QVector enabledGemNames = enabledGemNamesResult.GetValue(); + const QVector& enabledGemNames = enabledGemNamesResult.GetValue(); for (const AZStd::string& enabledGemName : enabledGemNames) { const QModelIndex modelIndex = m_gemModel->FindIndexByNameString(enabledGemName.c_str()); @@ -405,12 +409,24 @@ namespace O3DE::ProjectManager for (const QModelIndex& modelIndex : toBeAdded) { - const QString gemPath = GemModel::GetPath(modelIndex); + const QString& gemPath = GemModel::GetPath(modelIndex); + + // make sure any remote gems we added were downloaded successfully + if (GemModel::GetGemOrigin(modelIndex) == GemInfo::Remote && GemModel::GetDownloadStatus(modelIndex) != GemInfo::Downloaded) + { + QMessageBox::critical( + nullptr, "Cannot add gem that isn't downloaded", + tr("Cannot add gem %1 to project because it isn't downloaded yet or failed to download.") + .arg(GemModel::GetDisplayName(modelIndex))); + + return EnableDisableGemsResult::Failed; + } + const AZ::Outcome result = pythonBindings->AddGemToProject(gemPath, projectPath); if (!result.IsSuccess()) { - QMessageBox::critical(nullptr, "Operation failed", - QString("Cannot add gem %1 to project.\n\nError:\n%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str())); + QMessageBox::critical(nullptr, "Failed to add gem to project", + tr("Cannot add gem %1 to project.

Error:
%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str())); return EnableDisableGemsResult::Failed; } @@ -428,8 +444,8 @@ namespace O3DE::ProjectManager const AZ::Outcome result = pythonBindings->RemoveGemFromProject(gemPath, projectPath); if (!result.IsSuccess()) { - QMessageBox::critical(nullptr, "Operation failed", - QString("Cannot remove gem %1 from project.\n\nError:\n%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str())); + QMessageBox::critical(nullptr, "Failed to remove gem from project", + tr("Cannot remove gem %1 from project.

Error:
%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str())); return EnableDisableGemsResult::Failed; } @@ -443,6 +459,34 @@ namespace O3DE::ProjectManager emit ChangeScreenRequest(ProjectManagerScreen::GemRepos); } + void GemCatalogScreen::OnGemDownloadResult(bool succeeded, const QString& gemName) + { + if (succeeded) + { + // refresh the information for downloaded gems + const AZ::Outcome, AZStd::string>& allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(m_projectPath); + if (allGemInfosResult.IsSuccess()) + { + // we should find the gem name now in all gem infos + for (const GemInfo& gemInfo : allGemInfosResult.GetValue()) + { + if (gemInfo.m_name == gemName) + { + QModelIndex index = m_gemModel->FindIndexByNameString(gemName); + if (index.isValid()) + { + m_gemModel->setData(index, GemInfo::Downloaded, GemModel::RoleDownloadStatus); + m_gemModel->setData(index, gemInfo.m_path, GemModel::RolePath); + m_gemModel->setData(index, gemInfo.m_path, GemModel::RoleDirectoryLink); + } + + return; + } + } + } + } + } + ProjectManagerScreen GemCatalogScreen::GetScreenEnum() { return ProjectManagerScreen::GemCatalog; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h index 69ec85586d..6acf43b3eb 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h @@ -33,7 +33,6 @@ namespace O3DE::ProjectManager ProjectManagerScreen GetScreenEnum() override; void ReinitForProject(const QString& projectPath); - void Refresh(const QString& projectPath); enum class EnableDisableGemsResult { @@ -50,6 +49,8 @@ namespace O3DE::ProjectManager void OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies); void OnAddGemClicked(); void SelectGem(const QString& gemName); + void OnGemDownloadResult(bool succeeded, const QString& gemName); + void Refresh(); protected: void hideEvent(QHideEvent* event) override; @@ -76,5 +77,6 @@ namespace O3DE::ProjectManager DownloadController* m_downloadController = nullptr; bool m_notificationsEnabled = true; QSet m_gemsToRegisterWithProject; + QString m_projectPath = nullptr; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp index b0b8cca29a..afbac189ad 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp @@ -106,10 +106,10 @@ namespace O3DE::ProjectManager } // Depending gems - QStringList dependingGems = m_model->GetDependingGemNames(modelIndex); - if (!dependingGems.isEmpty()) + const QVector& dependingGemTags = m_model->GetDependingGemTags(modelIndex); + if (!dependingGemTags.isEmpty()) { - m_dependingGems->Update(tr("Depending Gems"), tr("The following Gems will be automatically enabled with this Gem."), dependingGems); + m_dependingGems->Update(tr("Depending Gems"), tr("The following Gems will be automatically enabled with this Gem."), dependingGemTags); m_dependingGems->show(); } else @@ -222,7 +222,7 @@ namespace O3DE::ProjectManager // Depending gems m_dependingGems = new GemsSubWidget(); - connect(m_dependingGems, &GemsSubWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); }); + connect(m_dependingGems, &GemsSubWidget::TagClicked, this, [=](const Tag& tag){ emit TagClicked(tag); }); m_mainLayout->addWidget(m_dependingGems); m_mainLayout->addSpacing(20); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.h index c6548527ab..9a6ad84dea 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.h @@ -44,7 +44,7 @@ namespace O3DE::ProjectManager inline constexpr static const char* s_textColor = "#DDDDDD"; signals: - void TagClicked(const QString& tag); + void TagClicked(const Tag& tag); private slots: void OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp index 7c217db65b..88c54de0b3 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp @@ -65,7 +65,6 @@ namespace O3DE::ProjectManager appendRow(item); const QModelIndex modelIndex = index(rowCount()-1, 0); - m_nameToIndexMap[gemInfo.m_displayName] = modelIndex; m_nameToIndexMap[gemInfo.m_name] = modelIndex; } @@ -178,18 +177,6 @@ namespace O3DE::ProjectManager return {}; } - void GemModel::FindGemDisplayNamesByNameStrings(QStringList& inOutGemNames) - { - for (QString& name : inOutGemNames) - { - QModelIndex modelIndex = FindIndexByNameString(name); - if (modelIndex.isValid()) - { - name = GetDisplayName(modelIndex); - } - } - } - QStringList GemModel::GetDependingGems(const QModelIndex& modelIndex) { return modelIndex.data(RoleDependingGems).toStringList(); @@ -209,16 +196,23 @@ namespace O3DE::ProjectManager } } - QStringList GemModel::GetDependingGemNames(const QModelIndex& modelIndex) + QVector GemModel::GetDependingGemTags(const QModelIndex& modelIndex) { - QStringList result = GetDependingGems(modelIndex); - if (result.isEmpty()) + QVector tags; + + QStringList dependingGemNames = GetDependingGems(modelIndex); + tags.reserve(dependingGemNames.size()); + + for (QString& gemName : dependingGemNames) { - return {}; + const QModelIndex& dependingIndex = FindIndexByNameString(gemName); + if (dependingIndex.isValid()) + { + tags.push_back({ GetDisplayName(dependingIndex), GetName(dependingIndex) }); + } } - FindGemDisplayNamesByNameStrings(result); - return result; + return tags; } QString GemModel::GetVersion(const QModelIndex& modelIndex) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h index e548d9d3f7..e25a1c7703 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h @@ -10,6 +10,7 @@ #if !defined(Q_MOC_RUN) #include +#include #include #include #include @@ -58,7 +59,7 @@ namespace O3DE::ProjectManager void UpdateGemDependencies(); QModelIndex FindIndexByNameString(const QString& nameString) const; - QStringList GetDependingGemNames(const QModelIndex& modelIndex); + QVector GetDependingGemTags(const QModelIndex& modelIndex); bool HasDependentGems(const QModelIndex& modelIndex) const; static QString GetName(const QModelIndex& modelIndex); @@ -113,7 +114,6 @@ namespace O3DE::ProjectManager void OnRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last); private: - void FindGemDisplayNamesByNameStrings(QStringList& inOutGemNames); void GetAllDependingGems(const QModelIndex& modelIndex, QSet& inOutGems); QStringList GetDependingGems(const QModelIndex& modelIndex); diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoInspector.cpp b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoInspector.cpp index 6655aef86d..f816e86733 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoInspector.cpp +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoInspector.cpp @@ -86,7 +86,7 @@ namespace O3DE::ProjectManager } // Included Gems - m_includedGems->Update(tr("Included Gems"), "", m_model->GetIncludedGemNames(modelIndex)); + m_includedGems->Update(tr("Included Gems"), "", m_model->GetIncludedGemTags(modelIndex)); m_mainWidget->adjustSize(); m_mainWidget->show(); diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoModel.cpp b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoModel.cpp index 7a9617e6c1..6189b6d8bf 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoModel.cpp @@ -103,17 +103,17 @@ namespace O3DE::ProjectManager return modelIndex.data(RoleIncludedGems).toStringList(); } - QStringList GemRepoModel::GetIncludedGemNames(const QModelIndex& modelIndex) + QVector GemRepoModel::GetIncludedGemTags(const QModelIndex& modelIndex) { - QStringList gemNames; - QVector gemInfos = GetIncludedGemInfos(modelIndex); - + QVector tags; + const QVector& gemInfos = GetIncludedGemInfos(modelIndex); + tags.reserve(gemInfos.size()); for (const GemInfo& gemInfo : gemInfos) { - gemNames.append(gemInfo.m_displayName); + tags.append({ gemInfo.m_displayName, gemInfo.m_name }); } - return gemNames; + return tags; } QVector GemRepoModel::GetIncludedGemInfos(const QModelIndex& modelIndex) diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoModel.h b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoModel.h index f36b66ca48..66fe972a95 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoModel.h +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoModel.h @@ -40,7 +40,7 @@ namespace O3DE::ProjectManager static QString GetPath(const QModelIndex& modelIndex); static QStringList GetIncludedGemPaths(const QModelIndex& modelIndex); - static QStringList GetIncludedGemNames(const QModelIndex& modelIndex); + static QVector GetIncludedGemTags(const QModelIndex& modelIndex); static QVector GetIncludedGemInfos(const QModelIndex& modelIndex); static bool IsEnabled(const QModelIndex& modelIndex); diff --git a/Code/Tools/ProjectManager/Source/GemsSubWidget.cpp b/Code/Tools/ProjectManager/Source/GemsSubWidget.cpp index 8b7b183008..2572a39db3 100644 --- a/Code/Tools/ProjectManager/Source/GemsSubWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemsSubWidget.cpp @@ -33,14 +33,14 @@ namespace O3DE::ProjectManager m_layout->addWidget(m_textLabel); m_tagWidget = new TagContainerWidget(); - connect(m_tagWidget, &TagContainerWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); }); + connect(m_tagWidget, &TagContainerWidget::TagClicked, this, [=](const Tag& tag){ emit TagClicked(tag); }); m_layout->addWidget(m_tagWidget); } - void GemsSubWidget::Update(const QString& title, const QString& text, const QStringList& gemNames) + void GemsSubWidget::Update(const QString& title, const QString& text, const QVector& tags) { m_titleLabel->setText(title); m_textLabel->setText(text); - m_tagWidget->Update(gemNames); + m_tagWidget->Update(tags); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemsSubWidget.h b/Code/Tools/ProjectManager/Source/GemsSubWidget.h index a9fabf5e92..5e670b930a 100644 --- a/Code/Tools/ProjectManager/Source/GemsSubWidget.h +++ b/Code/Tools/ProjectManager/Source/GemsSubWidget.h @@ -26,10 +26,10 @@ namespace O3DE::ProjectManager public: GemsSubWidget(QWidget* parent = nullptr); - void Update(const QString& title, const QString& text, const QStringList& gemNames); + void Update(const QString& title, const QString& text, const QVector& tags); signals: - void TagClicked(const QString& tag); + void TagClicked(const Tag& tag); private: QLabel* m_titleLabel = nullptr; diff --git a/Code/Tools/ProjectManager/Source/TagWidget.cpp b/Code/Tools/ProjectManager/Source/TagWidget.cpp index 39231ace4b..007f0839d1 100644 --- a/Code/Tools/ProjectManager/Source/TagWidget.cpp +++ b/Code/Tools/ProjectManager/Source/TagWidget.cpp @@ -12,15 +12,16 @@ namespace O3DE::ProjectManager { - TagWidget::TagWidget(const QString& text, QWidget* parent) - : QLabel(text, parent) + TagWidget::TagWidget(const Tag& tag, QWidget* parent) + : QLabel(tag.text, parent) + , m_tag(tag) { setObjectName("TagWidget"); } void TagWidget::mousePressEvent([[maybe_unused]] QMouseEvent* event) { - emit(TagClicked(text())); + emit TagClicked(m_tag); } TagContainerWidget::TagContainerWidget(QWidget* parent) @@ -39,20 +40,34 @@ namespace O3DE::ProjectManager void TagContainerWidget::Update(const QStringList& tags) { - FlowLayout* flowLayout = static_cast(layout()); + Clear(); - // remove old tags + foreach (const QString& tag, tags) + { + TagWidget* tagWidget = new TagWidget({tag, tag}); + connect(tagWidget, &TagWidget::TagClicked, this, [=](const Tag& clickedTag){ emit TagClicked(clickedTag); }); + layout()->addWidget(tagWidget); + } + } + + void TagContainerWidget::Update(const QVector& tags) + { + Clear(); + + foreach (const Tag& tag, tags) + { + TagWidget* tagWidget = new TagWidget(tag); + connect(tagWidget, &TagWidget::TagClicked, this, [=](const Tag& clickedTag){ emit TagClicked(clickedTag); }); + layout()->addWidget(tagWidget); + } + } + + void TagContainerWidget::Clear() + { QLayoutItem* layoutItem = nullptr; while ((layoutItem = layout()->takeAt(0)) != nullptr) { layoutItem->widget()->deleteLater(); } - - foreach (const QString& tag, tags) - { - TagWidget* tagWidget = new TagWidget(tag); - connect(tagWidget, &TagWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); }); - flowLayout->addWidget(tagWidget); - } } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/TagWidget.h b/Code/Tools/ProjectManager/Source/TagWidget.h index 7b4a5b1aaa..fce6eaf863 100644 --- a/Code/Tools/ProjectManager/Source/TagWidget.h +++ b/Code/Tools/ProjectManager/Source/TagWidget.h @@ -10,12 +10,19 @@ #if !defined(Q_MOC_RUN) #include -#include #include +#include +#include #endif namespace O3DE::ProjectManager { + struct Tag + { + QString text; + QString id; + }; + // Single tag class TagWidget : public QLabel @@ -23,14 +30,17 @@ namespace O3DE::ProjectManager Q_OBJECT // AUTOMOC public: - explicit TagWidget(const QString& text, QWidget* parent = nullptr); + explicit TagWidget(const Tag& id, QWidget* parent = nullptr); ~TagWidget() = default; signals: - void TagClicked(const QString& tag); + void TagClicked(const Tag& tag); protected: void mousePressEvent(QMouseEvent* event) override; + + private: + Tag m_tag; }; // Widget containing multiple tags, automatically wrapping based on the size @@ -43,9 +53,13 @@ namespace O3DE::ProjectManager explicit TagContainerWidget(QWidget* parent = nullptr); ~TagContainerWidget() = default; + void Update(const QVector& tags); void Update(const QStringList& tags); signals: - void TagClicked(const QString& tag); + void TagClicked(const Tag& tag); + + private: + void Clear(); }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index e76b4093a9..fb16484961 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -43,7 +43,7 @@ namespace O3DE::ProjectManager m_gemRepoScreen = new GemRepoScreen(this); connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &UpdateProjectCtrl::OnChangeScreenRequest); - connect(m_gemRepoScreen, &GemRepoScreen::OnRefresh, [this](){ m_gemCatalogScreen->Refresh(m_projectInfo.m_path); }); + connect(m_gemRepoScreen, &GemRepoScreen::OnRefresh, m_gemCatalogScreen, &GemCatalogScreen::Refresh); m_stack = new QStackedWidget(this); m_stack->setObjectName("body"); @@ -163,6 +163,7 @@ namespace O3DE::ProjectManager QMessageBox::critical(this, tr("Gems downloading"), tr("You must wait for gems to finish downloading before continuing.")); return; } + // Enable or disable the gems that got adjusted in the gem catalog and apply them to the given project. const GemCatalogScreen::EnableDisableGemsResult result = m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path); if (result == GemCatalogScreen::EnableDisableGemsResult::Failed) diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.h b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.h index 5fef296ee7..ee6fc792f2 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.h +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.h @@ -26,6 +26,7 @@ namespace O3DE::ProjectManager class UpdateProjectCtrl : public ScreenWidget { + Q_OBJECT public: explicit UpdateProjectCtrl(QWidget* parent = nullptr); ~UpdateProjectCtrl() = default; From 21c02b195f9e5ee39b6e9d90aa8a41a69a50a7dd Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 5 Nov 2021 17:24:08 -0700 Subject: [PATCH 09/10] Update signals/slots to match upstream changes Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- Code/Tools/ProjectManager/Source/DownloadController.cpp | 6 +++--- Code/Tools/ProjectManager/Source/DownloadController.h | 2 +- .../Source/GemCatalog/GemCatalogHeaderWidget.cpp | 2 +- .../ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp | 2 +- .../ProjectManager/Source/GemCatalog/GemCatalogScreen.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/DownloadController.cpp b/Code/Tools/ProjectManager/Source/DownloadController.cpp index a8eecffd78..d30e1bbc7c 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadController.cpp @@ -82,13 +82,13 @@ namespace O3DE::ProjectManager succeeded = false; } - const QString gemName = m_gemNames[0]; + QString gemName = m_gemNames.front(); m_gemNames.erase(m_gemNames.begin()); - emit Done(succeeded, gemName); + emit Done(gemName, succeeded); if (!m_gemNames.empty()) { - emit StartGemDownload(m_gemNames[0]); + emit StartGemDownload(m_gemNames.front()); } else { diff --git a/Code/Tools/ProjectManager/Source/DownloadController.h b/Code/Tools/ProjectManager/Source/DownloadController.h index 8afe8ef029..5b2d230379 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.h +++ b/Code/Tools/ProjectManager/Source/DownloadController.h @@ -58,7 +58,7 @@ namespace O3DE::ProjectManager signals: void StartGemDownload(const QString& gemName); - void Done(bool success, const QString& gemName); + void Done(const QString& gemName, bool success = true); void GemDownloadProgress(int percentage); private: diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 0db2b088c1..71d5086fff 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -261,7 +261,7 @@ namespace O3DE::ProjectManager } }; - auto downloadEnded = [=](bool /*success*/, const QString& /*gemName*/) + auto downloadEnded = [=](const QString& /*gemName*/, bool /*success*/) { update(0); // update the list to remove the gem that has finished }; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index b0e4fa73e1..79935ed235 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -459,7 +459,7 @@ namespace O3DE::ProjectManager emit ChangeScreenRequest(ProjectManagerScreen::GemRepos); } - void GemCatalogScreen::OnGemDownloadResult(bool succeeded, const QString& gemName) + void GemCatalogScreen::OnGemDownloadResult(const QString& gemName, bool succeeded) { if (succeeded) { diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h index 6acf43b3eb..da6d2efa7b 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h @@ -49,7 +49,7 @@ namespace O3DE::ProjectManager void OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies); void OnAddGemClicked(); void SelectGem(const QString& gemName); - void OnGemDownloadResult(bool succeeded, const QString& gemName); + void OnGemDownloadResult(const QString& gemName, bool succeeded = true); void Refresh(); protected: From 0295aa7070154d53c00b8ac4680d23ebb9a4e202 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 5 Nov 2021 17:31:01 -0700 Subject: [PATCH 10/10] revert change to cancel label href Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 71d5086fff..8c875e4846 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -245,7 +245,7 @@ namespace O3DE::ProjectManager QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); nameProgressLayout->addSpacerItem(spacer); - QLabel* cancelText = new QLabel(QString("Cancel")); + QLabel* cancelText = new QLabel(QString("Cancel").arg(gemName)); cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse); connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated); nameProgressLayout->addWidget(cancelText);