diff --git a/examples/TSP.cpp b/examples/TSP.cpp index e43403f41ed671189e7b7746f21a2b0d433350c8..d8a0ba08b806f19c0ef5539dd99b261a090531f7 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 d529ed0c4f1e1cb4243bd64f1f0fc1a92bb0e71d..cdbf72c95106489db18c6fafd4f60cba5c187b72 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 0713af4a8c82f4f8d7bc5843515dd90941b977f8..5e21906d99d7c00c3680e1f0041fcac935532a67 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 d9d888d96cbb6f39c5f67d1ab5671777064fe685..88e5f82f46f5d1be9e0b0ef94ebcb18fc051dbfd 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 7bdd5aabdbb57852aa6448fc0c224ac150c96552..8f1ffcefce3400f080f2a9db80aca5e5d482bef0 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 f410a89861890d5cc2a6110292a41cf89722eb10..3433a9db8a8c8d31af0bf2aad9866c2fe2d5ca33 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 d191db4ec99e364852fd69a6d604b6c007187f21..135ff35816c0e23cacb51149a583e81b211eae79 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 defb4cb6029612f3bbd7a77cb95f2ba9a83c398d..a9575bc3f923e0ca6a59af2720ad61893fc3c774 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 d8e58e9870b43db367cc75551ed5b7f339786015..d9a31697b2c7912e69f535459b58244a0329b083 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 8cccb70c7c46d6b790c442036dd2fc84a3f854bd..91637fde8d38fc843156c18dd92ae448f21381be 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 42ae7fe3acefbd9fb1263fabf3ea4bb8697337a1..dc56fb8de66804fc13a67b340ee48e2a06ca7571 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);