From 8b61760b679b0cd7554b36edc98347fc5d664d32 Mon Sep 17 00:00:00 2001
From: Naumann <uhxkb@student.kit.edu>
Date: Wed, 25 Oct 2023 14:54:54 +0200
Subject: [PATCH] Add support for linked global scenario configurations

---
 .../ScenarioManager/gui/OptionalEdit.cpp      |  7 --
 .../ScenarioManager/gui/OptionalEdit.h        |  1 -
 .../gui/detailedapplicationview.cpp           | 85 ++++++++++++++++---
 .../gui/detailedapplicationview.ui            | 73 ++++++++--------
 4 files changed, 108 insertions(+), 58 deletions(-)

diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/OptionalEdit.cpp b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/OptionalEdit.cpp
index 3e4a4cea..4bc25a49 100644
--- a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/OptionalEdit.cpp
+++ b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/OptionalEdit.cpp
@@ -80,8 +80,6 @@ OptionalEdit::OptionalEdit(const QString& elementName, const QString& propertyNa
     layout->addWidget(combo);
     layout->addWidget(readOnlyLineEdit);
 
-    this->isReadOnly = false;
-
     this->setLayout(layout);
 }
 
@@ -111,11 +109,6 @@ void OptionalEdit::setPropertyEnabled(const bool& enabled)
 
 void OptionalEdit::setReadOnly(bool readOnly)
 {
-    if (readOnly == this->isReadOnly)
-    {
-        return;
-    }
-
     checkbox->setDisabled(readOnly);
 
     combo->setVisible(not readOnly);
diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/OptionalEdit.h b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/OptionalEdit.h
index 2a4124f1..9480973f 100644
--- a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/OptionalEdit.h
+++ b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/OptionalEdit.h
@@ -86,7 +86,6 @@ namespace armarx
 
         QComboBox* combo = nullptr;
         QLineEdit* readOnlyLineEdit = nullptr;
-        bool isReadOnly;
 
         QCheckBox* checkbox = nullptr;
         QString elementName;
diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.cpp b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.cpp
index e62a0cf3..ac0e8a16 100644
--- a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.cpp
+++ b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.cpp
@@ -100,9 +100,9 @@ void DetailedApplicationView::init()
     void attributeChanged(QtProperty * property,
                           const QString & attribute, const QVariant & val);
 
-    ui->linkedApplicationLabel->setVisible(false);
+    ui->linkedInfoLabel->setVisible(false);
     ui->makeLocalButton->setVisible(false);
-    ui->addParameterButton->setVisible(false);
+    ui->addParameterButton->setEnabled(false);
     //QObject::connect(variantManager.get(), SIGNAL())
 }
 
@@ -229,9 +229,13 @@ void DetailedApplicationView::showApplicationInstance(ApplicationInstancePtr app
     }
 
     bool readOnly = appInstance->isReadOnly();
-    ui->linkedApplicationLabel->setVisible(readOnly);
+    ui->linkedInfoLabel->setVisible(readOnly);
+    ui->linkedInfoLabel->setText("Linked Application - read only");
+    ui->linkedInfoLabel->setToolTip(
+        "The application's config file is a link to another file, making it read only");
     ui->makeLocalButton->setVisible(readOnly);
-    ui->addParameterButton->setVisible(!readOnly);
+    ui->makeLocalButton->setToolTip("Replace the linked application with a local copy");
+    ui->addParameterButton->setEnabled(!readOnly);
 
     std::string label = appInstance->getName();
     if (readOnly)
@@ -275,7 +279,6 @@ void DetailedApplicationView::showApplicationInstance(ApplicationInstancePtr app
         ui->restartButton->setEnabled(false);
     }
 
-    ui->addParameterButton->setEnabled(true);
     ui->addParameterButton->setMenu(nullptr);
     ui->toolButton->setEnabled(true);
 
