From 7e2d37c5b16fed7022c793abfd5742c99f756c25 Mon Sep 17 00:00:00 2001
From: tobiglaser <76131623+tobiglaser@users.noreply.github.com>
Date: Tue, 10 Jun 2025 19:46:49 +0200
Subject: [PATCH] added local setup functionality

---
 examples/studiMain.cpp | 13 +++++++++--
 include/cute.h         |  2 +-
 src/configPanel.cpp    |  9 ++++++++
 src/configPanel.h      |  2 ++
 src/control.cpp        | 49 ++++++++++++++++++++++++++++++++++++++----
 src/control.h          | 15 +++++++++++--
 src/cute.cpp           |  4 ++--
 7 files changed, 83 insertions(+), 11 deletions(-)

diff --git a/examples/studiMain.cpp b/examples/studiMain.cpp
index cdbf72c..9040968 100644
--- a/examples/studiMain.cpp
+++ b/examples/studiMain.cpp
@@ -5,6 +5,15 @@ void superDummy();
 void advancedDummy();
 void bubblesort();
 
+void setup1()
+{
+    cute::logMessage("1");
+}
+void setup2()
+{
+    cute::logMessage("2");
+}
+
 // Is run once at startup.
 void setup()
 {
@@ -18,8 +27,8 @@ void setup()
     cute::setProgress(69);
     cute::setPlotVisible(1);
     cute::setStatusMessage("Hallo TEC");
-    cute::registerAlgorithm(superDummy, "DummyAlgo");
-    cute::registerAlgorithm(advancedDummy, "Problem");
+    cute::registerAlgorithm(superDummy, "DummyAlgo", setup1);
+    cute::registerAlgorithm(advancedDummy, "Problem", setup2);
     cute::registerAlgorithm(bubblesort, "Bubblesort");
     cute::setProblemFile("example.csv");
     cute::setProblemSize(4);
diff --git a/include/cute.h b/include/cute.h
index 5e21906..64151fd 100644
--- a/include/cute.h
+++ b/include/cute.h
@@ -113,7 +113,7 @@ namespace cute
     void DYNAMIC setAxisTitles(int plot, const std::string& x, const std::string& y);
     void DYNAMIC setAxisVisible(int plot, bool x, bool y);
 
-    void DYNAMIC registerAlgorithm(void (*func)(), const std::string& name);
+    void DYNAMIC registerAlgorithm(void (*func)(), const std::string& name, void (*localSetup)() = nullptr);
 
     void DYNAMIC plotPoint(const Point&          point,
                            int                   plot       = 0,
diff --git a/src/configPanel.cpp b/src/configPanel.cpp
index 98c1da5..22e1f34 100644
--- a/src/configPanel.cpp
+++ b/src/configPanel.cpp
@@ -33,6 +33,9 @@ ConfigPanel::ConfigPanel(QWidget* parent) : QDockWidget{parent}
     verbosityBox->setCurrentIndex(4);
     runButton = new QPushButton("Start");
     f->layout()->addWidget(runButton);
+    setupButton = new QPushButton("Setup");
+    f->layout()->addWidget(setupButton);
+    setupButton->setVisible(false);
 
 
     fileWidget = new QWidget();
@@ -139,6 +142,12 @@ void ConfigPanel::setGenUnlocked()
     pasteBox->setDisabled(false);
 }
 
+void ConfigPanel::switchButtons(bool setup)
+{
+    runButton->setVisible(!setup);
+    setupButton->setVisible(setup);
+}
+
 void ConfigPanel::onOpenButton()
 {
     QString filter = "CSV Files (*.csv)";
diff --git a/src/configPanel.h b/src/configPanel.h
index 2ce74a3..30b568d 100644
--- a/src/configPanel.h
+++ b/src/configPanel.h
@@ -22,6 +22,7 @@ private:
 
 public:
     QPushButton*    runButton;      ///< Used to Start and Stop the Algorithm.
+    QPushButton*    setupButton;    ///< Used to run the localSetup function of the Algorithm.
     QPushButton*    openButton;     ///< Used to Select a File via QFileDialog.
     QLineEdit*      fileLine;       ///< Shows path and filename and allows editing it.
     QPlainTextEdit* pasteBox;       ///< Used to enter csv data via drag n drop or copy and paste.
@@ -43,6 +44,7 @@ public slots:
     void setRunning(bool running);
     void setGenLocked();
     void setGenUnlocked();
+    void switchButtons(bool setup);
 
 signals:
     void previewButtonClicked(); ///< Signal emitted, when one of the Preview Buttons was clicked.
diff --git a/src/control.cpp b/src/control.cpp
index a307fda..9dc3d59 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -49,6 +49,9 @@ void Control::makeConnections()
     connect(cc, &CuteControl::s_undo, this, &Control::undo);
     connect(this, &Control::endThread, cc, &CuteControl::end);
     connect(w->configPanel->runButton, &QPushButton::clicked, this, &Control::onRunButton);
+    connect(w->configPanel->setupButton, &QPushButton::clicked, this, &Control::onSetupButton);
+    connect(
+        w->configPanel->algoBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Control::onAlgoSelected);
     connect(w->configPanel, &ConfigPanel::previewButtonClicked, this, &Control::onPreviewButton);
     connect(w->configPanel, &ConfigPanel::lockButtonClicked, this, &Control::onLockButton);
     connect(w, &MainWindow::saveProblem, this, &Control::saveProblem);
@@ -91,7 +94,15 @@ int Control::run(void (*userSetup)())
         userSetup();
         w->show();
         if (autorun)
-            startThread(algorithms.front().first);
+        {
+            if (algorithms.front().localSetup != nullptr)
+            {
+                algorithms.front().localSetup();
+                lastAlgorithmRun = algorithms.front();
+                w->configPanel->switchButtons(false);
+            }
+            startThread(algorithms.front().algorithm);
+        }
         int result = a.exec();
         running    = false;
         return result;
@@ -283,9 +294,9 @@ void Control::setAxisVisible(int plot, bool x, bool y)
  * @param func The function pointer to be called by the AlgoThread.
  * @param name The name to be displayed in the ConfigPanels QCombobox algoBox.
  */
-void Control::registerAlgorithm(void (*func)(), const QString name)
+void Control::registerAlgorithm(void (*func)(), const QString name, void (*setup)())
 {
-    algorithms.emplace_back(func, name);
+    algorithms.push_back({func, setup, name});
     w->addAlgorithm(name);
 }
 
@@ -355,7 +366,7 @@ void Control::onRunButton()
     if (!thread)
     {
         int  index = w->configPanel->algoBox->currentIndex();
-        auto func  = algorithms[index].first;
+        auto func  = algorithms[index].algorithm;
         startThread(func);
     }
     else
@@ -364,6 +375,36 @@ void Control::onRunButton()
     }
 }
 
