瀏覽代碼

edit gem workflow is now operational

Signed-off-by: T.J. Kotha <[email protected]>
T.J. Kotha 2 年之前
父節點
當前提交
816804b6d3

+ 27 - 7
Code/Tools/ProjectManager/Source/CreateAGemScreen.cpp

@@ -510,7 +510,27 @@ namespace O3DE::ProjectManager
 
                 if (m_isEditGem)
                 {
-                    //TODO: create new edit route
+                    //during editing, we remove the gem name tag to prevent the user accidentally altering it
+                    //so add it back here before submission
+                    if(!m_createGemInfo.m_features.contains(m_createGemInfo.m_name))
+                    {
+                        m_createGemInfo.m_features << m_createGemInfo.m_name;
+                    }
+
+                    auto result = PythonBindingsInterface::Get()->EditGem(m_oldGemInfo, m_createGemInfo);
+                    if(result.IsSuccess())
+                    {
+                        ClearWorkflow();
+                        emit GemEdited(result.GetValue<GemInfo>());
+                        emit GoToPreviousScreenRequest();
+                    }
+                    else
+                    {
+                        QMessageBox::critical(
+                            this,
+                            tr("Failed to edit gem"),
+                            tr("The gem failed to be edited"));
+                    }
                 }
                 else
                 {
@@ -576,7 +596,6 @@ namespace O3DE::ProjectManager
 
     void CreateGem::ChangeToCreateWorkflow()
     {
-        //TODO: revert to create gem UI
         m_header->setSubTitle(tr("Create a new gem"));
 
         //we ensure that we are using all pages
@@ -622,7 +641,11 @@ namespace O3DE::ProjectManager
         m_gemLocation->setErrorLabelVisible(false);
 
         m_gemIconPath->lineEdit()->setText(oldGemInfo.m_iconPath);
-        m_userDefinedGemTags->setTags(oldGemInfo.m_features);
+
+        //before settings the tags field, find a tag that includes the gem name, and remove it
+        QStringList tagsToEdit = oldGemInfo.m_features;
+        tagsToEdit.removeAll(oldGemInfo.m_name);
+        m_userDefinedGemTags->setTags(tagsToEdit);
 
         //creator details page
         m_origin->lineEdit()->setText(oldGemInfo.m_origin);
@@ -636,14 +659,12 @@ namespace O3DE::ProjectManager
         if(isEditWorkflow)
         {
             ChangeToEditWorkflow();
+            m_oldGemInfo = oldGemInfo;
         }
-        
-        //this will be ported over to a new EditGem class. There are a lot of subtle details, like removing the template selection, pre-filling gem values like type, and disabling folder editing, that are better handled on a separate class.
     }
 
     void CreateGem::ChangeToEditWorkflow()
     {
-        //TODO: change to the edit gem UI
         m_header->setSubTitle(tr("Edit gem"));
 
         //we will only have two pages: details page and creator details page
@@ -664,7 +685,6 @@ namespace O3DE::ProjectManager
 
         //there exists an edge case where backing out from an old create gem workflow fails to update next button title
         m_nextButton->setText(tr("Next"));
-
     }
 
 } // namespace O3DE::ProjectManager

+ 2 - 0
Code/Tools/ProjectManager/Source/CreateAGemScreen.h

@@ -41,6 +41,7 @@ namespace O3DE::ProjectManager
 
     signals:
         void GemCreated(const GemInfo& gemInfo);
+        void GemEdited(const GemInfo& newGemInfo);
 
     private slots:
         void HandleBackButton();
@@ -69,6 +70,7 @@ namespace O3DE::ProjectManager
 
         //Edit Gem workflow
         bool m_isEditGem = false;
+        GemInfo m_oldGemInfo;
 
         //Gem Setup
         QVector<TemplateInfo> m_gemTemplates;

+ 18 - 1
Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp

