From ec1b0e26b696bdd7f7113dac3893c510c8eaf7b0 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Mon, 2 Sep 2024 10:30:00 +0300 Subject: [PATCH 01/13] adc: multiple plot cursors fix Signed-off-by: Andrei Popa --- gui/include/gui/cursorcontroller.h | 10 +++- gui/include/gui/plotcursors.h | 2 +- gui/include/gui/widgets/cursorsettings.h | 6 +++ gui/src/cursorcontroller.cpp | 59 +++++++++++++++++++++--- gui/src/plotcursors.cpp | 9 +++- gui/src/widgets/cursorsettings.cpp | 12 +++++ plugins/adc/src/time/timeplotmanager.cpp | 1 + 7 files changed, 87 insertions(+), 12 deletions(-) diff --git a/gui/include/gui/cursorcontroller.h b/gui/include/gui/cursorcontroller.h index 8dfdb30109..7619af39a6 100644 --- a/gui/include/gui/cursorcontroller.h +++ b/gui/include/gui/cursorcontroller.h @@ -18,6 +18,10 @@ class SCOPY_GUI_EXPORT CursorController : public QObject PlotCursors *getPlotCursors(); void connectSignals(CursorSettings *cursorSettings); + void static syncXCursorControllers(CursorController *ctrl1, CursorController *ctrl2); + void static unsyncXCursorControllers(CursorController *ctrl1, CursorController *ctrl2); + bool isVisible(); + public Q_SLOTS: void setVisible(bool visible); void readoutsSetVisible(bool visible); @@ -32,6 +36,9 @@ public Q_SLOTS: void onRemovedChannel(PlotChannel *ch); void updateTracking(); +Q_SIGNALS: + void visibilityChanged(bool visible); + private: PlotWidget *m_plot; PlotCursors *plotCursors; @@ -47,10 +54,9 @@ public Q_SLOTS: bool xEn, xLock, xTrack; bool yEn, yLock; bool readoutDragsEn; + bool m_visible; void initUI(); - - // void initSession(); }; } // namespace scopy #endif // CURSORCONTROLLER_H diff --git a/gui/include/gui/plotcursors.h b/gui/include/gui/plotcursors.h index a1d98f2651..65d5e31962 100644 --- a/gui/include/gui/plotcursors.h +++ b/gui/include/gui/plotcursors.h @@ -12,7 +12,7 @@ class SCOPY_GUI_EXPORT PlotCursors : public QObject { Q_OBJECT public: - PlotCursors(PlotWidget *plot); + PlotCursors(PlotWidget *plot, QObject *parent = nullptr); ~PlotCursors(); void displayIntersection(); diff --git a/gui/include/gui/widgets/cursorsettings.h b/gui/include/gui/widgets/cursorsettings.h index 495a9a4df5..e0e7dd1b31 100644 --- a/gui/include/gui/widgets/cursorsettings.h +++ b/gui/include/gui/widgets/cursorsettings.h @@ -25,6 +25,12 @@ class SCOPY_GUI_EXPORT CursorSettings : public QWidget QAbstractButton *getYLock(); QAbstractButton *getReadoutsDrag(); + void updateSession(); + +Q_SIGNALS: + void sessionUpdated(); + +protected: void initSession(); private: diff --git a/gui/src/cursorcontroller.cpp b/gui/src/cursorcontroller.cpp index 08120308a1..78d80ea9db 100644 --- a/gui/src/cursorcontroller.cpp +++ b/gui/src/cursorcontroller.cpp @@ -12,6 +12,7 @@ CursorController::CursorController(PlotWidget *plot, QObject *parent) , yEn(true) , yLock(false) , readoutDragsEn(false) + , m_visible(false) { initUI(); @@ -27,7 +28,7 @@ CursorController::~CursorController() {} void CursorController::initUI() { - plotCursors = new PlotCursors(m_plot); + plotCursors = new PlotCursors(m_plot, this); plotCursors->setVisible(false); plotCursorReadouts = new PlotCursorReadouts(m_plot); @@ -60,12 +61,9 @@ void CursorController::connectSignals(CursorSettings *cursorSettings) connect(cursorSettings->getReadoutsDrag(), &QAbstractButton::toggled, this, &CursorController::readoutsDragToggled); - cursorSettings->initSession(); - - getPlotCursors()->getX1Cursor()->setPosition(0); - getPlotCursors()->getX2Cursor()->setPosition(0); - getPlotCursors()->getY1Cursor()->setPosition(0); - getPlotCursors()->getY2Cursor()->setPosition(0); + // update session in case the settings are conncted to multiple controllers + connect(cursorSettings, &CursorSettings::sessionUpdated, this, [=]() { setVisible(isVisible()); }); + cursorSettings->updateSession(); // cursor movement connect(y1Cursor, &PlotAxisHandle::scalePosChanged, this, [=](double pos) { @@ -178,10 +176,57 @@ void CursorController::updateTracking() } } +void CursorController::syncXCursorControllers(CursorController *ctrl1, CursorController *ctrl2) +{ + ctrl2->setVisible(ctrl1->isVisible()); + ctrl2->x1Cursor->setPosition(ctrl1->x1Cursor->getPosition()); + ctrl2->x2Cursor->setPosition(ctrl1->x2Cursor->getPosition()); + + // connect ctrl1 to ctrl2 + connect(ctrl1->x1Cursor, &PlotAxisHandle::scalePosChanged, ctrl2->x1Cursor, [=](double pos) { + ctrl1->x1Cursor->blockSignals(true); + ctrl2->x1Cursor->setPosition(pos); + ctrl1->x1Cursor->blockSignals(false); + ctrl2->m_plot->repaint(); + }); + connect(ctrl1->x2Cursor, &PlotAxisHandle::scalePosChanged, ctrl2->x2Cursor, [=](double pos) { + ctrl1->x2Cursor->blockSignals(true); + ctrl2->x2Cursor->setPosition(pos); + ctrl1->x2Cursor->blockSignals(false); + ctrl2->m_plot->repaint(); + }); + + // connect ctrl2 to ctrl1 + connect(ctrl2->x1Cursor, &PlotAxisHandle::scalePosChanged, ctrl1->x1Cursor, [=](double pos) { + ctrl2->x1Cursor->blockSignals(true); + ctrl1->x1Cursor->setPosition(pos); + ctrl2->x1Cursor->blockSignals(false); + ctrl1->m_plot->repaint(); + }); + connect(ctrl2->x2Cursor, &PlotAxisHandle::scalePosChanged, ctrl1->x2Cursor, [=](double pos) { + ctrl2->x2Cursor->blockSignals(true); + ctrl1->x2Cursor->setPosition(pos); + ctrl2->x2Cursor->blockSignals(false); + ctrl1->m_plot->repaint(); + }); +} + +void CursorController::unsyncXCursorControllers(CursorController *ctrl1, CursorController *ctrl2) +{ + disconnect(ctrl1->x1Cursor, &PlotAxisHandle::scalePosChanged, ctrl2->x1Cursor, nullptr); + disconnect(ctrl1->x2Cursor, &PlotAxisHandle::scalePosChanged, ctrl2->x2Cursor, nullptr); + disconnect(ctrl2->x1Cursor, &PlotAxisHandle::scalePosChanged, ctrl1->x1Cursor, nullptr); + disconnect(ctrl2->x2Cursor, &PlotAxisHandle::scalePosChanged, ctrl1->x2Cursor, nullptr); +} + +bool CursorController::isVisible() { return m_visible; } + void CursorController::setVisible(bool visible) { + m_visible = visible; readoutsSetVisible(visible); cursorsSetVisible(visible); + Q_EMIT visibilityChanged(visible); } void CursorController::readoutsSetVisible(bool visible) { hoverReadouts->setVisible(visible && (xEn || yEn)); } diff --git a/gui/src/plotcursors.cpp b/gui/src/plotcursors.cpp index 34e154377d..fa0cdde1c7 100644 --- a/gui/src/plotcursors.cpp +++ b/gui/src/plotcursors.cpp @@ -3,8 +3,9 @@ using namespace scopy; -PlotCursors::PlotCursors(PlotWidget *plot) - : m_plot(plot) +PlotCursors::PlotCursors(PlotWidget *plot, QObject *parent) + : QObject(parent) + , m_plot(plot) , m_tracking(false) { initUI(); @@ -19,6 +20,10 @@ void PlotCursors::initUI() m_yCursors.second = new PlotAxisHandle(m_plot, m_plot->yAxis()); m_xCursors.first = new PlotAxisHandle(m_plot, m_plot->xAxis()); m_xCursors.second = new PlotAxisHandle(m_plot, m_plot->xAxis()); + m_xCursors.first->setPosition(0); + m_xCursors.second->setPosition(0); + m_yCursors.first->setPosition(0); + m_yCursors.second->setPosition(0); plotMarker1 = new QwtPlotMarker(); plotMarker2 = new QwtPlotMarker(); diff --git a/gui/src/widgets/cursorsettings.cpp b/gui/src/widgets/cursorsettings.cpp index c7f6d8eefc..b734147bb3 100644 --- a/gui/src/widgets/cursorsettings.cpp +++ b/gui/src/widgets/cursorsettings.cpp @@ -10,6 +10,7 @@ CursorSettings::CursorSettings(QWidget *parent) { initUI(); connectSignals(); + initSession(); } CursorSettings::~CursorSettings() {} @@ -97,4 +98,15 @@ void CursorSettings::initSession() getReadoutsDrag()->setChecked(false); } +void CursorSettings::updateSession() +{ + Q_EMIT getXEn()->toggled(getXEn()->isChecked()); + Q_EMIT getXLock()->toggled(getXLock()->isChecked()); + Q_EMIT getXTrack()->toggled(getXTrack()->isChecked()); + Q_EMIT getYEn()->toggled(getYEn()->isChecked()); + Q_EMIT getYLock()->toggled(getYLock()->isChecked()); + Q_EMIT getReadoutsDrag()->toggled(getReadoutsDrag()->isChecked()); + Q_EMIT sessionUpdated(); +} + #include "moc_cursorsettings.cpp" diff --git a/plugins/adc/src/time/timeplotmanager.cpp b/plugins/adc/src/time/timeplotmanager.cpp index 49fd9350ea..56ec5a1168 100644 --- a/plugins/adc/src/time/timeplotmanager.cpp +++ b/plugins/adc/src/time/timeplotmanager.cpp @@ -110,6 +110,7 @@ void TimePlotManager::syncNavigatorAndCursors(PlotComponent *p) set.insert(p->plot(0)->xAxis()->axisId()); // set.insert(p->plot(0)->yAxis()->axisId()); PlotNavigator::syncPlotNavigators(m_primary->plot(0)->navigator(), p->plot(0)->navigator(), &set); + CursorController::syncXCursorControllers(m_primary->cursor(), p->cursor()); } void TimePlotManager::syncAllPlotNavigatorsAndCursors() From 4803bc6eaa3620027a94e5c39658d7d1f589ae13 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Mon, 2 Sep 2024 10:30:00 +0300 Subject: [PATCH 02/13] cursor readouts: draggable background fix Signed-off-by: Andrei Popa --- gui/src/stylehelper.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/gui/src/stylehelper.cpp b/gui/src/stylehelper.cpp index ca0f38a323..dbce568bc0 100644 --- a/gui/src/stylehelper.cpp +++ b/gui/src/stylehelper.cpp @@ -1122,19 +1122,24 @@ void StyleHelper::HoverWidget(QWidget *w, bool draggable, QString objectName) w->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); QString style; - if(draggable) { - style = QString(R"css( - .QWidget { - background-color: transparent; + style = QString(R"css( + QWidget { + background-color: &&Background&&; border-radius: 4px; } QWidget:hover { - background-color: &&UIElementBackground&&; + background-color: &&HoverBackground&&; border-radius: 4px; } )css"); + + if(draggable) { + style.replace("&&Background&&", StyleHelper::getColor("UIElementBackground")); + style.replace("&&HoverBackground&&", StyleHelper::getColor("UIElementHighlight")); + } else { + style.replace("&&Background&&", "transparent"); + style.replace("&&HoverBackground&&", "transparent"); } - style.replace("&&UIElementBackground&&", StyleHelper::getColor("UIElementBackground")); w->setStyleSheet(style); } From 5c6c093afbb074bbf7d795d63753dff8c9288404 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Mon, 2 Sep 2024 10:30:00 +0300 Subject: [PATCH 03/13] plot widget: changed grid color Signed-off-by: Andrei Popa --- gui/src/plotscales.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui/src/plotscales.cpp b/gui/src/plotscales.cpp index 69e02e7cc4..68a2c5e9bc 100644 --- a/gui/src/plotscales.cpp +++ b/gui/src/plotscales.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -14,7 +15,7 @@ using namespace scopy; PlotScales::PlotScales(PlotWidget *plot) : QObject(plot) , m_plot(plot) - , m_color(QColor(0x6E6E6F)) + , m_color(StyleHelper::GetInstance()->getColor("UIElementHighlight")) { initGrid(); initGraticule(); From 95e0fac2c8b8d15470404a025177cd269eb01ce6 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Mon, 2 Sep 2024 10:30:00 +0300 Subject: [PATCH 04/13] buffer previewer: fixed bad limits - previewer is now automatically updated unless doing setManualDataLimits(true). this is used in monitorplot Signed-off-by: Andrei Popa --- gui/include/gui/widgets/plotbufferpreviewer.h | 3 +- gui/src/widgets/plotbufferpreviewer.cpp | 30 +++++++++++-------- plugins/adc/src/time/timeplotmanager.cpp | 4 --- plugins/datalogger/src/monitorplot.cpp | 1 + 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/gui/include/gui/widgets/plotbufferpreviewer.h b/gui/include/gui/widgets/plotbufferpreviewer.h index 5aec90032d..94ee7b9158 100644 --- a/gui/include/gui/widgets/plotbufferpreviewer.h +++ b/gui/include/gui/widgets/plotbufferpreviewer.h @@ -15,7 +15,7 @@ class SCOPY_GUI_EXPORT PlotBufferPreviewer : public QWidget explicit PlotBufferPreviewer(PlotWidget *p, BufferPreviewer *b, QWidget *parent = nullptr); ~PlotBufferPreviewer(); - void updateDataLimits(); + void setManualDataLimits(bool enabled); void updateDataLimits(double min, double max); public Q_SLOTS: @@ -26,6 +26,7 @@ public Q_SLOTS: double m_bufferDataLimitMax; double m_bufferPrevInitMin; double m_bufferPrevInitMax; + bool m_manualDataLimits; void setupBufferPreviewer(); PlotWidget *m_plot; diff --git a/gui/src/widgets/plotbufferpreviewer.cpp b/gui/src/widgets/plotbufferpreviewer.cpp index b42968b2d5..d5fbc3dd1b 100644 --- a/gui/src/widgets/plotbufferpreviewer.cpp +++ b/gui/src/widgets/plotbufferpreviewer.cpp @@ -1,11 +1,13 @@ #include "plotbufferpreviewer.h" #include "plotaxis.h" #include +#include using namespace scopy; PlotBufferPreviewer::PlotBufferPreviewer(PlotWidget *p, BufferPreviewer *b, QWidget *parent) : QWidget{parent} + , m_manualDataLimits(false) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); QVBoxLayout *layout = new QVBoxLayout(this); @@ -21,6 +23,8 @@ PlotBufferPreviewer::PlotBufferPreviewer(PlotWidget *p, BufferPreviewer *b, QWid PlotBufferPreviewer::~PlotBufferPreviewer() {} +void PlotBufferPreviewer::setManualDataLimits(bool enabled) { m_manualDataLimits = enabled; } + void PlotBufferPreviewer::setupBufferPreviewer() { m_bufferPreviewer->setMinimumHeight(20); @@ -63,21 +67,17 @@ void PlotBufferPreviewer::setupBufferPreviewer() connect(m_bufferPreviewer, &BufferPreviewer::bufferResetPosition, this, [=]() { if(m_plot->xAxis()->min() > m_plot->xAxis()->max()) { - m_plot->xAxis()->setInterval(m_bufferDataLimitMax, m_bufferDataLimitMin); + m_plot->plot()->setAxisScale(m_plot->xAxis()->axisId(), m_bufferDataLimitMax, + m_bufferDataLimitMin); } else { - m_plot->xAxis()->setInterval(m_bufferDataLimitMin, m_bufferDataLimitMax); + m_plot->plot()->setAxisScale(m_plot->xAxis()->axisId(), m_bufferDataLimitMin, + m_bufferDataLimitMax); } m_plot->xAxis()->updateAxisScale(); - updateDataLimits(); + updateBufferPreviewer(); }); -} -void PlotBufferPreviewer::updateDataLimits() -{ - PlotAxis *xAxis = (m_plot->selectedChannel()) ? m_plot->selectedChannel()->xAxis() : m_plot->xAxis(); - m_bufferDataLimitMin = xAxis->min(); - m_bufferDataLimitMax = xAxis->max(); - updateBufferPreviewer(); + connect(m_plot->navigator(), &PlotNavigator::rectChanged, this, [=]() { updateBufferPreviewer(); }); } void PlotBufferPreviewer::updateDataLimits(double min, double max) @@ -89,12 +89,18 @@ void PlotBufferPreviewer::updateDataLimits(double min, double max) void PlotBufferPreviewer::updateBufferPreviewer() { + PlotAxis *xAxis = (m_plot->selectedChannel()) ? m_plot->selectedChannel()->xAxis() : m_plot->xAxis(); + // Time interval within the plot canvas - double left = m_plot->xAxis()->visibleMin(); - double right = m_plot->xAxis()->visibleMax(); + double left = xAxis->visibleMin(); + double right = xAxis->visibleMax(); QwtInterval plotInterval(std::min(left, right), std::max(left, right)); // Time interval that represents the captured data + if(!m_manualDataLimits) { + m_bufferDataLimitMin = xAxis->min(); + m_bufferDataLimitMax = xAxis->max(); + } QwtInterval dataInterval(std::min(m_bufferDataLimitMin, m_bufferDataLimitMax), std::fmax(m_bufferDataLimitMin, m_bufferDataLimitMax)); diff --git a/plugins/adc/src/time/timeplotmanager.cpp b/plugins/adc/src/time/timeplotmanager.cpp index 56ec5a1168..22d4ea5b52 100644 --- a/plugins/adc/src/time/timeplotmanager.cpp +++ b/plugins/adc/src/time/timeplotmanager.cpp @@ -99,10 +99,6 @@ void TimePlotManager::syncNavigatorAndCursors(PlotComponent *p) if(p == m_primary) return; - if(m_plotpreviewer == nullptr) { - m_plotpreviewer = new PlotBufferPreviewer(m_primary->plot(0), m_bufferpreviewer, m_primary->plot(0)); - } - auto plt = dynamic_cast(p); QSet set; set.insert(m_primary->plot(0)->xAxis()->axisId()); diff --git a/plugins/datalogger/src/monitorplot.cpp b/plugins/datalogger/src/monitorplot.cpp index e6e6b4fb34..707d87a746 100644 --- a/plugins/datalogger/src/monitorplot.cpp +++ b/plugins/datalogger/src/monitorplot.cpp @@ -242,6 +242,7 @@ void MonitorPlot::generateBufferPreviewer() AnalogBufferPreviewer *bufferPreviewer = new AnalogBufferPreviewer(this); m_bufferPreviewer = new PlotBufferPreviewer(m_plot, bufferPreviewer, this); + m_bufferPreviewer->setManualDataLimits(true); connect(m_plot->navigator(), &PlotNavigator::rectChanged, this, [=, this]() { double time = QwtDate::toDouble(QDateTime::currentDateTime()); From 956ce323e8eaa707085764cc4c93e4c7c8fdcc30 Mon Sep 17 00:00:00 2001 From: Adrian Suciu Date: Fri, 6 Sep 2024 16:47:29 +0300 Subject: [PATCH 05/13] adc: add cursor/navigator sync to fft instrument Signed-off-by: Adrian Suciu --- plugins/adc/src/freq/fftplotmanager.cpp | 35 ++++++++++++++++++++++++- plugins/adc/src/freq/fftplotmanager.h | 4 +++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/plugins/adc/src/freq/fftplotmanager.cpp b/plugins/adc/src/freq/fftplotmanager.cpp index efbb126b1b..cd7df5f156 100644 --- a/plugins/adc/src/freq/fftplotmanager.cpp +++ b/plugins/adc/src/freq/fftplotmanager.cpp @@ -3,13 +3,16 @@ #include "fftplotcomponentsettings.h" #include #include "plotmanagercombobox.h" +#include "plotnavigator.hpp" using namespace scopy; using namespace scopy::adc; FFTPlotManager::FFTPlotManager(QString name, QWidget *parent) : PlotManager(name, parent) -{} +{ + m_primary = nullptr; +} FFTPlotManager::~FFTPlotManager() {} @@ -18,6 +21,9 @@ uint32_t FFTPlotManager::addPlot(QString name) FFTPlotComponent *plt = new FFTPlotComponent(name, m_plotIdx, this); m_plotIdx++; m_plots.append(plt); + if(m_primary == nullptr) { + m_primary = plt; + } connect(this, &PlotManager::newData, plt->plot(0), &PlotWidget::newData); @@ -40,6 +46,7 @@ uint32_t FFTPlotManager::addPlot(QString name) } multiPlotUpdate(); + syncNavigatorAndCursors(plt); Q_EMIT plotAdded(plt->uuid()); return plt->uuid(); } @@ -56,6 +63,7 @@ void FFTPlotManager::removePlot(uint32_t uuid) } multiPlotUpdate(); + syncAllPlotNavigatorsAndCursors(); } FFTPlotComponent *FFTPlotManager::plot(uint32_t uuid) @@ -75,3 +83,28 @@ void FFTPlotManager::multiPlotUpdate() cb->setVisible(b); } } + +void FFTPlotManager::syncNavigatorAndCursors(PlotComponent *p) +{ + if(p == m_primary) + return; + + auto plt = dynamic_cast(p); + QSet set; + set.insert(m_primary->plot(0)->xAxis()->axisId()); + // set.insert(m_primary->plot(0)->yAxis()->axisId()); + set.insert(p->plot(0)->xAxis()->axisId()); + // set.insert(p->plot(0)->yAxis()->axisId()); + PlotNavigator::syncPlotNavigators(m_primary->plot(0)->navigator(), p->plot(0)->navigator(), &set); + CursorController::syncXCursorControllers(m_primary->cursor(), p->cursor()); +} + +void FFTPlotManager::syncAllPlotNavigatorsAndCursors() +{ + if(m_primary != m_plots[0]) { + m_primary = m_plots[0]; + for(PlotComponent *p : qAsConst(m_plots)) { + syncNavigatorAndCursors(p); + } + } +} diff --git a/plugins/adc/src/freq/fftplotmanager.h b/plugins/adc/src/freq/fftplotmanager.h index bf233f57b7..c66fc649e4 100644 --- a/plugins/adc/src/freq/fftplotmanager.h +++ b/plugins/adc/src/freq/fftplotmanager.h @@ -23,7 +23,11 @@ class SCOPY_ADC_EXPORT FFTPlotManager : public PlotManager FFTPlotComponent *plot(uint32_t uuid); private: + PlotComponent *m_primary; void multiPlotUpdate(); + + void syncNavigatorAndCursors(PlotComponent *); + void syncAllPlotNavigatorsAndCursors(); }; } // namespace adc } // namespace scopy From 72483407a1de04e6267425da055292030c343ea3 Mon Sep 17 00:00:00 2001 From: Adrian Suciu Date: Fri, 6 Sep 2024 16:47:40 +0300 Subject: [PATCH 06/13] adc: move default position of cursor readouts to bottom right Signed-off-by: Adrian Suciu --- gui/src/cursorcontroller.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/src/cursorcontroller.cpp b/gui/src/cursorcontroller.cpp index 78d80ea9db..3ea9d6c5be 100644 --- a/gui/src/cursorcontroller.cpp +++ b/gui/src/cursorcontroller.cpp @@ -40,9 +40,9 @@ void CursorController::initUI() plotCursorReadouts->setYUnits(ch->yAxis()->getUnits()); } hoverReadouts = new HoverWidget(plotCursorReadouts, m_plot->plot()->canvas(), m_plot); - hoverReadouts->setAnchorPos(HoverPosition::HP_TOPLEFT); - hoverReadouts->setContentPos(HoverPosition::HP_BOTTOMRIGHT); - hoverReadouts->setAnchorOffset(QPoint(10, 10)); + hoverReadouts->setAnchorPos(HoverPosition::HP_BOTTOMRIGHT); + hoverReadouts->setContentPos(HoverPosition::HP_TOPLEFT); + hoverReadouts->setAnchorOffset(QPoint(-10, -10)); hoverReadouts->setRelative(true); } From e0854afcfdaba38d0d377795ee134fad65d408c3 Mon Sep 17 00:00:00 2001 From: Adrian Suciu Date: Fri, 6 Sep 2024 16:48:18 +0300 Subject: [PATCH 07/13] adc: fixed scroll bar showing when only 1 marker is enabled Signed-off-by: Adrian Suciu --- plugins/adc/src/markercontroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/adc/src/markercontroller.cpp b/plugins/adc/src/markercontroller.cpp index 6c1b6a0169..a28bc8b169 100644 --- a/plugins/adc/src/markercontroller.cpp +++ b/plugins/adc/src/markercontroller.cpp @@ -380,7 +380,7 @@ void MarkerPanel::deleteChannel(QString name) void MarkerPanel::updateChannel(QString name, QList mi) { dynamic_cast(m_map[name])->updateInfo(mi); - setFixedHeight(20 + mi.count() * 20); + setFixedHeight(25 + mi.count() * 20); } int MarkerPanel::markerCount() { return m_map.count(); } From 3931da94d9a2e5ffd937bc3e38b958f82efcc16c Mon Sep 17 00:00:00 2001 From: Adrian Suciu Date: Fri, 6 Sep 2024 16:48:35 +0300 Subject: [PATCH 08/13] adc: changed display name of instruments Signed-off-by: Adrian Suciu --- plugins/adc/src/adcplugin.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/adc/src/adcplugin.cpp b/plugins/adc/src/adcplugin.cpp index 6f65a31b7a..3b603a4185 100644 --- a/plugins/adc/src/adcplugin.cpp +++ b/plugins/adc/src/adcplugin.cpp @@ -133,8 +133,8 @@ bool ADCPlugin::loadPage() void ADCPlugin::loadToolList() { m_toolList.append( - SCOPY_NEW_TOOLMENUENTRY("time", "Time", ":/gui/icons/scopy-default/icons/tool_oscilloscope.svg")); - m_toolList.append(SCOPY_NEW_TOOLMENUENTRY("freq", "Frequency", + SCOPY_NEW_TOOLMENUENTRY("time", "ADC - Time", ":/gui/icons/scopy-default/icons/tool_oscilloscope.svg")); + m_toolList.append(SCOPY_NEW_TOOLMENUENTRY("freq", "ADC - Frequency", ":/gui/icons/scopy-default/icons/tool_spectrum_analyzer.svg")); } @@ -226,7 +226,7 @@ void ADCPlugin::newInstrument(ADCInstrumentType t, AcqTreeNode *root) ADCInstrument *ui; if(t == TIME) { - m_toolList.append(SCOPY_NEW_TOOLMENUENTRY("time", "Time", + m_toolList.append(SCOPY_NEW_TOOLMENUENTRY("time", "ADC - Time", ":/gui/icons/scopy-default/icons/tool_oscilloscope.svg")); auto tme = m_toolList.last(); tme->setEnabled(true); @@ -259,7 +259,7 @@ void ADCPlugin::newInstrument(ADCInstrumentType t, AcqTreeNode *root) } else if(t == FREQUENCY) { m_toolList.append(SCOPY_NEW_TOOLMENUENTRY( - "freq", "Frequency", ":/gui/icons/scopy-default/icons/tool_spectrum_analyzer.svg")); + "freq", "ADC - Frequency", ":/gui/icons/scopy-default/icons/tool_spectrum_analyzer.svg")); auto tme = m_toolList.last(); tme->setEnabled(true); tme->setRunBtnVisible(true); From 81a827e8305bf21e1c4fd5534cf5a0bac3a36972 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Wed, 4 Sep 2024 17:00:57 +0300 Subject: [PATCH 09/13] gui: added scroll area to VerticalChannelManager - this fixes overlapping channels if there are too many Signed-off-by: Andrei Popa --- .../gui/widgets/verticalchannelmanager.h | 4 +++ gui/src/widgets/verticalchannelmanager.cpp | 32 ++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/gui/include/gui/widgets/verticalchannelmanager.h b/gui/include/gui/widgets/verticalchannelmanager.h index 03799a5fb9..844f876ea1 100644 --- a/gui/include/gui/widgets/verticalchannelmanager.h +++ b/gui/include/gui/widgets/verticalchannelmanager.h @@ -7,6 +7,7 @@ #include #include +class QScrollArea; namespace scopy { class SCOPY_GUI_EXPORT VerticalChannelManager : public QWidget, public CompositeWidget { @@ -21,6 +22,9 @@ class SCOPY_GUI_EXPORT VerticalChannelManager : public QWidget, public Composite private: QSpacerItem *spacer; QVBoxLayout *lay; + QVBoxLayout *m_contLayout; + QScrollArea *m_scrollArea; + QWidget *m_container; }; } // namespace scopy diff --git a/gui/src/widgets/verticalchannelmanager.cpp b/gui/src/widgets/verticalchannelmanager.cpp index ca5e1433fd..5d03845c35 100644 --- a/gui/src/widgets/verticalchannelmanager.cpp +++ b/gui/src/widgets/verticalchannelmanager.cpp @@ -1,33 +1,49 @@ #include +#include using namespace scopy; VerticalChannelManager::VerticalChannelManager(QWidget *parent) : QWidget(parent) { lay = new QVBoxLayout(this); - setLayout(lay); lay->setMargin(0); - lay->setSpacing(6); - spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding); - lay->addSpacerItem(spacer); + lay->setSpacing(0); + + setLayout(lay); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + + spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding); + + QWidget *m_container = new QWidget(this); + m_contLayout = new QVBoxLayout(m_container); + m_contLayout->addSpacerItem(spacer); + m_contLayout->setMargin(0); + m_contLayout->setSpacing(6); + m_container->setLayout(m_contLayout); + + m_scrollArea = new QScrollArea(this); + m_scrollArea->setWidget(m_container); + m_scrollArea->setWidgetResizable(true); + m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + lay->addWidget(m_scrollArea); } VerticalChannelManager::~VerticalChannelManager() {} void VerticalChannelManager::add(QWidget *ch) { - int position = lay->indexOf(spacer); - lay->insertWidget(position, ch); + int position = m_contLayout->indexOf(spacer); + m_contLayout->insertWidget(position, ch); ch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); } void VerticalChannelManager::addEnd(QWidget *ch) { - lay->addWidget(ch); + m_contLayout->addWidget(ch); ch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); } -void VerticalChannelManager::remove(QWidget *ch) { lay->removeWidget(ch); } +void VerticalChannelManager::remove(QWidget *ch) { m_contLayout->removeWidget(ch); } #include "moc_verticalchannelmanager.cpp" From f1aa60928d40ad3233bf2bf851c5b33376283ce8 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Fri, 6 Sep 2024 17:06:00 +0300 Subject: [PATCH 10/13] BufferPreviewer: rework previewer to use PlotMagnifier Signed-off-by: Andrei Popa --- gui/include/gui/plotmagnifier.hpp | 3 ++ gui/include/gui/plotnavigator.hpp | 3 ++ gui/include/gui/widgets/plotbufferpreviewer.h | 3 +- gui/src/plotmagnifier.cpp | 16 ++++++- gui/src/plotnavigator.cpp | 30 ++++++++++++ gui/src/widgets/plotbufferpreviewer.cpp | 48 ++++++++----------- 6 files changed, 71 insertions(+), 32 deletions(-) diff --git a/gui/include/gui/plotmagnifier.hpp b/gui/include/gui/plotmagnifier.hpp index c52dcd75bd..b4e5e00dc2 100644 --- a/gui/include/gui/plotmagnifier.hpp +++ b/gui/include/gui/plotmagnifier.hpp @@ -55,6 +55,9 @@ class SCOPY_GUI_EXPORT PlotMagnifier : public QObject bool isXAxisEn() const; bool isYAxisEn() const; + static double scaleToFactor(double scale, QwtAxisId axisId, QwtPlot *plot); + static double factorToScale(double factor, QwtAxisId axisId, QwtPlot *plot); + Q_SIGNALS: void reset(); void zoomed(double factor, QPointF cursorPos = QPointF()); diff --git a/gui/include/gui/plotnavigator.hpp b/gui/include/gui/plotnavigator.hpp index 51299fe4fa..bcd7dfba7c 100644 --- a/gui/include/gui/plotnavigator.hpp +++ b/gui/include/gui/plotnavigator.hpp @@ -48,6 +48,9 @@ class SCOPY_GUI_EXPORT PlotNavigator : public QObject void removeChannel(PlotChannel *channel); bool isZoomed(); + void forcePan(QwtAxisId axisId, double factor); + void forceMagnify(QwtAxisId axisId, double factor, QPointF cursorPos); + void forceZoom(QwtAxisId axisId, const QRectF &rect); void setZoomerXAxesEn(bool en); void setZoomerYAxesEn(bool en); diff --git a/gui/include/gui/widgets/plotbufferpreviewer.h b/gui/include/gui/widgets/plotbufferpreviewer.h index 94ee7b9158..bbbaec4dd3 100644 --- a/gui/include/gui/widgets/plotbufferpreviewer.h +++ b/gui/include/gui/widgets/plotbufferpreviewer.h @@ -24,13 +24,12 @@ public Q_SLOTS: private: double m_bufferDataLimitMin; double m_bufferDataLimitMax; - double m_bufferPrevInitMin; - double m_bufferPrevInitMax; bool m_manualDataLimits; void setupBufferPreviewer(); PlotWidget *m_plot; BufferPreviewer *m_bufferPreviewer; + double m_lastMin; }; } // namespace scopy diff --git a/gui/src/plotmagnifier.cpp b/gui/src/plotmagnifier.cpp index c9390c1a6e..c0e1c8ad83 100644 --- a/gui/src/plotmagnifier.cpp +++ b/gui/src/plotmagnifier.cpp @@ -182,6 +182,20 @@ bool PlotMagnifier::eventFilter(QObject *object, QEvent *event) return QObject::eventFilter(object, event); } +double PlotMagnifier::scaleToFactor(double scale, QwtAxisId axisId, QwtPlot *plot) +{ + double v1 = plot->axisInterval(axisId).minValue(); + double v2 = plot->axisInterval(axisId).maxValue(); + return (scale / 0.5 - (v2 - v1)) / (v1 - v2); +} + +double PlotMagnifier::factorToScale(double factor, QwtAxisId axisId, QwtPlot *plot) +{ + double v1 = plot->axisInterval(axisId).minValue(); + double v2 = plot->axisInterval(axisId).maxValue(); + return ((v2 - v1) - (v2 - v1) * factor) * 0.5; +} + void PlotMagnifier::panRescale(double factor) { if(isXAxisEn()) { @@ -190,7 +204,7 @@ void PlotMagnifier::panRescale(double factor) double v1 = plot()->axisInterval(axisId).minValue(); double v2 = plot()->axisInterval(axisId).maxValue(); - double pan_amount = (((v2 - v1) - (v2 - v1) * factor) * 0.5); + double pan_amount = factorToScale(factor, axisId, plot()); bool isInverted = v1 > v2; if(isInverted) { diff --git a/gui/src/plotnavigator.cpp b/gui/src/plotnavigator.cpp index 05e028c874..681f704551 100644 --- a/gui/src/plotnavigator.cpp +++ b/gui/src/plotnavigator.cpp @@ -354,6 +354,36 @@ bool PlotNavigator::isZoomed() return zoomed; } +void PlotNavigator::forcePan(QwtAxisId axisId, double factor) +{ + for(Navigator *nav : *m_navigators) { + if((nav->magnifier->isXAxisEn() && nav->magnifier->getXAxis() == axisId) || + (nav->magnifier->isYAxisEn() && nav->magnifier->getYAxis() == axisId)) { + nav->magnifier->pan(factor); + } + } +} + +void PlotNavigator::forceMagnify(QwtAxisId axisId, double factor, QPointF cursorPos) +{ + for(Navigator *nav : *m_navigators) { + if((nav->magnifier->isXAxisEn() && nav->magnifier->getXAxis() == axisId) || + (nav->magnifier->isYAxisEn() && nav->magnifier->getYAxis() == axisId)) { + nav->magnifier->zoom(factor, cursorPos); + } + } +} + +void PlotNavigator::forceZoom(QwtAxisId axisId, const QRectF &rect) +{ + for(Navigator *nav : *m_navigators) { + if((nav->zoomer->isXAxisEn() && nav->zoomer->getXAxis() == axisId) || + (nav->zoomer->isYAxisEn() && nav->zoomer->getYAxis() == axisId)) { + nav->zoomer->zoom(rect); + } + } +} + void PlotNavigator::setZoomerXAxesEn(bool en) { m_visibleZoomer->setXAxisEn(en); diff --git a/gui/src/widgets/plotbufferpreviewer.cpp b/gui/src/widgets/plotbufferpreviewer.cpp index d5fbc3dd1b..ae7cd59838 100644 --- a/gui/src/widgets/plotbufferpreviewer.cpp +++ b/gui/src/widgets/plotbufferpreviewer.cpp @@ -1,6 +1,7 @@ #include "plotbufferpreviewer.h" #include "plotaxis.h" #include +#include #include using namespace scopy; @@ -8,6 +9,7 @@ using namespace scopy; PlotBufferPreviewer::PlotBufferPreviewer(PlotWidget *p, BufferPreviewer *b, QWidget *parent) : QWidget{parent} , m_manualDataLimits(false) + , m_lastMin(p->xAxis()->visibleMin()) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); QVBoxLayout *layout = new QVBoxLayout(this); @@ -37,43 +39,31 @@ void PlotBufferPreviewer::setupBufferPreviewer() updateDataLimits(m_plot->xAxis()->min(), m_plot->xAxis()->max()); - connect(m_bufferPreviewer, &BufferPreviewer::bufferStopDrag, this, [=]() {}); - connect(m_bufferPreviewer, &BufferPreviewer::bufferStartDrag, this, [=]() { // reset the buffer preview position to current visible section - // using lower and upper bound to also consider zoom level - m_bufferPrevInitMin = m_plot->xAxis()->visibleMin(); - m_bufferPrevInitMax = m_plot->xAxis()->visibleMax(); + m_lastMin = m_plot->xAxis()->visibleMin(); }); - connect(m_bufferPreviewer, &BufferPreviewer::bufferMovedBy, this, [=](int value) { - double moveTo = 0.0; - - int width = m_bufferPreviewer->width(); - double xAxisWidth = abs(m_bufferDataLimitMax - m_bufferDataLimitMin); - - if(m_plot->xAxis()->min() > m_plot->xAxis()->max()) { - value *= -1; - } - - moveTo = value * xAxisWidth / width; - - m_plot->plot()->setAxisScale(m_plot->xAxis()->axisId(), m_bufferPrevInitMin + moveTo, - m_bufferPrevInitMax + moveTo); - m_plot->replot(); - + connect(m_bufferPreviewer, &BufferPreviewer::bufferMovedBy, this, [=](int bufferPos) { + double bufferWidth = m_bufferPreviewer->width(); + double axisWidth = m_bufferDataLimitMax - m_bufferDataLimitMin; + double newAxisPos = bufferPos * axisWidth / bufferWidth; + double axisOffset = m_lastMin - m_plot->xAxis()->visibleMin(); + if(axisWidth < 0) + axisOffset *= -1; + + double panAmount = PlotMagnifier::scaleToFactor(newAxisPos + axisOffset, m_plot->xAxis()->axisId(), + m_plot->plot()); + + bool bounded = m_plot->navigator()->isBounded(); + m_plot->navigator()->setBounded(false); + m_plot->navigator()->forcePan(m_plot->xAxis()->axisId(), panAmount); + m_plot->navigator()->setBounded(bounded); updateBufferPreviewer(); }); connect(m_bufferPreviewer, &BufferPreviewer::bufferResetPosition, this, [=]() { - if(m_plot->xAxis()->min() > m_plot->xAxis()->max()) { - m_plot->plot()->setAxisScale(m_plot->xAxis()->axisId(), m_bufferDataLimitMax, - m_bufferDataLimitMin); - } else { - m_plot->plot()->setAxisScale(m_plot->xAxis()->axisId(), m_bufferDataLimitMin, - m_bufferDataLimitMax); - } - m_plot->xAxis()->updateAxisScale(); + Q_EMIT m_plot->navigator()->reset(); updateBufferPreviewer(); }); From 5c279e01d55a569c3b79fed8b9e634bfff3fb5d3 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Tue, 10 Sep 2024 11:43:28 +0300 Subject: [PATCH 11/13] PlotNavigator: added sync function for all axes - code optimizations Signed-off-by: Andrei Popa --- gui/include/gui/plotnavigator.hpp | 6 +- gui/src/plotnavigator.cpp | 108 +++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 32 deletions(-) diff --git a/gui/include/gui/plotnavigator.hpp b/gui/include/gui/plotnavigator.hpp index bcd7dfba7c..1f771ee844 100644 --- a/gui/include/gui/plotnavigator.hpp +++ b/gui/include/gui/plotnavigator.hpp @@ -98,12 +98,14 @@ class SCOPY_GUI_EXPORT PlotNavigator : public QObject Qt::KeyboardModifier getZoomerXYModifier(); static void syncPlotNavigators(PlotNavigator *pNav1, PlotNavigator *pNav2, QSet *axes); + static void syncPlotNavigators(PlotNavigator *pNav1, PlotNavigator *pNav2); void setResetButtonEn(bool en); Q_SIGNALS: void reset(); void undo(); void rectChanged(const QRectF &rect, navigationType type); + void addedNavigator(Navigator *nav); protected: virtual bool eventFilter(QObject *object, QEvent *event) QWT_OVERRIDE; @@ -118,11 +120,13 @@ class SCOPY_GUI_EXPORT PlotNavigator : public QObject PlotMagnifier *createMagnifier(QwtAxisId axisId); PlotZoomer *createZoomer(QwtAxisId axisId); void addNavigators(QwtAxisId axisId); - void removeNavigators(QwtAxisId axisId); + void removeNavigators(QwtAxisId axisId, PlotChannel *channel); void addRectToHistory(Navigator *nav, const QRectF &rect, navigationType type); void onUndo(); void onReset(); static void syncNavigators(PlotNavigator *pNav1, Navigator *nav1, PlotNavigator *pNav2, Navigator *nav2); + static void syncPlotNavigatorSignals(PlotNavigator *pNav1, PlotNavigator *pNav2); + static void syncPlotNavigatorAxes(PlotNavigator *pNav1, PlotNavigator *pNav2, QSet *axes); private: bool m_en; diff --git a/gui/src/plotnavigator.cpp b/gui/src/plotnavigator.cpp index 681f704551..5a7d6f4672 100644 --- a/gui/src/plotnavigator.cpp +++ b/gui/src/plotnavigator.cpp @@ -193,16 +193,34 @@ void PlotNavigator::addNavigators(QwtAxisId axisId) Q_EMIT reset(); } }); + + Q_EMIT addedNavigator(nav); } -void PlotNavigator::removeNavigators(QwtAxisId axisId) +void PlotNavigator::removeNavigators(QwtAxisId axisId, PlotChannel *channel) { + // remove axes if there aren't other channels using them + bool found = false; + + for(PlotChannel *ch : *m_channels) { + if((ch->xAxis()->axisId() == axisId) || (ch->yAxis()->axisId() == axisId)) { + found = true; + } + } + + QList toDelete; for(Navigator *nav : *m_navigators) { - if(nav->magnifier->getXAxis() == axisId || nav->magnifier->getYAxis() == axisId) { - delete nav; - m_navigators->remove(nav); + if((!found && nav->magnifier->getXAxis() == axisId) || + (!found && nav->magnifier->getYAxis() == axisId)) { + toDelete.push_back(nav); } } + + for(Navigator *n : toDelete) { + m_navigators->remove(n); + delete n; + m_axes->remove(axisId); + } } void PlotNavigator::onReset() @@ -284,8 +302,6 @@ QSet *PlotNavigator::channels() { return m_channels; } void PlotNavigator::addChannel(PlotChannel *channel) { - m_channels->insert(channel); - // insert axes if there aren't other channels already using them QwtAxisId axisId = channel->xAxis()->axisId(); if(!m_axes->contains(axisId)) { @@ -301,38 +317,18 @@ void PlotNavigator::addChannel(PlotChannel *channel) setBaseRect(axisId); } + m_channels->insert(channel); m_visibleZoomer->setEnabled(isZoomerEn()); } void PlotNavigator::removeChannel(PlotChannel *channel) { - m_channels->remove(channel); - // remove axes if there aren't other channels using them QwtAxisId xAxis = channel->xAxis()->axisId(); - bool xFound = false; QwtAxisId yAxis = channel->yAxis()->axisId(); - bool yFound = false; - - for(PlotChannel *ch : *m_channels) { - if(ch->xAxis()->axisId() == xAxis) { - xFound = true; - } - if(ch->yAxis()->axisId() == yAxis) { - yFound = true; - } - } - - QList toDelete; - for(Navigator *nav : *m_navigators) { - if((xFound && nav->magnifier->getXAxis() == xAxis) || (yFound && nav->magnifier->getYAxis() == yAxis)) { - toDelete.push_back(nav); - } - } - for(Navigator *n : toDelete) { - m_navigators->remove(n); - delete n; - } + removeNavigators(xAxis, channel); + removeNavigators(yAxis, channel); + m_channels->remove(channel); if(m_channels->empty()) { m_visibleZoomer->setEnabled(false); @@ -553,14 +549,17 @@ void PlotNavigator::syncNavigators(PlotNavigator *pNav1, Navigator *nav1, PlotNa connect(nav1->zoomer, &PlotZoomer::zoomed, pNav2, [=](const QRectF &rect) { nav2->zoomer->silentZoom(rect); pNav2->addRectToHistory(nav2, rect, navigationType::Zoom); + Q_EMIT pNav2->rectChanged(rect, navigationType::Zoom); }); connect(nav1->magnifier, &PlotMagnifier::zoomedRect, pNav2, [=](const QRectF &rect) { nav2->zoomer->silentZoom(rect); pNav2->addRectToHistory(nav2, rect, navigationType::Magnify); + Q_EMIT pNav2->rectChanged(rect, navigationType::Magnify); }); connect(nav1->magnifier, &PlotMagnifier::pannedRect, pNav2, [=](const QRectF &rect) { nav2->zoomer->silentZoom(rect); pNav2->addRectToHistory(nav2, rect, navigationType::Pan); + Q_EMIT pNav2->rectChanged(rect, navigationType::Pan); }); connect(pNav1, &PlotNavigator::reset, nav2->magnifier, &PlotMagnifier::reset); connect(pNav1, &PlotNavigator::reset, nav2->zoomer, &PlotZoomer::reset); @@ -569,27 +568,33 @@ void PlotNavigator::syncNavigators(PlotNavigator *pNav1, Navigator *nav1, PlotNa connect(nav2->zoomer, &PlotZoomer::zoomed, pNav1, [=](const QRectF &rect) { nav1->zoomer->silentZoom(rect); pNav1->addRectToHistory(nav1, rect, navigationType::Zoom); + Q_EMIT pNav1->rectChanged(rect, navigationType::Zoom); }); connect(nav2->magnifier, &PlotMagnifier::zoomedRect, pNav1, [=](const QRectF &rect) { nav1->zoomer->silentZoom(rect); pNav1->addRectToHistory(nav1, rect, navigationType::Magnify); + Q_EMIT pNav1->rectChanged(rect, navigationType::Magnify); }); connect(nav2->magnifier, &PlotMagnifier::pannedRect, pNav1, [=](const QRectF &rect) { nav1->zoomer->silentZoom(rect); pNav1->addRectToHistory(nav1, rect, navigationType::Pan); + Q_EMIT pNav1->rectChanged(rect, navigationType::Pan); }); connect(pNav2, &PlotNavigator::reset, nav1->magnifier, &PlotMagnifier::reset); connect(pNav2, &PlotNavigator::reset, nav1->zoomer, &PlotZoomer::reset); } -void PlotNavigator::syncPlotNavigators(PlotNavigator *pNav1, PlotNavigator *pNav2, QSet *axes) +void PlotNavigator::syncPlotNavigatorSignals(PlotNavigator *pNav1, PlotNavigator *pNav2) { connect(pNav1, &PlotNavigator::undo, pNav2, &PlotNavigator::onUndo); connect(pNav1, &PlotNavigator::reset, pNav2, &PlotNavigator::onReset); connect(pNav2, &PlotNavigator::undo, pNav1, &PlotNavigator::onUndo); connect(pNav2, &PlotNavigator::reset, pNav1, &PlotNavigator::onReset); +} +void PlotNavigator::syncPlotNavigatorAxes(PlotNavigator *pNav1, PlotNavigator *pNav2, QSet *axes) +{ for(Navigator *nav1 : *pNav1->navigators()) { if((nav1->magnifier->isXAxisEn() && axes->contains(nav1->magnifier->getXAxis())) || (nav1->magnifier->isYAxisEn() && axes->contains(nav1->magnifier->getYAxis()))) { @@ -603,6 +608,47 @@ void PlotNavigator::syncPlotNavigators(PlotNavigator *pNav1, PlotNavigator *pNav } } +// Sync plot navigators only on the specified axes +void PlotNavigator::syncPlotNavigators(PlotNavigator *pNav1, PlotNavigator *pNav2, QSet *axes) +{ + syncPlotNavigatorSignals(pNav1, pNav2); + syncPlotNavigatorAxes(pNav1, pNav2, axes); +} + +// Sync plot navigators on all axes +// this will also work for axes added/removed later +void PlotNavigator::syncPlotNavigators(PlotNavigator *pNav1, PlotNavigator *pNav2) +{ + syncPlotNavigatorSignals(pNav1, pNav2); + + // sync axes shared by both navigators + QSet *axes = new QSet(pNav1->axes()->begin(), pNav1->axes()->end()); + axes->intersect(*pNav2->axes()); + syncPlotNavigatorAxes(pNav1, pNav2, axes); + + // sync future axes + connect(pNav1, &PlotNavigator::addedNavigator, pNav1, [=](Navigator *nav1) { + for(Navigator *nav2 : *pNav2->navigators()) { + if((nav1->magnifier->isXAxisEn() && nav2->magnifier->isXAxisEn() && + nav1->magnifier->getXAxis() == nav2->magnifier->getXAxis()) || + (nav1->magnifier->isYAxisEn() && nav2->magnifier->isYAxisEn() && + nav1->magnifier->getYAxis() == nav2->magnifier->getYAxis())) { + syncNavigators(pNav1, nav1, pNav2, nav2); + } + } + }); + connect(pNav2, &PlotNavigator::addedNavigator, pNav2, [=](Navigator *nav2) { + for(Navigator *nav1 : *pNav1->navigators()) { + if((nav2->magnifier->isXAxisEn() && nav1->magnifier->isXAxisEn() && + nav2->magnifier->getXAxis() == nav1->magnifier->getXAxis()) || + (nav2->magnifier->isYAxisEn() && nav1->magnifier->isYAxisEn() && + nav2->magnifier->getYAxis() == nav1->magnifier->getYAxis())) { + syncNavigators(pNav2, nav2, pNav1, nav1); + } + } + }); +} + void PlotNavigator::setResetButtonEn(bool en) { m_resetHover->setVisible(en); } #include "moc_plotnavigator.cpp" From 5a79e3f7c37905d155ce309969e4f6e4d4233c20 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Wed, 11 Sep 2024 16:51:33 +0300 Subject: [PATCH 12/13] adc: Fixed plot navigator sync Signed-off-by: Andrei Popa --- gui/src/plotwidget.cpp | 4 ++++ plugins/adc/src/freq/fftplotmanager.cpp | 10 ++-------- plugins/adc/src/time/timeplotmanager.cpp | 10 ++-------- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/gui/src/plotwidget.cpp b/gui/src/plotwidget.cpp index 343d5447d1..ea2d8dca14 100644 --- a/gui/src/plotwidget.cpp +++ b/gui/src/plotwidget.cpp @@ -109,18 +109,22 @@ void PlotWidget::setupOpenGLCanvas() void PlotWidget::plotChannelChangeXAxis(PlotChannel *c, PlotAxis *x) { + m_navigator->removeChannel(c); m_tracker->removeChannel(c); c->xAxis()->setVisible(false); c->setXAxis(x); + m_navigator->addChannel(c); m_tracker->addChannel(c); showAxisLabels(); } void PlotWidget::plotChannelChangeYAxis(PlotChannel *c, PlotAxis *y) { + m_navigator->removeChannel(c); m_tracker->removeChannel(c); c->yAxis()->setVisible(false); c->setYAxis(y); + m_navigator->addChannel(c); m_tracker->addChannel(c); showAxisLabels(); } diff --git a/plugins/adc/src/freq/fftplotmanager.cpp b/plugins/adc/src/freq/fftplotmanager.cpp index cd7df5f156..c73f7ff62f 100644 --- a/plugins/adc/src/freq/fftplotmanager.cpp +++ b/plugins/adc/src/freq/fftplotmanager.cpp @@ -63,7 +63,7 @@ void FFTPlotManager::removePlot(uint32_t uuid) } multiPlotUpdate(); - syncAllPlotNavigatorsAndCursors(); + // syncAllPlotNavigatorsAndCursors(); } FFTPlotComponent *FFTPlotManager::plot(uint32_t uuid) @@ -89,13 +89,7 @@ void FFTPlotManager::syncNavigatorAndCursors(PlotComponent *p) if(p == m_primary) return; - auto plt = dynamic_cast(p); - QSet set; - set.insert(m_primary->plot(0)->xAxis()->axisId()); - // set.insert(m_primary->plot(0)->yAxis()->axisId()); - set.insert(p->plot(0)->xAxis()->axisId()); - // set.insert(p->plot(0)->yAxis()->axisId()); - PlotNavigator::syncPlotNavigators(m_primary->plot(0)->navigator(), p->plot(0)->navigator(), &set); + PlotNavigator::syncPlotNavigators(m_primary->plot(0)->navigator(), p->plot(0)->navigator()); CursorController::syncXCursorControllers(m_primary->cursor(), p->cursor()); } diff --git a/plugins/adc/src/time/timeplotmanager.cpp b/plugins/adc/src/time/timeplotmanager.cpp index 22d4ea5b52..c6fd0f011b 100644 --- a/plugins/adc/src/time/timeplotmanager.cpp +++ b/plugins/adc/src/time/timeplotmanager.cpp @@ -72,7 +72,7 @@ void TimePlotManager::removePlot(uint32_t uuid) } multiPlotUpdate(); - syncAllPlotNavigatorsAndCursors(); + // syncAllPlotNavigatorsAndCursors(); } TimePlotComponent *TimePlotManager::plot(uint32_t uuid) @@ -99,13 +99,7 @@ void TimePlotManager::syncNavigatorAndCursors(PlotComponent *p) if(p == m_primary) return; - auto plt = dynamic_cast(p); - QSet set; - set.insert(m_primary->plot(0)->xAxis()->axisId()); - // set.insert(m_primary->plot(0)->yAxis()->axisId()); - set.insert(p->plot(0)->xAxis()->axisId()); - // set.insert(p->plot(0)->yAxis()->axisId()); - PlotNavigator::syncPlotNavigators(m_primary->plot(0)->navigator(), p->plot(0)->navigator(), &set); + PlotNavigator::syncPlotNavigators(m_primary->plot(0)->navigator(), p->plot(0)->navigator()); CursorController::syncXCursorControllers(m_primary->cursor(), p->cursor()); } From 0631d5361d5c0208decc40b2e09f22490c6740f7 Mon Sep 17 00:00:00 2001 From: Andrei Popa Date: Thu, 12 Sep 2024 15:59:12 +0300 Subject: [PATCH 13/13] adc: primary plot cannot be deleted - fixed MapStackedWidget not updating size based on content size Signed-off-by: Andrei Popa --- gui/include/gui/mapstackedwidget.h | 4 ++++ gui/src/mapstackedwidget.cpp | 16 ++++++++++++++++ .../adc/src/time/timeplotcomponentsettings.cpp | 6 ++++++ plugins/adc/src/time/timeplotcomponentsettings.h | 1 + plugins/adc/src/time/timeplotmanager.cpp | 5 ++++- 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/gui/include/gui/mapstackedwidget.h b/gui/include/gui/mapstackedwidget.h index 27c7ce915f..00608bb647 100644 --- a/gui/include/gui/mapstackedwidget.h +++ b/gui/include/gui/mapstackedwidget.h @@ -19,6 +19,10 @@ class SCOPY_GUI_EXPORT MapStackedWidget : public QStackedWidget virtual QString getKey(QWidget *w); virtual bool contains(QString key); virtual QWidget *get(QString key); + + QSize sizeHint() const override; + QSize minimumSizeHint() const override; + public Q_SLOTS: virtual bool show(QString key); diff --git a/gui/src/mapstackedwidget.cpp b/gui/src/mapstackedwidget.cpp index d6340fc273..701557fbe4 100644 --- a/gui/src/mapstackedwidget.cpp +++ b/gui/src/mapstackedwidget.cpp @@ -50,6 +50,22 @@ QWidget *MapStackedWidget::get(QString key) return nullptr; } +QSize MapStackedWidget::sizeHint() const +{ + if(currentWidget()) { + return currentWidget()->sizeHint(); + } + return QStackedWidget::sizeHint(); +} + +QSize MapStackedWidget::minimumSizeHint() const +{ + if(currentWidget()) { + return currentWidget()->minimumSizeHint(); + } + return QStackedWidget::minimumSizeHint(); +} + bool MapStackedWidget::show(QString key) { QWidget *w = map[key]; diff --git a/plugins/adc/src/time/timeplotcomponentsettings.cpp b/plugins/adc/src/time/timeplotcomponentsettings.cpp index 3079a2b74e..098dce6bac 100644 --- a/plugins/adc/src/time/timeplotcomponentsettings.cpp +++ b/plugins/adc/src/time/timeplotcomponentsettings.cpp @@ -162,6 +162,12 @@ TimePlotComponentSettings::TimePlotComponentSettings(TimePlotComponent *plt, QWi } void TimePlotComponentSettings::showDeleteButtons(bool b) +{ + m_deletePlotHover->setVisible(b); + m_deletePlot->setVisible(b); +} + +void TimePlotComponentSettings::showPlotButtons(bool b) { m_plotComponent->timePlot()->plotButtonManager()->setVisible(b); m_deletePlot->setVisible(b); diff --git a/plugins/adc/src/time/timeplotcomponentsettings.h b/plugins/adc/src/time/timeplotcomponentsettings.h index a0eb13e6e5..b4b9fe4967 100644 --- a/plugins/adc/src/time/timeplotcomponentsettings.h +++ b/plugins/adc/src/time/timeplotcomponentsettings.h @@ -19,6 +19,7 @@ class SCOPY_ADC_EXPORT TimePlotComponentSettings : public QWidget, public ToolCo ~TimePlotComponentSettings(); void showDeleteButtons(bool b); + void showPlotButtons(bool b); public Q_SLOTS: void addChannel(ChannelComponent *c); diff --git a/plugins/adc/src/time/timeplotmanager.cpp b/plugins/adc/src/time/timeplotmanager.cpp index c6fd0f011b..77f977c3cf 100644 --- a/plugins/adc/src/time/timeplotmanager.cpp +++ b/plugins/adc/src/time/timeplotmanager.cpp @@ -86,7 +86,10 @@ void TimePlotManager::multiPlotUpdate() for(PlotComponent *p : qAsConst(m_plots)) { auto plt = dynamic_cast(p); - plt->plotMenu()->showDeleteButtons(b); + plt->plotMenu()->showPlotButtons(b); + + // do not allow users to delete the primary plot + plt->plotMenu()->showDeleteButtons(b && plt != m_primary); } for(PlotManagerCombobox *cb : m_channelPlotcomboMap) {