@@ -389,12 +392,14 @@ void DetailedApplicationView::showApplicationInstance(ApplicationInstancePtr app
 
     QtVariantProperty* nodePropertyItem = variantManager->addProperty(QVariant::String, "Node Name");
     nodePropertyItem->setValue(QString::fromStdString(appInstance->getNodeName()));
-    nodePropertyItem->setToolTip("Describes on which Node the currently Application should be deployed on");
+    nodePropertyItem->setToolTip("Describes on which Node the current Application should be deployed on");
+    nodePropertyItem->setAttribute(QLatin1String("readOnly"), QVariant(appInstance->isReadOnly()));
     appIcePropertyTopItem->addSubProperty(nodePropertyItem);
 
     QtVariantProperty* iceAutoRestartItem = variantManager->addProperty(QVariant::Bool, "Ice Auto Restart");
     iceAutoRestartItem->setValue(appInstance->getIceAutoRestart());
     iceAutoRestartItem->setToolTip("Describes if Ice should automatically restart this Application");
+    iceAutoRestartItem->setAttribute("enabled", QVariant(appInstance->isReadOnly()));
     appIcePropertyTopItem->addSubProperty(iceAutoRestartItem);
 
     ui->propertyBrowser->addProperty(appInstanceTopItem);
@@ -442,6 +447,36 @@ void DetailedApplicationView::showScenario(ScenarioPtr scenario)
     subMenu->addAction(addVariableToIceAction);
 
 
+    bool readOnly = scenario->isReadOnly();
+    ui->linkedInfoLabel->setVisible(readOnly);
+    ui->linkedInfoLabel->setText("Linked Scenario config - read only");
+    ui->linkedInfoLabel->setToolTip(
+        "The Secnario's global configuration is a link to another file, making it read only");
+    ui->makeLocalButton->setVisible(readOnly);
+    ui->makeLocalButton->setToolTip("Replace the linked global scenario configuration with a local copy. Does not alter any applications.");
+    ui->addParameterButton->setEnabled(!readOnly);
+
+    std::string label = scenario->getName();
+    if (readOnly)
+    {
+        auto [package, origScenario] = scenarioInfoFromLink(scenario->getGlobalConfigPath());
+        label += " -> " + origScenario;
+        std::string tooltip;
+        if (package == "unknown")
+        {
+            tooltip = "Could not determine original scenario for config '" +
+                      std::string(std::filesystem::canonical(scenario->getGlobalConfigPath())) + "'";
+        }
+        else
+        {
+            tooltip = "Original is in " +
+                      (package == "unknown" ? "unknown package" : "package " + package) +
+                      ", scenario " + origScenario;
+        }
+        ui->dataLabel->setToolTip(QString::fromStdString(tooltip));
+    }
+    ui->dataLabel->setText(QString::fromStdString(label));
+
     //ui->addParameterButton->setPopupMode(QToolButton::InstantPopup);
     ui->addParameterButton->setMenu(subMenu);
 
@@ -474,7 +509,6 @@ void DetailedApplicationView::showScenario(ScenarioPtr scenario)
     ui->startButton->setEnabled(true);
     ui->restartButton->setEnabled(true);
     ui->stopButton->setEnabled(true);
-    ui->addParameterButton->setEnabled(true);
     ui->toolButton->setEnabled(true);
 
     //build propertybrowser items
@@ -531,6 +565,8 @@ void DetailedApplicationView::showScenario(ScenarioPtr scenario)
             {
                 //nothing to do
             }
+
+            scenarioPropertyItem->setAttribute(QLatin1String("readOnly"), QVariant(scenario->isReadOnly()));
             scenarioPropertyTopItem->addSubProperty(scenarioPropertyItem);
         }
     }
@@ -539,14 +575,30 @@ void DetailedApplicationView::showScenario(ScenarioPtr scenario)
             QLatin1String("Scenario Ice Deployment Properties"));
     scenarioTopItem->addSubProperty(scenarioIcePropertyTopItem);
 
-    QtVariantProperty* scenarioDeploymentTypeItem = variantManager->addProperty(QtVariantPropertyManager::enumTypeId(), QString::fromStdString("Deployment Type"));
-    scenarioDeploymentTypeItem->setAttribute("enumNames", scenario->getScenarioDeploymentType() == ScenarioDeploymentType::Local ? QStringList({"Local", "Remote"}) : QStringList({"Remote", "Local"}));
+    QtVariantProperty* scenarioDeploymentTypeItem = nullptr;
+    if (readOnly)
+    {
+        scenarioDeploymentTypeItem = variantManager->addProperty(
+            QVariant::String,
+            QString::fromStdString("Deployment Type"));
+        scenarioDeploymentTypeItem->setValue(
+            scenario->getScenarioDeploymentType() == ScenarioDeploymentType::Local ? "Local" : "Remote");
+        scenarioDeploymentTypeItem->setAttribute(QLatin1String("readOnly"), QVariant(true));
+    }
+    else
+    {
+        scenarioDeploymentTypeItem = variantManager->addProperty(
+            QtVariantPropertyManager::enumTypeId(),
+            QString::fromStdString("Deployment Type"));
+        scenarioDeploymentTypeItem->setAttribute("enumNames", scenario->getScenarioDeploymentType() == ScenarioDeploymentType::Local ? QStringList({"Local", "Remote"}) : QStringList({"Remote", "Local"}));
+    }
     scenarioDeploymentTypeItem->setToolTip("Describes if the Scenario should either use the Local build for Ice deployment or an Remote sync directory");
     scenarioIcePropertyTopItem->addSubProperty(scenarioDeploymentTypeItem);
 
     QtVariantProperty* nodePropertyItem = variantManager->addProperty(QVariant::String, "Node Name");
     nodePropertyItem->setValue(QString::fromStdString(scenario->getNodeName()));
     nodePropertyItem->setToolTip("Describes on which Node the currently applications of the current scenario should be deployed on. Can be overwritten for each application.");