@@ -80,7 +80,9 @@ namespace O3DE::ProjectManager
             ScreenWidget* createGemScreen = m_screensControl->FindScreen(ProjectManagerScreen::CreateGem);
             if (createGemScreen)
             {
-                connect(static_cast<CreateGem*>(createGemScreen), &CreateGem::GemCreated, this, &GemCatalogScreen::HandleGemCreated);
+                CreateGem* createGem = static_cast<CreateGem*>(createGemScreen);
+                connect(createGem, &CreateGem::GemCreated, this, &GemCatalogScreen::HandleGemCreated);
+                connect(createGem, &CreateGem::GemEdited, this, &GemCatalogScreen::HandleGemEdited);
             }
         }
 
@@ -738,6 +740,21 @@ namespace O3DE::ProjectManager
         ShowStandardToastNotification(notification);
     }
 
+    void GemCatalogScreen::HandleGemEdited(const GemInfo& newGemInfo)
+    {
+        // This signal only occurs upon successful completion of editing a gem. As such, the gemInfo is assumed to be valid
+
+        // make sure to update the current model index in the gem catalog model
+        m_gemModel->RemoveGem(m_gemInspector->GetCurrentModelIndex());
+        m_gemModel->AddGem(newGemInfo);
+
+        //gem inspector needs to have its selection updated to the newly added gem
+        SelectGem(newGemInfo.m_name);
+
+        QString notification = tr("%1 was edited.").arg(newGemInfo.m_displayName);
+        ShowStandardToastNotification(notification);
+    }
+
     ProjectManagerScreen GemCatalogScreen::GetScreenEnum()
     {
         return ProjectManagerScreen::GemCatalog;

+ 1 - 0
Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h

@@ -62,6 +62,7 @@ namespace O3DE::ProjectManager
         void UpdateGem(const QModelIndex& modelIndex);
         void UninstallGem(const QModelIndex& modelIndex);
         void HandleGemCreated(const GemInfo& gemInfo);
+        void HandleGemEdited(const GemInfo& newGemInfo);
 
     protected:
         void hideEvent(QHideEvent* event) override;

+ 69 - 0
Code/Tools/ProjectManager/Source/PythonBindings.cpp

@@ -320,6 +320,7 @@ namespace O3DE::ProjectManager
             m_register = pybind11::module::import("o3de.register");
             m_manifest = pybind11::module::import("o3de.manifest");
             m_engineTemplate = pybind11::module::import("o3de.engine_template");
+            m_gemProperties = pybind11::module::import("o3de.gem_properties");
             m_engineProperties = pybind11::module::import("o3de.engine_properties");
             m_enableGemProject = pybind11::module::import("o3de.enable_gem");
             m_disableGemProject = pybind11::module::import("o3de.disable_gem");
@@ -884,6 +885,74 @@ namespace O3DE::ProjectManager
         }
     }
 