+void Control::onSetupButton()
+{
+    int  index = w->configPanel->algoBox->currentIndex();
+    auto setup = algorithms[index].localSetup;
+    if (setup != nullptr)
+    {
+        setup();
+        lastAlgorithmRun = algorithms[index];
+        w->configPanel->switchButtons(false);
+    }
+}
+
+/**
+ * @brief
+ * @param index
+ * @todo the current index changes on construction, so this gets called.
+ */
+void Control::onAlgoSelected(int index)
+{
+    auto setup = algorithms[index].localSetup;
+    if (setup != lastAlgorithmRun.localSetup && setup != nullptr)
+    {
+        w->configPanel->switchButtons(true);
+    }
+    else
+    {
+        w->configPanel->switchButtons(false);
+    }
+}
+
 /**
  * @brief Change the problem widget stack to random generation and set the given size.
  * The setProblem functions only manipulate the entries in the View.abort
diff --git a/src/control.h b/src/control.h
index 3e9027b..c40ae68 100644
--- a/src/control.h
+++ b/src/control.h
@@ -12,13 +12,22 @@
 class Control : public QObject
 {
     Q_OBJECT
+private:
+    struct Algorithm
+    {
+        void (*algorithm)();
+        void (*localSetup)();
+        QString name;
+    };
+
 private:
     Control() = default;
     virtual ~Control() { stopThread(); }
     MainWindow*                                          w;
-    std::vector<std::pair<void (*)(), QString>>          algorithms;
+    std::vector<Algorithm>                               algorithms;
     bool                                                 threadRunning;
     bool                                                 autorun;
+    Algorithm                                            lastAlgorithmRun = Algorithm();
     AlgoThread*                                          thread;
     void                                                 startThread(void (*func)());
     void                                                 makeConnections();
@@ -41,7 +50,7 @@ public:
     }
     static Control& get() { return getInstance(); }
     int             run(void (*setup)());
-    void            registerAlgorithm(void (*func)(), const QString name);
+    void            registerAlgorithm(void (*func)(), const QString name, void (*setup)() = nullptr);
 public slots:
     void enableAutorun(bool run) { autorun = run; }
     void stopThread();
@@ -57,6 +66,8 @@ public slots:
     void setAxisTitles(int plot, QString x, QString y);
     void setAxisVisible(int plot, bool x, bool y);
     void onRunButton();
+    void onSetupButton();
+    void onAlgoSelected(int index);
     void onPreviewButton();
     void setProblemSize(int n);
     void setProblemFile(QString path);
diff --git a/src/cute.cpp b/src/cute.cpp
index a9575bc..084eb18 100644
--- a/src/cute.cpp
+++ b/src/cute.cpp
@@ -139,10 +139,10 @@ void cute::setAxisVisible(int plot, bool x, bool y)
 }
 
 
-void cute::registerAlgorithm(void (*func)(), const std::string& name)
+void cute::registerAlgorithm(void (*func)(), const std::string& name, void (*localSetup)())
 {
     timerPauseInternal();
-    Control::get().registerAlgorithm(func, name.c_str());
+    Control::get().registerAlgorithm(func, name.c_str(), localSetup);
     timerResumeInternal();
 }
 
-- 
GitLab