From 9a0622e54b4a57d613004b051643a50e5483e674 Mon Sep 17 00:00:00 2001
From: tobiglaser <76131623+tobiglaser@users.noreply.github.com>
Date: Mon, 9 Jun 2025 18:31:55 +0200
Subject: [PATCH] added addPlot functionality
---
examples/TSP.cpp | 3 ++
examples/studiMain.cpp | 3 ++
include/cute.h | 7 +++
src/chartMenu.cpp | 104 ++++++++++++++++++++---------------------
src/chartMenu.h | 8 ++--
src/control.cpp | 27 +++++------
src/control.h | 4 +-
src/cute.cpp | 7 +++
src/cuteControl.h | 3 ++
src/mainWindow.cpp | 57 ++++++++++------------
src/mainWindow.h | 2 +-
11 files changed, 123 insertions(+), 102 deletions(-)
diff --git a/examples/TSP.cpp b/examples/TSP.cpp
index e43403f..d8a0ba0 100644
--- a/examples/TSP.cpp
+++ b/examples/TSP.cpp
@@ -17,6 +17,9 @@ void setup()
registerAlgorithm(twoOpt, "2-Opt :D");
registerAlgorithm(bruteForce, "Brute Force!");
setProblemSize(15);
+ addPlot();
+ addPlot();
+ addPlot();
setPlotTheme(3);
setPlotVisible(1, false);
setPlotVisible(2, true);
diff --git a/examples/studiMain.cpp b/examples/studiMain.cpp
index d529ed0..cdbf72c 100644
--- a/examples/studiMain.cpp
+++ b/examples/studiMain.cpp
@@ -8,6 +8,9 @@ void bubblesort();
// Is run once at startup.
void setup()
{
+ cute::addPlot();
+ cute::addPlot();
+ cute::addPlot();
cute::setPlotTitle(0, "Hallo");
cute::setPlotTitle(1, "Hochschule");
cute::setPlotTitle(2, "Reutlingen");
diff --git a/include/cute.h b/include/cute.h
index 0713af4..5e21906 100644
--- a/include/cute.h
+++ b/include/cute.h
@@ -35,6 +35,11 @@ namespace cute
logarithmic
};
+ enum PlotType /// Different types of Plots you might use.
+ {
+ chart ///< 2D Points & Lines as well as column charts.
+ };
+
/**
* @brief Representation of RGB colors used when drawing points and lines.
* For the Transparency, 0 is fully visible, 255 is unvisible.
@@ -97,6 +102,8 @@ namespace cute
bool legend = true; ///< Whether you want the data to show up in the legend.
Shape shape = circle; ///< The shape you want points to have.
};
+
+ void DYNAMIC addPlot(PlotType type = chart);
void DYNAMIC setPlotVisible(int plot, bool visible = true);
void DYNAMIC setPlotTitle(int plot, const std::string& title);
void DYNAMIC setPlotScale(int plot, Scale x, Scale y);
diff --git a/src/chartMenu.cpp b/src/chartMenu.cpp
index d9d888d..88e5f82 100644
--- a/src/chartMenu.cpp
+++ b/src/chartMenu.cpp
@@ -12,61 +12,61 @@
#include <QValueAxis>
-ChartMenu::ChartMenu(std::vector<QWidget*>& graphingWidgets, QWidget* parent) : QMenu(parent)
+void ChartMenu::plotAdded(QWidget* graphingWidget)
{
- this->graphingWidgets = graphingWidgets;
-
- for (size_t i = 0; i < graphingWidgets.size(); ++i)
+ graphingWidgets.push_back(graphingWidget);
+ QString name = "Plot ";
+ name += std::to_string(graphingWidgets.size() - 1).c_str();
+ titles.push_back(name);
+
+ QAction* menuAction = new QAction(name, this);
+ menuActions.push_back(menuAction);
+ menuAction->setCheckable(true);
+ menuAction->setChecked(!graphingWidget->isHidden());
+ addAction(menuAction);
+
+ QMenu* menu = new QMenu(name);
+ menuAction->setMenu(menu);
+
+ QAction* visibilityAction = new QAction(name, this);
+ visibilityAction->setCheckable(true); // Make it checkable
+ visibilityAction->setChecked(!graphingWidget->isHidden());
+ visibiliyActions.push_back(visibilityAction);
+ menu->addAction(visibilityAction);
+ connect(visibilityAction, &QAction::triggered, this, &ChartMenu::onVisibility);
+
+ QAction* resetAction = new QAction("Reset", this);
+ menu->addAction(resetAction);
+ resetActions.push_back(resetAction);
+ connect(resetAction, &QAction::triggered, this, &ChartMenu::onReset);
+
+ QtCharts::QChartView* chartView = dynamic_cast<QtCharts::QChartView*>(graphingWidget);
+ if (chartView)
{
- QString name = "Plot ";
- name += std::to_string(i).c_str();
- titles.push_back(name);
-
- QAction* menuAction = new QAction(name, this);
- menuActions.push_back(menuAction);
- menuAction->setCheckable(true);
- menuAction->setChecked(!graphingWidgets[i]->isHidden());
- addAction(menuAction);
-
- QMenu* menu = new QMenu(name);
- menuAction->setMenu(menu);
-
- QAction* visibilityAction = new QAction(name, this);
- visibilityAction->setCheckable(true); // Make it checkable
- visibilityAction->setChecked(!graphingWidgets[i]->isHidden());
- visibiliyActions.push_back(visibilityAction);
- menu->addAction(visibilityAction);
- connect(visibilityAction, &QAction::triggered, this, &ChartMenu::onVisibility);
-
- QAction* resetAction = new QAction("Reset", this);
- menu->addAction(resetAction);
- resetActions.push_back(resetAction);
- connect(resetAction, &QAction::triggered, this, &ChartMenu::onReset);
-
- QtCharts::QChartView* chartView = dynamic_cast<QtCharts::QChartView*>(graphingWidgets[i]);
- if (chartView)
- {
- menu->addSeparator();
- QAction* xlinAction = new QAction("X - linear");
- xlinAction->setCheckable(true);
- menu->addAction(xlinAction);
- QAction* xlogAction = new QAction("X - logarithmic");
- xlogAction->setCheckable(true);
- menu->addAction(xlogAction);
- menu->addSeparator();
- QAction* ylinAction = new QAction("Y - linear");
- ylinAction->setCheckable(true);
- menu->addAction(ylinAction);
- QAction* ylogAction = new QAction("Y - logarithmic");
- ylogAction->setCheckable(true);
- menu->addAction(ylogAction);
- scaleBundles.push_back({xlinAction, xlogAction, ylinAction, ylogAction, chartView});
- connect(xlinAction, &QAction::triggered, this, &ChartMenu::onScale);
- connect(xlogAction, &QAction::triggered, this, &ChartMenu::onScale);
- connect(ylinAction, &QAction::triggered, this, &ChartMenu::onScale);
- connect(ylogAction, &QAction::triggered, this, &ChartMenu::onScale);
- }
+ menu->addSeparator();
+ QAction* xlinAction = new QAction("X - linear");
+ xlinAction->setCheckable(true);
+ menu->addAction(xlinAction);
+ QAction* xlogAction = new QAction("X - logarithmic");
+ xlogAction->setCheckable(true);
+ menu->addAction(xlogAction);
+ menu->addSeparator();
+ QAction* ylinAction = new QAction("Y - linear");
+ ylinAction->setCheckable(true);
+ menu->addAction(ylinAction);
+ QAction* ylogAction = new QAction("Y - logarithmic");
+ ylogAction->setCheckable(true);
+ menu->addAction(ylogAction);
+ scaleBundles.push_back({xlinAction, xlogAction, ylinAction, ylogAction, chartView});
+ connect(xlinAction, &QAction::triggered, this, &ChartMenu::onScale);
+ connect(xlogAction, &QAction::triggered, this, &ChartMenu::onScale);
+ connect(ylinAction, &QAction::triggered, this, &ChartMenu::onScale);
+ connect(ylogAction, &QAction::triggered, this, &ChartMenu::onScale);
}
+}
+
+ChartMenu::ChartMenu(QWidget* parent) : QMenu(parent)
+{
connect(this, &QMenu::aboutToShow, this, &ChartMenu::onShow);
themeAction = new QAction("Theme", this);
addAction(themeAction);
diff --git a/src/chartMenu.h b/src/chartMenu.h
index 7bdd5aa..8f1ffce 100644
--- a/src/chartMenu.h
+++ b/src/chartMenu.h
@@ -30,10 +30,14 @@ private:
public:
- ChartMenu(std::vector<QWidget*>& graphingWidgets, QWidget* parent = nullptr);
+ ChartMenu(QWidget* parent = nullptr);
QAction* themeAction;
std::vector<QString> titles;
+ void plotAdded(QWidget* graphingWidget);
+ void titleChanged(int plot, const QString& title);
+ void chartThemeChanged(int themeNumber);
+
private slots:
void onShow();
void onScale();
@@ -41,8 +45,6 @@ private slots:
public slots:
void onVisibility();
- void chartThemeChanged(int themeNumber);
- void titleChanged(int plot, const QString& title);
signals:
void s_setPlotScale(int plot, int x, int y);
diff --git a/src/control.cpp b/src/control.cpp
index f410a89..3433a9d 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -31,6 +31,7 @@ void Control::makeConnections()
connect(cc, &CuteControl::s_setProgress, this, &Control::setProgress);
connect(cc, &CuteControl::s_logMessage, this, &Control::logMessage);
connect(cc, &CuteControl::s_setStatusMessage, this, &Control::setStatusMessage);
+ connect(cc, &CuteControl::s_addPlot, this, &Control::addPlot);
connect(cc, &CuteControl::s_setPlotVisible, this, &Control::setPlotVisible);
connect(cc, &CuteControl::s_setPlotTitle, this, &Control::setPlotTitle);
connect(cc, &CuteControl::s_setPlotScale, this, &Control::setPlotScale);
@@ -99,22 +100,22 @@ int Control::run(void (*userSetup)())
return -1;
}
-/**
- * @brief Construct a new Control::Control object
- * Here, in a not at all dynamic way, the vectors for processing plot commands
- * are created.
- * @todo This really should not be hardcoded.
- */
-Control::Control()
+
+void Control::addPlot(int type)
{
- onTopSeries.emplace_back();
- onTopSeries.emplace_back();
- onTopSeries.emplace_back();
- plotHistory.emplace_back();
- plotHistory.emplace_back();
- plotHistory.emplace_back();
+ if (type == cute::PlotType::chart)
+ {
+ addChart();
+ }
}
+void Control::addChart()
+ {
+ onTopSeries.emplace_back();
+ plotHistory.emplace_back();
+ w->addChart();
+ }
+
/**
* @brief Appends a QString to MainWindows logging Area / textEdit.
*
diff --git a/src/control.h b/src/control.h
index d191db4..135ff35 100644
--- a/src/control.h
+++ b/src/control.h
@@ -13,7 +13,7 @@ class Control : public QObject
{
Q_OBJECT
private:
- Control();
+ Control() = default;
virtual ~Control() { stopThread(); }
MainWindow* w;
std::vector<std::pair<void (*)(), QString>> algorithms;
@@ -66,6 +66,8 @@ public slots:
void resetPlot(int plot);
void undo(int plot);
void saveProblem();
+ void addPlot(int type);
+ void addChart();
signals:
void endThread();
};
diff --git a/src/cute.cpp b/src/cute.cpp
index defb4cb..a9575bc 100644
--- a/src/cute.cpp
+++ b/src/cute.cpp
@@ -86,6 +86,13 @@ void timerResumeInternal()
}
}
+void cute::addPlot(PlotType type)
+{
+ timerPauseInternal();
+ CuteControl::get().addPlot(type);
+ timerResumeInternal();
+}
+
void cute::setPlotVisible(int plot, bool visible)
{
timerPauseInternal();
diff --git a/src/cuteControl.h b/src/cuteControl.h
index d8e58e9..d9a3169 100644
--- a/src/cuteControl.h
+++ b/src/cuteControl.h
@@ -28,6 +28,7 @@ signals:
void s_setProgress(int n);
void s_logMessage(QString message);
void s_setStatusMessage(QString message, int duration_s);
+ void s_addPlot(int type);
void s_setPlotTitle(int plot, QString title);
void s_setPlotVisible(int plot, bool visible);
void s_setPlotScale(int plot, int x, int y);
@@ -77,6 +78,8 @@ public:
{
emit s_setStatusMessage(message.c_str(), duration_s);
}
+ void addPlot(cute::PlotType type) { emit s_addPlot((int)type); }
+
void setPlotTheme(int themeNumber) { emit s_setPlotTheme(themeNumber); }
void setPlotTitle(int plot, const std::string& title) { emit s_setPlotTitle(plot, title.c_str()); }
diff --git a/src/mainWindow.cpp b/src/mainWindow.cpp
index 8cccb70..91637fd 100644
--- a/src/mainWindow.cpp
+++ b/src/mainWindow.cpp
@@ -31,9 +31,10 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
setDockNestingEnabled(false);
setupStatusBar();
- setupCharts();
setupMenuBar();
+ setCentralWidget(new QWidget());
+ new QHBoxLayout(centralWidget());
centralWidget()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(centralWidget(), &QWidget::customContextMenuRequested, this, &MainWindow::chartContextMenu);
@@ -81,10 +82,11 @@ void MainWindow::setupMenuBar()
probM->addAction(probSave);
connect(probSave, &QAction::triggered, this, &MainWindow::saveProblem);
- cm = new ChartMenu(graphingWidgets);
+ cm = new ChartMenu();
cm->setTitle("Charts");
menubar->addMenu(cm);
connect(cm->themeAction, &QAction::triggered, this, &MainWindow::incrementChartTheme);
+ //connect
}
void MainWindow::switchToFile()
@@ -121,37 +123,28 @@ void MainWindow::switchToPaste()
}
-void MainWindow::setupCharts()
+void MainWindow::addChart()
{
- QWidget* grW = new QWidget();
- setCentralWidget(grW);
- QHBoxLayout* layout = new QHBoxLayout();
- grW->setLayout(layout);
-
- for (size_t i = 0; i < 3; i++)
- {
- QtCharts::QChartView* v = new QtCharts::QChartView();
- graphingWidgets.push_back(v);
- layout->addWidget(v, 1);
-
- QtCharts::QChart* c = new QtCharts::QChart();
- charts.push_back(c);
- v->setChart(c);
- v->setMouseTracking(true);
- v->setRenderHint(QPainter::Antialiasing);
- QString title = "Plot ";
- title += std::to_string(i).c_str();
- c->setTitle(title);
- c->legend()->setVisible(true);
- c->legend()->setMarkerShape(QtCharts::QLegend::MarkerShapeFromSeries);
- c->setMinimumSize(300, 300);
- QtCharts::QValueAxis* axisX = new QtCharts::QValueAxis();
- //axisX->setTitleText("X");
- c->addAxis(axisX, Qt::AlignBottom);
- QtCharts::QValueAxis* axisY = new QtCharts::QValueAxis();
- //axisY->setTitleText("Y");
- c->addAxis(axisY, Qt::AlignLeft);
- }
+ QtCharts::QChartView* v = new QtCharts::QChartView();
+ graphingWidgets.push_back(v);
+ centralWidget()->layout()->addWidget(v);
+
+ QtCharts::QChart* c = new QtCharts::QChart();
+ charts.push_back(c);
+ v->setChart(c);
+ v->setMouseTracking(true);
+ v->setRenderHint(QPainter::Antialiasing);
+ QString title = "Plot ";
+ title += std::to_string(charts.size() - 1).c_str();
+ c->setTitle(title);
+ c->legend()->setVisible(true);
+ c->legend()->setMarkerShape(QtCharts::QLegend::MarkerShapeFromSeries);
+ c->setMinimumSize(300, 300);
+ QtCharts::QValueAxis* axisX = new QtCharts::QValueAxis();
+ c->addAxis(axisX, Qt::AlignBottom);
+ QtCharts::QValueAxis* axisY = new QtCharts::QValueAxis();
+ c->addAxis(axisY, Qt::AlignLeft);
+ cm->plotAdded(v);
}
void MainWindow::addAlgorithm(const QString& name)
diff --git a/src/mainWindow.h b/src/mainWindow.h
index 42ae7fe..dc56fb8 100644
--- a/src/mainWindow.h
+++ b/src/mainWindow.h
@@ -35,11 +35,11 @@ public:
std::vector<QtCharts::QChart*> charts;
void addAlgorithm(const QString& name);
+ void addChart();
private:
void setupStatusBar();
void setupMenuBar();
- void setupCharts();
private slots:
void chartContextMenu(const QPoint& poss);
--
GitLab