+    AZ::Outcome<GemInfo> PythonBindings::EditGem(const GemInfo& oldGemInfo, const GemInfo& newGemInfo)
+    {
+        using namespace pybind11::literals;
+
+        QStringList newList;
+
+        for(auto feature : newGemInfo.m_features)
+        {
+            if(!oldGemInfo.m_features.contains(feature))
+            {
+                //this must have been added by the user
+                newList << feature;
+            }
+        }
+
+        QStringList removeList;
+
+        for (auto feature : oldGemInfo.m_features)
+        {
+            if(!newGemInfo.m_features.contains(feature))
+            {
+                //this must have been removed by the user
+                removeList << feature;
+            }
+        }
+
+        GemInfo gemInfoResult;
+        bool result = ExecuteWithLock(
+            [&]
+            {
+                auto gemPath = QString_To_Py_Path(oldGemInfo.m_path);
+
+                auto editGemResult = m_gemProperties.attr("edit_gem_props")(
+                    "gem_path"_a = gemPath,
+                    "gem_name"_a = QString_To_Py_String(oldGemInfo.m_name),
+                    "new_name"_a = QString_To_Py_String(newGemInfo.m_name),
+                    "new_display"_a = QString_To_Py_String(newGemInfo.m_displayName),
+                    "new_origin"_a = QString_To_Py_String(newGemInfo.m_origin),
+                    "new_type"_a = pybind11::none(), //For the Project manager, it does not make sense to change the type of a gem once it's created
+                    "new_summary"_a = QString_To_Py_String(newGemInfo.m_summary),
+                    "new_icon"_a = QString_To_Py_String(newGemInfo.m_iconPath),
+                    "new_requirements"_a = QString_To_Py_String(newGemInfo.m_requirement),
+                    "new_documentation_url"_a = QString_To_Py_String(newGemInfo.m_documentationLink),
+                    "new_license"_a = QString_To_Py_String(newGemInfo.m_licenseText),
+                    "new_license_url"_a = QString_To_Py_String(newGemInfo.m_licenseLink),
+                    "new_tags"_a = QString_To_Py_String(newList.join(" ")),  //the python code seems to interpret these lists as space separated
+                    "remove_tags"_a = QString_To_Py_String(removeList.join(" ")),
+                    "replace_tags"_a = pybind11::none())
+                    ;
+                
+                if (editGemResult.cast<int>() == 0)
+                {
+                    gemInfoResult = GemInfoFromPath(gemPath, pybind11::none());
+                }
+            });
+        
+        if(!result || !gemInfoResult.IsValid())
+        {
+            return AZ::Failure();
+        }
+        else
+        {
+            //Make sure directory link is a normalized path that can be rendered in "View Directory" dialog
+            gemInfoResult.m_directoryLink = QDir::cleanPath(gemInfoResult.m_directoryLink);
+            return AZ::Success(AZStd::move(gemInfoResult));
+        }
+    }
+
     AZ::Outcome<ProjectInfo> PythonBindings::GetProject(const QString& path)
     {
         ProjectInfo projectInfo = ProjectInfoFromPath(QString_To_Py_Path(path));

+ 2 - 0
Code/Tools/ProjectManager/Source/PythonBindings.h

@@ -45,6 +45,7 @@ namespace O3DE::ProjectManager
 
         // Gem
         AZ::Outcome<GemInfo> CreateGem(const QString& templatePath, const GemInfo& gemInfo, bool registerGem = true) override;
+        AZ::Outcome<GemInfo> EditGem(const GemInfo& oldGemInfo, const GemInfo& newGemInfo) override;
         AZ::Outcome<GemInfo> GetGemInfo(const QString& path, const QString& projectPath = {}) override;
         AZ::Outcome<QVector<GemInfo>, AZStd::string> GetEngineGemInfos() override;
         AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemInfos(const QString& projectPath) override;
@@ -114,6 +115,7 @@ namespace O3DE::ProjectManager
         AZ::IO::FixedMaxPath m_enginePath;
         mutable AZStd::recursive_mutex m_lock;
 
+        pybind11::handle m_gemProperties;
         pybind11::handle m_engineTemplate;
         pybind11::handle m_engineProperties;
         pybind11::handle m_cmake;

+ 8 - 0
Code/Tools/ProjectManager/Source/PythonBindingsInterface.h

@@ -108,6 +108,14 @@ namespace O3DE::ProjectManager
          */
         virtual AZ::Outcome<GemInfo> CreateGem(const QString& templatePath, const GemInfo& gemInfo, bool registerGem = true) = 0;
 
+        /**
+         * Edit a Gem from the Edit Gem Wizard
+         * @param oldGemInfo the gem info that existed prior to the update request
+         * @param newGemInfo the gem updates that the user is requesting
+         * @return an outcome with GemInfo on success
+         */
+         virtual AZ::Outcome<GemInfo> EditGem(const GemInfo& oldGemInfo, const GemInfo& newGemInfo) = 0;
+
         /**
          * Get info about a Gem.
          * @param path The absolute path to the Gem