Add existing gem through Project Manager

monroegm-disable-blank-issue-2
Alex Peterson 4 years ago committed by GitHub
parent 0dfa08cac8
commit b536abbf4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -523,6 +523,14 @@ QProgressBar::chunk {
background-color: #444444; background-color: #444444;
} }
#gemCatalogMenuButton {
qproperty-flat: true;
max-width:36px;
min-width:36px;
max-height:24px;
min-height:24px;
}
#GemCatalogHeaderLabel { #GemCatalogHeaderLabel {
font-size: 12px; font-size: 12px;
color: #FFFFFF; color: #FFFFFF;

@ -8,14 +8,13 @@
#include <GemCatalog/GemCatalogHeaderWidget.h> #include <GemCatalog/GemCatalogHeaderWidget.h>
#include <AzCore/std/functional.h> #include <AzCore/std/functional.h>
#include <TagWidget.h>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QMouseEvent> #include <QMouseEvent>
#include <QLabel> #include <QLabel>
#include <QPushButton> #include <QPushButton>
#include <QMenu>
#include <QProgressBar> #include <QProgressBar>
#include <TagWidget.h>
#include <QMenu>
namespace O3DE::ProjectManager namespace O3DE::ProjectManager
{ {
@ -406,7 +405,6 @@ namespace O3DE::ProjectManager
CartButton* cartButton = new CartButton(gemModel, downloadController); CartButton* cartButton = new CartButton(gemModel, downloadController);
hLayout->addWidget(cartButton); hLayout->addWidget(cartButton);
hLayout->addSpacing(16); hLayout->addSpacing(16);
// Separating line // Separating line
@ -418,9 +416,9 @@ namespace O3DE::ProjectManager
hLayout->addSpacing(16); hLayout->addSpacing(16);
QMenu* gemMenu = new QMenu(this); QMenu* gemMenu = new QMenu(this);
m_openGemReposAction = gemMenu->addAction(tr("Show Gem Repos")); gemMenu->addAction( tr("Show Gem Repos"), [this]() { emit OpenGemsRepo(); });
gemMenu->addSeparator();
connect(m_openGemReposAction, &QAction::triggered, this,[this](){ emit OpenGemsRepo(); }); gemMenu->addAction( tr("Add Existing Gem"), [this]() { emit AddGem(); });
QPushButton* gemMenuButton = new QPushButton(this); QPushButton* gemMenuButton = new QPushButton(this);
gemMenuButton->setObjectName("gemCatalogMenuButton"); gemMenuButton->setObjectName("gemCatalogMenuButton");

@ -8,24 +8,23 @@
#pragma once #pragma once
#include <AzCore/std/function/function_fwd.h>
#if !defined(Q_MOC_RUN) #if !defined(Q_MOC_RUN)
#include <AzCore/std/function/function_fwd.h>
#include <AzQtComponents/Components/SearchLineEdit.h> #include <AzQtComponents/Components/SearchLineEdit.h>
#include <GemCatalog/GemModel.h> #include <GemCatalog/GemModel.h>
#include <GemCatalog/GemSortFilterProxyModel.h> #include <GemCatalog/GemSortFilterProxyModel.h>
#include <TagWidget.h> #include <TagWidget.h>
#include <DownloadController.h>
#include <QFrame> #include <QFrame>
#include <QLabel> #include <DownloadController.h>
#include <QDialog>
#include <QMoveEvent>
#include <QHideEvent>
#include <QVBoxLayout>
#include <QAction>
#endif #endif
QT_FORWARD_DECLARE_CLASS(QPushButton)
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
QT_FORWARD_DECLARE_CLASS(QHBoxLayout)
QT_FORWARD_DECLARE_CLASS(QHideEvent)
QT_FORWARD_DECLARE_CLASS(QMoveEvent)
namespace O3DE::ProjectManager namespace O3DE::ProjectManager
{ {
class CartOverlayWidget class CartOverlayWidget
@ -87,12 +86,11 @@ namespace O3DE::ProjectManager
void ReinitForProject(); void ReinitForProject();
signals: signals:
void AddGem();
void OpenGemsRepo(); void OpenGemsRepo();
private: private:
AzQtComponents::SearchLineEdit* m_filterLineEdit = nullptr; AzQtComponents::SearchLineEdit* m_filterLineEdit = nullptr;
inline constexpr static int s_height = 60; inline constexpr static int s_height = 60;
QAction* m_openGemReposAction = nullptr;
}; };
} // namespace O3DE::ProjectManager } // namespace O3DE::ProjectManager

@ -19,6 +19,10 @@
#include <QTimer> #include <QTimer>
#include <PythonBindingsInterface.h> #include <PythonBindingsInterface.h>
#include <QMessageBox> #include <QMessageBox>
#include <QDir>
#include <QStandardPaths>
#include <QFileDialog>
#include <QMessageBox>
namespace O3DE::ProjectManager namespace O3DE::ProjectManager
{ {
@ -74,6 +78,7 @@ namespace O3DE::ProjectManager
void GemCatalogScreen::ReinitForProject(const QString& projectPath) void GemCatalogScreen::ReinitForProject(const QString& projectPath)
{ {
m_gemModel->clear(); m_gemModel->clear();
m_gemsToRegisterWithProject.clear();
FillModel(projectPath); FillModel(projectPath);
if (m_filterWidget) if (m_filterWidget)
@ -90,6 +95,47 @@ namespace O3DE::ProjectManager
connect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter); connect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter);
connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged); connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged);
connect(
m_headerWidget, &GemCatalogHeaderWidget::AddGem,
[&]()
{
EngineInfo engineInfo;
QString defaultPath;
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
if (engineInfoResult.IsSuccess())
{
engineInfo = engineInfoResult.GetValue();
defaultPath = engineInfo.m_defaultGemsFolder;
}
if (defaultPath.isEmpty())
{
defaultPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
}
QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Browse"), defaultPath));
if (!directory.isEmpty())
{
// register the gem to the o3de_manifest.json and to the project after the user confirms
// project creation/update
auto registerResult = PythonBindingsInterface::Get()->RegisterGem(directory);
if(!registerResult)
{
QMessageBox::critical(this, tr("Failed to add gem"), registerResult.GetError().c_str());
}
else
{
m_gemsToRegisterWithProject.insert(directory);
AZ::Outcome<GemInfo, void> gemInfoResult = PythonBindingsInterface::Get()->GetGemInfo(directory);
if (gemInfoResult)
{
m_gemModel->AddGem(gemInfoResult.GetValue<GemInfo>());
m_gemModel->UpdateGemDependencies();
}
}
}
});
// Select the first entry after everything got correctly sized // Select the first entry after everything got correctly sized
QTimer::singleShot(200, [=]{ QTimer::singleShot(200, [=]{
@ -251,6 +297,12 @@ namespace O3DE::ProjectManager
return EnableDisableGemsResult::Failed; return EnableDisableGemsResult::Failed;
} }
// register external gems that were added with relative paths
if (m_gemsToRegisterWithProject.contains(gemPath))
{
pythonBindings->RegisterGem(QDir(projectPath).relativeFilePath(gemPath), projectPath);
}
} }
for (const QModelIndex& modelIndex : toBeRemoved) for (const QModelIndex& modelIndex : toBeRemoved)

@ -18,6 +18,8 @@
#include <GemCatalog/GemInspector.h> #include <GemCatalog/GemInspector.h>
#include <GemCatalog/GemModel.h> #include <GemCatalog/GemModel.h>
#include <GemCatalog/GemSortFilterProxyModel.h> #include <GemCatalog/GemSortFilterProxyModel.h>
#include <QSet>
#include <QString>
#endif #endif
namespace O3DE::ProjectManager namespace O3DE::ProjectManager
@ -70,5 +72,6 @@ namespace O3DE::ProjectManager
GemFilterWidget* m_filterWidget = nullptr; GemFilterWidget* m_filterWidget = nullptr;
DownloadController* m_downloadController = nullptr; DownloadController* m_downloadController = nullptr;
bool m_notificationsEnabled = true; bool m_notificationsEnabled = true;
QSet<QString> m_gemsToRegisterWithProject;
}; };
} // namespace O3DE::ProjectManager } // namespace O3DE::ProjectManager

