From dc67ff595ff947920b5005401d509443f3a5f2fe Mon Sep 17 00:00:00 2001
From: Peter Albrecht <albrecpe@gmail.com>
Date: Thu, 14 Dec 2023 15:21:05 +0100
Subject: [PATCH] Implemented update for execution tree

---
 .../libraries/skills_gui/CMakeLists.txt       |   2 +
 .../executions/SkillExecutionTreeWidget.cpp   | 106 ++++++------------
 .../executions/SkillExecutionTreeWidget.h     |  12 ++
 .../SkillExecutionTreeWidgetItem.cpp          |  30 +++++
 .../executions/SkillExecutionTreeWidgetItem.h |   7 +-
 .../skills_gui/skills/SkillTreeWidgetItem.cpp |   6 +
 .../skills_gui/skills/SkillTreeWidgetItem.h   |  10 ++
 7 files changed, 95 insertions(+), 78 deletions(-)
 create mode 100644 source/RobotAPI/libraries/skills_gui/skills/SkillTreeWidgetItem.cpp
 create mode 100644 source/RobotAPI/libraries/skills_gui/skills/SkillTreeWidgetItem.h

diff --git a/source/RobotAPI/libraries/skills_gui/CMakeLists.txt b/source/RobotAPI/libraries/skills_gui/CMakeLists.txt
index 8470d46ab..f3564c12f 100644
--- a/source/RobotAPI/libraries/skills_gui/CMakeLists.txt
+++ b/source/RobotAPI/libraries/skills_gui/CMakeLists.txt
@@ -56,6 +56,7 @@ set(SOURCES
 
     skills/SkillTreeWidget.cpp
     skills/SkillGroupBox.cpp
+    skills/SkillTreeWidgetItem.cpp
 
     skill_details/SkillDetailsGroupBox.cpp
     skill_details/ProfileMenuWidget.cpp
@@ -97,6 +98,7 @@ set(HEADERS
 
     skills/SkillTreeWidget.h
     skills/SkillGroupBox.h
+    skills/SkillTreeWidgetItem
 
     skill_details/SkillDetailsGroupBox.h
     skill_details/ProfileMenuWidget.h
diff --git a/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidget.cpp b/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidget.cpp
index 8e53e9708..f1be93266 100644
--- a/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidget.cpp
+++ b/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidget.cpp
@@ -1,6 +1,11 @@
 #include "SkillExecutionTreeWidget.h"
 
+#include <mutex>
+
 #include <QMenu>
+#include <QTreeWidgetItem>
+
+#include "SkillExecutionTreeWidgetItem.h"
 
 namespace armarx::skills::gui
 {
@@ -43,101 +48,56 @@ namespace armarx::skills::gui
         memory->stopExecution(this->selectedExecution.skillExecutionId);
     }
 
-    /*
     void
     SkillExecutionTreeWidget::refresh()
     {
+        auto currentManagerStatuses = memory->getLatestUpdate().statuses;
 
-
-        SkillManagerWrapper::Snapshot snapshot = memory->getLatestSnapshot();
-
-        // update tree view. Remove non-existing elements
-        int i = 0;
-        while (i < this->topLevelItemCount())
+        for (const auto& [k, v] : currentManagerStatuses)
         {
-            auto* providerItem = this->topLevelItem(i);
-            auto providerName = providerItem->text(0).toStdString();
-            snapshot.skills::ProviderID providerId{.providerName = providerName};
-
-            if (snapshot.skills.find(providerId) == snapshot.skills.end())
-            {
-                providerItem = nullptr; // reset
-                auto remove = this->takeTopLevelItem(i);
-                delete remove;
-                continue;
-            }
+            skills::SkillExecutionID executionId = k;
+            skills::SkillStatusUpdate statusUpdate = v;
 
-            ++i;
-            auto& providedSkills = snapshot.skills.at(providerId);
-
-            int j = 0;
-            while (j < providerItem->childCount())
+            SkillExecutionTreeWidgetItem* found = nullptr;
+            for (int i = 0; i < this->topLevelItemCount(); ++i)
             {
-                auto* skillItem = providerItem->child(j);
-                auto skillName = skillItem->text(0).toStdString();
+                auto c = static_cast<SkillExecutionTreeWidgetItem*>(topLevelItem(i));
 
-                skills::SkillID skillId{
-                    .providerId = snapshot.skills::ProviderID{.providerName = providerName},
-                    .skillName = skillName};
+                found = SkillExecutionTreeWidgetItem::SearchRecursiveForMatch(c, executionId);
 
-                if (providedSkills.find(skillId) == providedSkills.end())
+                if (found)
                 {
-                    skillItem = nullptr;
-                    auto remove = providerItem->takeChild(j);
-                    delete remove;
-                    continue;
-                }
-
-                ++j;
-            }
-        }
-
-        // update tree view. Add new elements
-        for (const auto& [providerId, providedSkills] : snapshot.skills)
-        {
-            QTreeWidgetItem* providerItem = nullptr;
-            for (int i = 0; i < this->topLevelItemCount(); ++i)
-            {
-                auto el = this->topLevelItem(i);
-                auto providerName = el->text(0).toStdString();
-                skills::ProviderID elProviderId{.providerName = providerName};
+                    for (std::pair<skills::SkillStatus, std::string> i : EXECUTION_STATUS_TO_STRING)
+                    {
+                        if (i.first == statusUpdate.status)
+                        {
+                            found->setText(3, QString::fromStdString(i.second));
+                        }
+                    }
 
-                if (providerId == elProviderId)
-                {
-                    providerItem = el;
                     break;
                 }
             }
 
-            if (!providerItem)
+            if (!found)
             {
-                providerItem = new QTreeWidgetItem(this);
-                providerItem->setText(0, QString::fromStdString(providerId.providerName));
-            }
-
-            for (const auto& [skillId, skill] : providedSkills)
-            {
-                QTreeWidgetItem* skillItem = nullptr;
-                for (int i = 0; i < providerItem->childCount(); ++i)
+                // TODO: Sort to executor!
+                auto item = new SkillExecutionTreeWidgetItem(executionId, memory);
+
+                item->setText(
+                    0, QString::fromStdString(executionId.executionStartedTime.toDateTimeString()));
+                item->setText(1, QString::fromStdString(executionId.executorName));
+                item->setText(2, QString::fromStdString(executionId.skillId.toString()));
+                for (std::pair<skills::SkillStatus, std::string> i : EXECUTION_STATUS_TO_STRING)
                 {
-                    auto el = providerItem->child(i);
-                    auto skillName = el->text(0).toStdString();
-                    skills::SkillID elSkillId{providerId, skillName};
-
-                    if (skillId == elSkillId)
+                    if (i.first == statusUpdate.status)
                     {
-                        skillItem = el;
-                        break;
+                        item->setText(3, QString::fromStdString(i.second));
                     }
                 }
 
-                if (!skillItem)
-                {
-                    skillItem = new SkillInfoTreeWidgetItem(skill, providerItem);
-                    skillItem->setText(0, QString::fromStdString(skillId.skillName));
-                }
+                this->insertTopLevelItem(0, item);
             }
         }
     }
-*/
 } // namespace armarx::skills::gui
diff --git a/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidget.h b/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidget.h
index 2dc6b8a3f..211538c64 100644
--- a/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidget.h
+++ b/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidget.h
@@ -10,6 +10,18 @@
 namespace armarx::skills::gui
 {
 
+    static const std::map<skills::SkillStatus, std::string> EXECUTION_STATUS_TO_STRING = {
+        // Main states
+        {skills::SkillStatus::Constructing, "Constructing"},
+        {skills::SkillStatus::Initializing, "Initializing"},
+        {skills::SkillStatus::Preparing, "Preparing"},
+        {skills::SkillStatus::Running, "Running"},
+
+        // Terminating
+        {skills::SkillStatus::Aborted, "Aborted"},
+        {skills::SkillStatus::Failed, "Failed"},
+        {skills::SkillStatus::Succeeded, "Succeeded"}};
+
     class SkillExecutionTreeWidget : public QTreeWidget, public MemoryCommunicatorBase
     {
     public:
diff --git a/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidgetItem.cpp b/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidgetItem.cpp
index 727a82168..735042b14 100644
--- a/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidgetItem.cpp
+++ b/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidgetItem.cpp
@@ -1 +1,31 @@
 #include "SkillExecutionTreeWidgetItem.h"
+
+namespace armarx::skills::gui
+{
+    SkillExecutionTreeWidgetItem*
+    SkillExecutionTreeWidgetItem::SearchRecursiveForMatch(SkillExecutionTreeWidgetItem* haystack,
+                                                          const SkillExecutionID& needle)
+    {
+        if (!haystack)
+        {
+            return nullptr;
+        }
+
+        if (needle == haystack->executionId)
+        {
+            return haystack;
+        }
+        for (int i = 0; i < haystack->childCount(); ++i)
+        {
+            auto el = dynamic_cast<SkillExecutionTreeWidgetItem*>(haystack->child(i));
+            if (!el)
+            {
+                // Dynamic casting failed. Skip element...
+                // We assume, that only this type can contain children in the tree.
+                continue;
+            }
+            return SkillExecutionTreeWidgetItem::SearchRecursiveForMatch(el, needle);
+        }
+        return nullptr;
+    }
+} // namespace armarx::skills::gui
diff --git a/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidgetItem.h b/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidgetItem.h
index 35b133f79..18afc6356 100644
--- a/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidgetItem.h
+++ b/source/RobotAPI/libraries/skills_gui/executions/SkillExecutionTreeWidgetItem.h
@@ -11,7 +11,7 @@
 
 namespace armarx::skills::gui
 {
-    class SkillExecutionTreeWidgetItem : QTreeWidgetItem, public MemoryCommunicatorBase
+    class SkillExecutionTreeWidgetItem : public QTreeWidgetItem, public MemoryCommunicatorBase
     {
     public:
         SkillExecutionTreeWidgetItem() = delete;
@@ -24,15 +24,12 @@ namespace armarx::skills::gui
         }
 
         static SkillExecutionTreeWidgetItem*
-        SearchRecursiveForMatch(SkillExecutionTreeWidgetItem* el,
+        SearchRecursiveForMatch(SkillExecutionTreeWidgetItem* haystack,
                                 const skills::SkillExecutionID& needle);
 
         skills::SkillExecutionID getExecutionID();
         void updateItem(skills::SkillStatus status);
 
-    private slots:
-        void runContextMenu(const QPoint& pos);
-
     protected:
         skills::SkillExecutionID executionId;
 
diff --git a/source/RobotAPI/libraries/skills_gui/skills/SkillTreeWidgetItem.cpp b/source/RobotAPI/libraries/skills_gui/skills/SkillTreeWidgetItem.cpp
new file mode 100644
index 000000000..235461cfc
--- /dev/null
+++ b/source/RobotAPI/libraries/skills_gui/skills/SkillTreeWidgetItem.cpp
@@ -0,0 +1,6 @@
+#include "SkillTreeWidgetItem.h"
+
+SkillTreeWidgetItem::SkillTreeWidgetItem()
+{
+
+}
diff --git a/source/RobotAPI/libraries/skills_gui/skills/SkillTreeWidgetItem.h b/source/RobotAPI/libraries/skills_gui/skills/SkillTreeWidgetItem.h
new file mode 100644
index 000000000..d56c906bb
--- /dev/null
+++ b/source/RobotAPI/libraries/skills_gui/skills/SkillTreeWidgetItem.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <QTreeWidgetItem>
+
+class SkillTreeWidgetItem : public QTreeWidgetItem
+{
+public:
+    SkillTreeWidgetItem();
+};
+
-- 
GitLab