diff --git a/examples/studiMain.cpp b/examples/studiMain.cpp index 091f06bccd1bc7047e86c0a635eadece8c6d4ab8..89b5b2a030f69fd006c08d2872635db64fe1d28a 100644 --- a/examples/studiMain.cpp +++ b/examples/studiMain.cpp @@ -113,6 +113,11 @@ void advancedDummy() prop.line = cute::LineStyle::dash; prop.legend = toggle; cute::plotLines(problem2D, 0, true, prop); + prop.color = cute::Colors::magenta; + cute::plotPoint(problem2D.front(), 0, prop); + prop.color = cute::Colors::darkRed; + prop.line = cute::LineStyle::solid; + cute::plotLine(problem2D.front(), problem2D.back(), 0, prop); } cute::setStatusMessage("Done already!"); @@ -188,7 +193,11 @@ void bubblesort() + to_string(cute::timerResult().count()) + "us.\n"; cute::logMessage(s); - //cute::addRuntime(data.size(), timer.result()); + cute::Point p = {(float)data.size(), (float)cute::timerResult().count()}; + if (cute::timerResult().count() > 0) + { + cute::plotPoint(p, 2); + } } else cute::logMessage(":'("); diff --git a/include/cute.h b/include/cute.h index 51cf20efe7563a9b6caddf0bcd7c6ce06d1906e0..f812ebecd988b44091b2d82ceb334a6befd701c8 100644 --- a/include/cute.h +++ b/include/cute.h @@ -83,11 +83,14 @@ namespace cute void DYNAMIC registerAlgorithm(void (*func)(), const std::string& name); - void DYNAMIC plotPoint(Point& point, int plot, const PlotProperties& properties); + void DYNAMIC plotPoint(const Point& point, + int plot = 0, + const PlotProperties& properties = {}, + const std::string& tooltip = "(@X, @Y)"); void DYNAMIC plotPoints(const std::vector<Point>& points, int plot = 0, const PlotProperties& properties = {}); void DYNAMIC plotValues(std::vector<float>& values, int plot = 0, const PlotProperties& properties = {}); void DYNAMIC highlightValue(float value, int plot = 0, const Color& color = cute::Colors::red); - void DYNAMIC plotLine(Point& a, Point& b, int plot, const PlotProperties& properties); + void DYNAMIC plotLine(Point& a, Point& b, int plot = 0, const PlotProperties& properties = {}); void DYNAMIC plotLines(const std::vector<Point>& points, int plot = 0, bool loop = false, diff --git a/src/control.cpp b/src/control.cpp index c35ed9a71a231de9fe0e603e63de4dcca48f687c..96ce7baef3af02c61c722a4b562de789be1599ff 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -14,6 +14,7 @@ #include <QLineEdit> #include <QLogValueAxis> #include <QString> +#include <QTooltip> #include <QValueAxis> #include <algorithm> #include <cmath> @@ -292,7 +293,7 @@ void Control::onProblemSettingChanged([[maybe_unused]] const QString& text) w->configPanel->setGenUnlocked(); } -void Control::plotXYSeries(QtCharts::QXYSeries* s, int plot, bool onTop, bool legend) +void Control::plotXYSeries(QtCharts::QXYSeries* s, int plot, bool onTop, bool legend, QString tooltip) { w->charts[plot]->addSeries(s); plotHistory[plot].push_back(s); @@ -309,6 +310,30 @@ void Control::plotXYSeries(QtCharts::QXYSeries* s, int plot, bool onTop, bool le } resizeAxes(plot); redrawOnTopSeries(plot); + + if (!tooltip.isEmpty()) + { + QtCharts::QChartView* chartView; + for (auto&& widget : w->graphingWidgets) + if ((chartView = dynamic_cast<QtCharts::QChartView*>(widget))) + if (chartView->chart() == w->charts[plot]) + break; + + QObject::connect(s, &QtCharts::QXYSeries::hovered, [=](const QPointF& point, bool state) { + if (state) + { + // Map the scene position back to the widget coordinates + QPoint pos = chartView->mapFromScene(w->charts[plot]->mapToPosition(point)); + QString text = tooltip.arg(point.x()).arg(point.y()); + + QToolTip::showText(chartView->mapToGlobal(pos), text); + } + else + { + QToolTip::hideText(); + } + }); + } } void Control::plotBarSeries(QtCharts::QBarSeries* series, int plot, bool onTop, bool legend) diff --git a/src/control.h b/src/control.h index 0e0fa8f2aab7202eb63e43d480c49bb798315716..e28da5baead22c6da91595a49b612f42522fc38a 100644 --- a/src/control.h +++ b/src/control.h @@ -60,7 +60,7 @@ public slots: void setProblemSize(int n); void setProblemFile(QString path); void onProblemSettingChanged(const QString& text); - void plotXYSeries(QtCharts::QXYSeries* s, int plot, bool onTop, bool legend); + void plotXYSeries(QtCharts::QXYSeries* s, int plot, bool onTop, bool legend, QString tooltip = ""); void plotBarSeries(QtCharts::QBarSeries* series, int plot, bool onTop, bool legend); void highlightValue(float value, int plot, QColor c); void resetPlot(int plot); diff --git a/src/cute.cpp b/src/cute.cpp index 08757b54f2a98b912e47ca3195b1a930a92d179d..51d1311b63e795e36c762f03601a79ecff83d3c4 100644 --- a/src/cute.cpp +++ b/src/cute.cpp @@ -126,9 +126,17 @@ void cute::registerAlgorithm(void (*func)(), const std::string& name) timerResumeInternal(); } -/* -void cute::plotPoint(Point &point, int plot, const PlotProperties& properties); -*/ + +void cute::plotPoint(const cute::Point& point, + int plot, + const cute::PlotProperties& properties, + const std::string& tooltip) +{ + timerPauseInternal(); + std::vector<Point> points = {point}; + CuteControl::get().plotPoints(points, plot, properties, tooltip); + timerResumeInternal(); +} void cute::plotPoints(const std::vector<Point>& points, int plot, const PlotProperties& properties) { @@ -151,9 +159,13 @@ void DYNAMIC cute::highlightValue(float value, int plot, const cute::Color& colo timerResumeInternal(); } -/* -void cute::plotLine(Point &a, Point &b, int plot, const PlotProperties& properties); -*/ +void cute::plotLine(Point& a, Point& b, int plot, const PlotProperties& properties) +{ + timerPauseInternal(); + std::vector<cute::Point> points = {a, b}; + CuteControl::get().plotLines(points, plot, false, properties); + timerResumeInternal(); +} void cute::plotLines(const std::vector<Point>& points, int plot, bool loop, const PlotProperties& properties) { diff --git a/src/cuteControl.h b/src/cuteControl.h index 249760fc297912df1acb80c53dc535e3b76d9f2c..0893c21de12118ee4ecd2badaf21f317d6d057c1 100644 --- a/src/cuteControl.h +++ b/src/cuteControl.h @@ -36,7 +36,7 @@ signals: void s_setLegendVisible(int plot, bool visible); void s_setAxisTitles(int plot, QString x, QString y); void s_setAxisVisible(int plot, bool x, bool y); - void s_plotXYSeries(QtCharts::QXYSeries* series, int plot, bool onTop, bool legend); + void s_plotXYSeries(QtCharts::QXYSeries* series, int plot, bool onTop, bool legend, QString tooltip = ""); void s_plotBarSeries(QtCharts::QBarSeries* series, int plot, bool onTop, bool legend); void s_highlightValue(float value, int plot, QColor c); void s_resetPlot(int plot); @@ -104,7 +104,10 @@ public: } } - void plotPoints(const std::vector<cute::Point>& points, int plot, const cute::PlotProperties& properties) + void plotPoints(const std::vector<cute::Point>& points, + int plot, + const cute::PlotProperties& properties, + std::string tooltip = "") { // No ownership is taken here, the Graph will own the series. using QtCharts::QScatterSeries; @@ -133,7 +136,12 @@ public: s->setMarkerShape((QtCharts::QScatterSeries::MarkerShape)properties.shape); s->setName(properties.name.c_str()); s->moveToThread(QApplication::instance()->thread()); - emit s_plotXYSeries(s, plot, properties.onTop, properties.legend); + if (!tooltip.empty()) + { + tooltip.replace(tooltip.find("@X"), 2, "%1"); + tooltip.replace(tooltip.find("@Y"), 2, "%2"); + } + emit s_plotXYSeries(s, plot, properties.onTop, properties.legend, tooltip.c_str()); } void plotValues(std::vector<float>& values, int plot, const cute::PlotProperties& properties = {}) diff --git a/src/mainWindow.cpp b/src/mainWindow.cpp index f2100714e9fe7b663e4050ccf1ad36dc08f515e6..1ae16d14d8808bf54d0aa0a9ea685fbffe1d8c72 100644 --- a/src/mainWindow.cpp +++ b/src/mainWindow.cpp @@ -116,6 +116,7 @@ void MainWindow::setupCharts() 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();