@ -556,6 +556,47 @@ namespace O3DE::ProjectManager
return AZ::Success(AZStd::move(gemNames)); return AZ::Success(AZStd::move(gemNames));
} }
AZ::Outcome<void, AZStd::string> PythonBindings::RegisterGem(const QString& gemPath, const QString& projectPath)
{
bool registrationResult = false;
auto result = ExecuteWithLockErrorHandling(
[&]
{
auto externalProjectPath = projectPath.isEmpty() ? pybind11::none() : QString_To_Py_Path(projectPath);
auto pythonRegistrationResult = m_register.attr("register")(
pybind11::none(), // engine_path
pybind11::none(), // project_path
QString_To_Py_Path(gemPath), // gem folder
pybind11::none(), // external subdirectory
pybind11::none(), // template_path
pybind11::none(), // restricted folder
pybind11::none(), // repo uri
pybind11::none(), // default_engines_folder
pybind11::none(), // default_projects_folder
pybind11::none(), // default_gems_folder
pybind11::none(), // default_templates_folder
pybind11::none(), // default_restricted_folder
pybind11::none(), // default_third_party_folder
pybind11::none(), // external_subdir_engine_path
externalProjectPath // external_subdir_project_path
);
// Returns an exit code so boolify it then invert result
registrationResult = !pythonRegistrationResult.cast<bool>();
});
if (!result.IsSuccess())
{
return AZ::Failure<AZStd::string>(result.GetError().c_str());
}
else if (!registrationResult)
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to register gem path %s", gemPath.toUtf8().constData()));
}
return AZ::Success();
}
bool PythonBindings::AddProject(const QString& path) bool PythonBindings::AddProject(const QString& path)
{ {
bool registrationResult = false; bool registrationResult = false;

@ -42,6 +42,7 @@ namespace O3DE::ProjectManager
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetEngineGemInfos() override; AZ::Outcome<QVector<GemInfo>, AZStd::string> GetEngineGemInfos() override;
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemInfos(const QString& projectPath) override; AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemInfos(const QString& projectPath) override;
AZ::Outcome<QVector<AZStd::string>, AZStd::string> GetEnabledGemNames(const QString& projectPath) override; AZ::Outcome<QVector<AZStd::string>, AZStd::string> GetEnabledGemNames(const QString& projectPath) override;
AZ::Outcome<void, AZStd::string> RegisterGem(const QString& gemPath, const QString& projectPath = {}) override;
// Project // Project
AZ::Outcome<ProjectInfo> CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) override; AZ::Outcome<ProjectInfo> CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) override;