+    nodePropertyItem->setAttribute(QLatin1String("readOnly"), QVariant(scenario->isReadOnly()));
     scenarioIcePropertyTopItem->addSubProperty(nodePropertyItem);
 
 
@@ -558,6 +610,7 @@ void DetailedApplicationView::showScenario(ScenarioPtr scenario)
     {
         QtVariantProperty* iceEnvVarItem = variantManager->addProperty(QVariant::String, QString::fromStdString(envVar.first));
         iceEnvVarItem->setValue(QString::fromStdString(envVar.second));
+        iceEnvVarItem->setAttribute(QLatin1String("readOnly"), QVariant(scenario->isReadOnly()));
         scenarioIceEnvVarsTopItem->addSubProperty(iceEnvVarItem);
     }
 
@@ -583,6 +636,8 @@ void DetailedApplicationView::showPackage(PackagePtr package)
         ui->restartButton->setEnabled(false);
         ui->addParameterButton->setEnabled(false);
         ui->toolButton->setEnabled(false);
+        ui->linkedInfoLabel->setVisible(false);
+        ui->makeLocalButton->setVisible(false);
 
         lastAppInstance = ApplicationInstancePtr(nullptr);
         lastScenario = ScenarioPtr(nullptr);
@@ -991,11 +1046,15 @@ void DetailedApplicationView::on_reloadButton_clicked()
 
 void DetailedApplicationView::on_makeLocalButton_clicked()
 {
-    if (!lastAppInstance)
+    if (lastAppInstance)
     {
-        return;
+        lastAppInstance->makeLocal();
+        showApplicationInstance(lastAppInstance, nullptr);
+    }
+    else if (lastScenario)
+    {
+        lastScenario->makeLocalGlobalConfig();
+        showScenario(lastScenario);
     }
-    lastAppInstance->makeLocal();
-    showApplicationInstance(lastAppInstance, nullptr);
 }
 
diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.ui b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.ui
index 56c02ab7..c3ceac93 100644
--- a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.ui
+++ b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.ui
@@ -127,7 +127,40 @@
           </widget>
          </item>
          <item>
-          <widget class="QLabel" name="linkedApplicationLabel">
+          <widget class="QToolButton" name="addParameterButton">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="toolTip">
+            <string>Add Property</string>
+           </property>
+           <property name="text">
+            <string>Add property</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../../../libraries/ArmarXGuiBase/armarxicons.qrc">
+             <normaloff>:/icons/edit-add.ico</normaloff>:/icons/edit-add.ico</iconset>
+           </property>
+           <property name="toolButtonStyle">
+            <enum>Qt::ToolButtonTextBesideIcon</enum>
+           </property>
+           <property name="autoRaise">
+            <bool>false</bool>
+           </property>
+           <property name="arrowType">
+            <enum>Qt::NoArrow</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_5">
+         <item>
+          <widget class="QLabel" name="linkedInfoLabel">
            <property name="sizePolicy">
             <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
              <horstretch>0</horstretch>
@@ -172,7 +205,7 @@
             </palette>
            </property>
            <property name="text">
-            <string>Linked Application - read only</string>
+            <string>Linked &lt;&gt; - read only</string>
            </property>
            <property name="alignment">
             <set>Qt::AlignCenter</set>
@@ -194,41 +227,7 @@
             <string>Unlink the application with the current configuration</string>
            </property>
            <property name="text">
-            <string>Make local</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QToolButton" name="addParameterButton">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="font">
-            <font>
-             <pointsize>9</pointsize>
-            </font>
-           </property>
-           <property name="toolTip">
-            <string>Add Property</string>
-           </property>
-           <property name="text">
-            <string>Add property</string>
-           </property>
-           <property name="icon">
-            <iconset resource="../../../libraries/ArmarXGuiBase/armarxicons.qrc">
-             <normaloff>:/icons/edit-add.ico</normaloff>:/icons/edit-add.ico</iconset>
-           </property>
-           <property name="toolButtonStyle">
-            <enum>Qt::ToolButtonTextBesideIcon</enum>
-           </property>
-           <property name="autoRaise">
-            <bool>false</bool>
-           </property>
-           <property name="arrowType">
-            <enum>Qt::NoArrow</enum>
+            <string>Unlink</string>
            </property>
           </widget>
          </item>
-- 
GitLab