@ -91,6 +91,14 @@ namespace O3DE::ProjectManager
*/ */
virtual AZ::Outcome<QVector<AZStd::string>, AZStd::string> GetEnabledGemNames(const QString& projectPath) = 0; virtual AZ::Outcome<QVector<AZStd::string>, AZStd::string> GetEnabledGemNames(const QString& projectPath) = 0;
/**
* Registers the gem to the specified project, or to the o3de_manifest.json if no project path is given
* @param gemPath the path to the gem
* @param projectPath the path to the project. If empty, will register the external path in o3de_manifest.json
* @return An outcome with the success flag as well as an error message in case of a failure.
*/
virtual AZ::Outcome<void, AZStd::string> RegisterGem(const QString& gemPath, const QString& projectPath = {}) = 0;
// Projects // Projects

@ -596,7 +596,7 @@ def register(engine_path: pathlib.Path = None,
:param default_third_party_folder: default 3rd party cache folder :param default_third_party_folder: default 3rd party cache folder
:param external_subdir_engine_path: Path to the engine to use when registering an external subdirectory. :param external_subdir_engine_path: Path to the engine to use when registering an external subdirectory.
The registration occurs in the engine.json file in this case The registration occurs in the engine.json file in this case
:param external_subdir_engine_path: Path to the project to use when registering an external subdirectory. :param external_subdir_project_path: Path to the project to use when registering an external subdirectory.
The registrations occurs in the project.json in this case The registrations occurs in the project.json in this case
:param remove: add/remove the entries :param remove: add/remove the entries
:param force: force update of the engine_path for specified "engine_name" from the engine.json file :param force: force update of the engine_path for specified "engine_name" from the engine.json file

Loading…
Cancel
Save