diff --git a/gui/style/qss/properties/widget/tableViewWidget.qss b/gui/style/qss/properties/widget/tableViewWidget.qss index 0a4ac86ccd..a23700f5d2 100644 --- a/gui/style/qss/properties/widget/tableViewWidget.qss +++ b/gui/style/qss/properties/widget/tableViewWidget.qss @@ -1,9 +1,18 @@ -QHeaderView::section[&&property&&=true] { - border: 1px solid &content_default&; - background-color: &background_primary&; +QTableWidget QHeaderView::section { + background-color: &background_primary&; + border: 1px solid &background_secondary&; } -QTableWidget::item[&&property&&=true] { - border-right: 1px dashed &content_default&; - border-bottom: 1px dashed &content_default&; +QTableWidget QTableCornerButton::section { + background-color: &background_primary&; + border: 1px solid &background_secondary&; +} + +QTableWidget { + gridline-color: &background_secondary&; +} + +QTableWidget::item:selected { + background-color: &interactive_primary_hover&; + color: &content_inverse&; } diff --git a/packages/pqmon/plugins/pqm/include/pqm/acquisitionmanager.h b/packages/pqmon/plugins/pqm/include/pqm/acquisitionmanager.h index bd1ab1e416..0c12997ea4 100644 --- a/packages/pqmon/plugins/pqm/include/pqm/acquisitionmanager.h +++ b/packages/pqmon/plugins/pqm/include/pqm/acquisitionmanager.h @@ -66,6 +66,8 @@ private Q_SLOTS: double convertFromHwToHost(int value, QString chnlId); void enableBufferChnls(iio_device *dev); void readData(); + void readAttrData(); + void readBuffData(); bool readPqmAttributes(); bool readBufferedData(); void setData(QMap>); @@ -95,6 +97,8 @@ private Q_SLOTS: bool m_attrHaveBeenRead = false; bool m_buffHaveBeenRead = false; bool m_hasFwVers = false; + bool m_concurrentAcq = false; + bool m_alternateExecution = false; const int THREAD_FINISH_TIMEOUT = 10000; }; } // namespace scopy::pqm diff --git a/packages/pqmon/plugins/pqm/include/pqm/attrinstrumenthandler.h b/packages/pqmon/plugins/pqm/include/pqm/attrinstrumenthandler.h new file mode 100644 index 0000000000..ba226d3d7d --- /dev/null +++ b/packages/pqmon/plugins/pqm/include/pqm/attrinstrumenthandler.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef ATTRINSTRUMENTHANDLER_H +#define ATTRINSTRUMENTHANDLER_H + +#include +#include +#include +#include + +namespace scopy::pqm { +class AttrInstrumentHandler : public QObject, public ResourceUser +{ + Q_OBJECT +public: + AttrInstrumentHandler(QString m_uri, QObject *parent = nullptr); + ~AttrInstrumentHandler(); + + void stop() override; + + void setHarmonicsInstrument(HarmonicsInstrument *newHarmonicsInstrument); + + void setRmsInstrument(RmsInstrument *newRmsInstrument); + +public Q_SLOTS: + void onToggle(bool en, const QString &tool); + void concurrentEnable(QString pref, QVariant value); + +private: + bool isAnyToolRunning(); + void resourceManagerCheck(bool en); + void resetValues(); + + QMap m_runningMap = {{RMS_TOOL, false}, {HARMONICS_TOOL, false}}; + bool m_concurrentAcq = false; + bool m_resourceLock = false; + QString m_uri; + HarmonicsInstrument *m_harmonicsInstrument = nullptr; + RmsInstrument *m_rmsInstrument = nullptr; +}; +} // namespace scopy::pqm + +#endif // ATTRINSTRUMENTHANDLER_H diff --git a/packages/pqmon/plugins/pqm/include/pqm/harmonicsinstrument.h b/packages/pqmon/plugins/pqm/include/pqm/harmonicsinstrument.h index bb57d129e2..0b45c4a41b 100644 --- a/packages/pqmon/plugins/pqm/include/pqm/harmonicsinstrument.h +++ b/packages/pqmon/plugins/pqm/include/pqm/harmonicsinstrument.h @@ -30,19 +30,20 @@ #include #include #include +#include #include #include #include #include -#include #define NUMBER_OF_HARMONICS 51 #define HARMONICS_MIN_DEGREE 0 #define HARMONICS_MAX_DEGREE 50 #define MAX_CHNLS 6 +#define HARMONICS_TOOL "harmonics" namespace scopy::pqm { -class SCOPY_PQM_EXPORT HarmonicsInstrument : public QWidget, public ResourceUser +class SCOPY_PQM_EXPORT HarmonicsInstrument : public QWidget { Q_OBJECT public: @@ -50,14 +51,23 @@ class SCOPY_PQM_EXPORT HarmonicsInstrument : public QWidget, public ResourceUser ~HarmonicsInstrument(); void showThdWidget(bool show); + public Q_SLOTS: - void stop() override; + void stop(); void toggleHarmonics(bool en); void onAttrAvailable(QMap> attr); + Q_SIGNALS: - void enableTool(bool en, QString toolName = "harmonics"); + void enableTool(bool en, QString toolName = HARMONICS_TOOL); void logData(PqmDataLogger::ActiveInstrument instr, const QString &filePath); void pqEvent(); + void showPlots(bool show); + + // Emitted when this instrument requests other instruments to reset their event buttons + void resetEventsRequest(); + // Received signal to reset this instrument's event button + void resetEventsBtn(); + private Q_SLOTS: void updateTable(); void onActiveChnlChannged(QString chnlId); @@ -66,15 +76,19 @@ private Q_SLOTS: private: void initData(); void initTable(); - void initPlot(); - void setupPlotChannels(); - QWidget *createThdWidget(); + void initPlot(PlotWidget *plot); + void createCurrentPlots(QWidget *parent = nullptr); + QMap setupPlotChannels(PlotWidget *plot, const QMap &channels, + int startChIndex = 0); + void concurrentEnable(QString pref, QVariant value); + QWidget *createThdWidget(QWidget *parent = nullptr); QWidget *createSettingsMenu(QWidget *parent); QWidget *createMenuGeneralSection(QWidget *parent); QWidget *createMenuLogSection(QWidget *parent); bool selectedFromSameCol(QModelIndexList list); QPushButton *createPQEventsBtn(QWidget *parent); + DockableAreaInterface *m_dockableArea; QString m_uri; bool m_running; QString m_harmonicsType; @@ -83,6 +97,7 @@ private Q_SLOTS: SingleShotBtn *m_singleBtn; QTableWidget *m_table; PlotWidget *m_plot; + QMap m_currentPlots; std::vector m_xTime; QMap> m_yValues; QMap m_labels; diff --git a/packages/pqmon/plugins/pqm/include/pqm/pqmplugin.h b/packages/pqmon/plugins/pqm/include/pqm/pqmplugin.h index cd37fd172e..48778eea82 100644 --- a/packages/pqmon/plugins/pqm/include/pqm/pqmplugin.h +++ b/packages/pqmon/plugins/pqm/include/pqm/pqmplugin.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,8 @@ class SCOPY_PQM_EXPORT PQMPlugin : public QObject, public PluginBase public: void preload() override; bool compatible(QString m_param, QString category) override; + void initPreferences() override; + bool loadPreferencesPage() override; bool loadPage() override; bool loadIcon() override; void loadToolList() override; @@ -61,6 +64,7 @@ public Q_SLOTS: InfoPage *m_infoPage; AcquisitionManager *m_acqManager; + AttrInstrumentHandler *m_attrHandler; }; } // namespace scopy::pqm diff --git a/packages/pqmon/plugins/pqm/include/pqm/rmsinstrument.h b/packages/pqmon/plugins/pqm/include/pqm/rmsinstrument.h index 0b5461c6d9..0dfc21c96a 100644 --- a/packages/pqmon/plugins/pqm/include/pqm/rmsinstrument.h +++ b/packages/pqmon/plugins/pqm/include/pqm/rmsinstrument.h @@ -31,13 +31,13 @@ #include #include #include -#include #include #define DEVICE_NAME "pqm" +#define RMS_TOOL "rms" namespace scopy::pqm { -class SCOPY_PQM_EXPORT RmsInstrument : public QWidget, public ResourceUser +class SCOPY_PQM_EXPORT RmsInstrument : public QWidget { Q_OBJECT public: @@ -46,11 +46,16 @@ class SCOPY_PQM_EXPORT RmsInstrument : public QWidget, public ResourceUser Q_SIGNALS: void pqEvent(); - void enableTool(bool en, QString toolName = "rms"); + void enableTool(bool en, QString toolName = RMS_TOOL); void logData(PqmDataLogger::ActiveInstrument instr, const QString &filePath); + // Emitted when this instrument requests other instruments to reset their event buttons + void resetEventsRequest(); + // Received signal to reset this instrument's event button + void resetEventsBtn(); + public Q_SLOTS: - void stop() override; + void stop(); void toggleRms(bool en); void onAttrAvailable(QMap> data); diff --git a/packages/pqmon/plugins/pqm/include/pqm/waveforminstrument.h b/packages/pqmon/plugins/pqm/include/pqm/waveforminstrument.h index 18c3fb8191..f80ccf53a2 100644 --- a/packages/pqmon/plugins/pqm/include/pqm/waveforminstrument.h +++ b/packages/pqmon/plugins/pqm/include/pqm/waveforminstrument.h @@ -67,6 +67,8 @@ private Q_SLOTS: void initData(); void initPlot(PlotWidget *plot, QString unitType, int yMin = -650, int yMax = 650); void setupChannels(PlotWidget *plot, QMap chnls); + void resourceManagerCheck(bool en); + void concurrentEnable(QString pref, QVariant value); QWidget *createSettMenu(QWidget *parent); QWidget *createMenuLogSection(QWidget *parent); QWidget *createMenuPlotSection(QWidget *parent); @@ -76,6 +78,7 @@ private Q_SLOTS: void deletePlottingStrategy(); void createTriggeredStrategy(QString triggerChnl); + bool m_concurrentAcq = false; bool m_running; PlotWidget *m_voltagePlot; PlotWidget *m_currentPlot; diff --git a/packages/pqmon/plugins/pqm/src/acquisitionmanager.cpp b/packages/pqmon/plugins/pqm/src/acquisitionmanager.cpp index 683422b3f1..a742bae095 100644 --- a/packages/pqmon/plugins/pqm/src/acquisitionmanager.cpp +++ b/packages/pqmon/plugins/pqm/src/acquisitionmanager.cpp @@ -23,6 +23,7 @@ #include "qtconcurrentrun.h" #include #include +#include Q_LOGGING_CATEGORY(CAT_PQM_ACQ, "PqmAqcManager"); using namespace scopy::pqm; @@ -34,6 +35,8 @@ AcquisitionManager::AcquisitionManager(iio_context *ctx, PingTask *pingTask, QOb , m_buffer(nullptr) , m_pqmLog(nullptr) { + Preferences *p = Preferences::GetInstance(); + m_concurrentAcq = p->get("pqm_concurrent").toBool(); m_readFw = new QFutureWatcher(this); m_setFw = new QFutureWatcher(this); iio_device *dev = iio_context_find_device(m_ctx, DEVICE_PQM); @@ -53,6 +56,12 @@ AcquisitionManager::AcquisitionManager(iio_context *ctx, PingTask *pingTask, QOb connect(m_readFw, &QFutureWatcher::finished, this, &AcquisitionManager::onReadFinished, Qt::QueuedConnection); connect(this, &AcquisitionManager::logData, m_pqmLog, &PqmDataLogger::logPressed); + connect(p, &Preferences::preferenceChanged, this, [this](QString pref, QVariant value) { + if(pref == "pqm_concurrent") { + m_concurrentAcq = value.toBool(); + m_alternateExecution = !m_concurrentAcq; + } + }); } else { qWarning(CAT_PQM_ACQ) << "The PQM device is not available!"; } @@ -132,19 +141,41 @@ void AcquisitionManager::futureReadData() void AcquisitionManager::readData() { QMutexLocker locker(&m_mutex); - if(m_tools["rms"] || m_tools["harmonics"] || m_tools["settings"]) { - if(!m_processData.load()) { - setProcessData(true); + + bool needsAttrData = m_tools["rms"] || m_tools["harmonics"] || m_tools["settings"]; + bool needsBufferData = m_tools["waveform"]; + if(m_concurrentAcq && needsAttrData && needsBufferData) { + if(m_alternateExecution) { + readBuffData(); + } else { + readAttrData(); } - m_attrHaveBeenRead = readPqmAttributes(); - adjustMap("angle", &AcquisitionManager::computeAdjustedAngle); - } - if(m_tools["waveform"]) { - if(m_processData.load()) { - setProcessData(false); + m_alternateExecution = !m_alternateExecution; + } else { + if(needsAttrData) { + readAttrData(); } - m_buffHaveBeenRead = readBufferedData(); + if(needsBufferData) { + readBuffData(); + } + } +} + +void AcquisitionManager::readAttrData() +{ + if(!m_processData.load()) { + setProcessData(true); + } + m_attrHaveBeenRead = readPqmAttributes(); + adjustMap("angle", &AcquisitionManager::computeAdjustedAngle); +} + +void AcquisitionManager::readBuffData() +{ + if(m_processData.load()) { + setProcessData(false); } + m_buffHaveBeenRead = readBufferedData(); } bool AcquisitionManager::readPqmAttributes() diff --git a/packages/pqmon/plugins/pqm/src/attrinstrumenthandler.cpp b/packages/pqmon/plugins/pqm/src/attrinstrumenthandler.cpp new file mode 100644 index 0000000000..b42205d9af --- /dev/null +++ b/packages/pqmon/plugins/pqm/src/attrinstrumenthandler.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "attrinstrumenthandler.h" +#include + +using namespace scopy::pqm; + +AttrInstrumentHandler::AttrInstrumentHandler(QString uri, QObject *parent) + : QObject(parent) + , m_uri(uri) +{ + m_concurrentAcq = Preferences::get("pqm_concurrent").toBool(); + connect(Preferences::GetInstance(), &Preferences::preferenceChanged, this, + &AttrInstrumentHandler::concurrentEnable); +} + +AttrInstrumentHandler::~AttrInstrumentHandler() { ResourceManager::close("pqm" + m_uri); } + +void AttrInstrumentHandler::stop() +{ + if(m_harmonicsInstrument) { + m_harmonicsInstrument->stop(); + } + if(m_rmsInstrument) { + m_rmsInstrument->stop(); + } + resetValues(); +} + +void AttrInstrumentHandler::onToggle(bool en, const QString &tool) +{ + m_runningMap[tool] = en; + if(!m_concurrentAcq) { + resourceManagerCheck(en); + } +} + +void AttrInstrumentHandler::concurrentEnable(QString pref, QVariant value) +{ + if(pref != "pqm_concurrent") { + return; + } + m_concurrentAcq = value.toBool(); + if(!m_concurrentAcq && m_rmsInstrument && m_harmonicsInstrument) { + m_rmsInstrument->stop(); + m_harmonicsInstrument->stop(); + } +} + +bool AttrInstrumentHandler::isAnyToolRunning() { return m_runningMap[HARMONICS_TOOL] || m_runningMap[RMS_TOOL]; } + +void AttrInstrumentHandler::resourceManagerCheck(bool en) +{ + if(en && !m_resourceLock) { + ResourceManager::open("pqm" + m_uri, this); + m_resourceLock = true; + } else if(!en && m_resourceLock) { + if(isAnyToolRunning()) { + return; + } + ResourceManager::close("pqm" + m_uri); + m_resourceLock = false; + } +} + +void AttrInstrumentHandler::resetValues() +{ + m_resourceLock = false; + m_runningMap[HARMONICS_TOOL] = false; + m_runningMap[RMS_TOOL] = false; +} + +void AttrInstrumentHandler::setRmsInstrument(RmsInstrument *newRmsInstrument) +{ + if(m_rmsInstrument) { + return; + } + m_rmsInstrument = newRmsInstrument; + connect(m_rmsInstrument, &RmsInstrument::enableTool, this, &AttrInstrumentHandler::onToggle); +} + +void AttrInstrumentHandler::setHarmonicsInstrument(HarmonicsInstrument *newHarmonicsInstrument) +{ + if(m_harmonicsInstrument) { + return; + } + m_harmonicsInstrument = newHarmonicsInstrument; + connect(m_harmonicsInstrument, &HarmonicsInstrument::enableTool, this, &AttrInstrumentHandler::onToggle); +} diff --git a/packages/pqmon/plugins/pqm/src/harmonicsinstrument.cpp b/packages/pqmon/plugins/pqm/src/harmonicsinstrument.cpp index 6cf936f672..5eade7bb73 100644 --- a/packages/pqmon/plugins/pqm/src/harmonicsinstrument.cpp +++ b/packages/pqmon/plugins/pqm/src/harmonicsinstrument.cpp @@ -20,6 +20,9 @@ */ #include "harmonicsinstrument.h" +#include "dockablearea.h" +#include "dockwrapper.h" +#include "menuonoffswitch.h" #include "plotaxis.h" #include "qheaderview.h" @@ -36,6 +39,7 @@ #include #include +using namespace scopy; using namespace scopy::pqm; HarmonicsInstrument::HarmonicsInstrument(ToolMenuEntry *tme, QString uri, QWidget *parent) @@ -64,19 +68,45 @@ HarmonicsInstrument::HarmonicsInstrument(ToolMenuEntry *tme, QString uri, QWidge QDesktopServices::openUrl(QUrl("https://analogdevicesinc.github.io/scopy/plugins/pqm/harmonics.html")); }); - // central widget components - m_thdWidget = createThdWidget(); - tool->addWidgetToCentralContainerHelper(m_thdWidget); + // create dockable area + m_dockableArea = createDockableArea(this); + QWidget *dockableAreaWidget = dynamic_cast(m_dockableArea); + Style::setBackgroundColor(dockableAreaWidget, json::theme::background_subtle, true); + QScrollArea *scrollArea = new QScrollArea(this); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(dockableAreaWidget); + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_table = new QTableWidget(MAX_CHNLS, NUMBER_OF_HARMONICS, this); - Style::setBackgroundColor(m_table, Style::getAttribute(json::theme::background_primary), true); + // central widget components + DockWrapperInterface *tableDock = createDockWrapper("Table"); + QWidget *tableWrapper = new QWidget(dockableAreaWidget); + tableWrapper->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + QVBoxLayout *tableWrapLay = new QVBoxLayout(tableWrapper); + tableWrapLay->setMargin(0); + tableWrapLay->setSpacing(0); + + m_thdWidget = createThdWidget(tableWrapper); + + m_table = new QTableWidget(MAX_CHNLS, NUMBER_OF_HARMONICS, dockableAreaWidget); + Style::setBackgroundColor(m_table, Style::getAttribute(json::theme::background_plot), true); + Style::setStyle(m_table, style::properties::widget::tableViewWidget); initTable(); - tool->addWidgetToCentralContainerHelper(m_table); - m_plot = new PlotWidget(this); - initPlot(); - setupPlotChannels(); - tool->addWidgetToCentralContainerHelper(m_plot); + tableWrapLay->addWidget(m_thdWidget); + tableWrapLay->addWidget(m_table); + tableDock->setInnerWidget(tableWrapper); + + DockWrapperInterface *plotDock = createDockWrapper("Harmonics Overview"); + m_plot = new PlotWidget(dockableAreaWidget); + initPlot(m_plot); + m_plotChnls = setupPlotChannels(m_plot, m_chnls); + plotDock->setInnerWidget(m_plot); + + // Create individual current plots for ia, ib, ic + createCurrentPlots(dockableAreaWidget); + m_dockableArea->addDockWrapper(plotDock, DockableAreaInterface::Direction_TOP); + plotDock->setActivated(false); + m_dockableArea->addDockWrapper(tableDock, DockableAreaInterface::Direction_TOP); // instrument menu GearBtn *settingsMenuBtn = new GearBtn(this); @@ -92,12 +122,19 @@ HarmonicsInstrument::HarmonicsInstrument(ToolMenuEntry *tme, QString uri, QWidge pqEventsBtn->setChecked(m_running); } }); + connect(this, &HarmonicsInstrument::resetEventsBtn, this, [this, pqEventsBtn]() { + if(pqEventsBtn->isChecked()) { + pqEventsBtn->setChecked(false); + } + }); + tool->addWidgetToCentralContainerHelper(scrollArea); tool->addWidgetToTopContainerHelper(m_runBtn, TTA_RIGHT); tool->addWidgetToTopContainerHelper(m_singleBtn, TTA_RIGHT); tool->addWidgetToTopContainerHelper(settingsMenuBtn, TTA_RIGHT); tool->addWidgetToTopContainerHelper(pqEventsBtn, TTA_LEFT); + connect(this, &HarmonicsInstrument::showPlots, this, [plotDock](bool en) { plotDock->setActivated(en); }); connect(m_tme, &ToolMenuEntry::runClicked, m_runBtn, &QAbstractButton::setChecked); connect(this, &HarmonicsInstrument::enableTool, m_tme, &ToolMenuEntry::setRunning); connect(m_runBtn, &QAbstractButton::toggled, m_singleBtn, &QAbstractButton::setDisabled); @@ -112,7 +149,6 @@ HarmonicsInstrument::~HarmonicsInstrument() m_yValues.clear(); m_labels.clear(); m_plotChnls.clear(); - ResourceManager::close("pqm" + m_uri); } void HarmonicsInstrument::showThdWidget(bool show) { m_thdWidget->setVisible(show); } @@ -130,6 +166,7 @@ void HarmonicsInstrument::initData() void HarmonicsInstrument::initTable() { m_table->setVerticalHeaderLabels(m_chnls.keys()); + m_table->verticalHeader()->setMinimumWidth(50); m_table->verticalHeader()->setDefaultAlignment(Qt::AlignCenter); m_table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_table->setFixedHeight(220); @@ -142,7 +179,6 @@ void HarmonicsInstrument::initTable() for(int i = 0; i < HARMONICS_MIN_DEGREE; i++) { m_table->horizontalHeader()->hideSection(i); } - Style::setStyle(m_table->parentWidget(), style::properties::widget::tableViewWidget, true, true); for(int i = 0; i < MAX_CHNLS; i++) { for(int j = 0; j < NUMBER_OF_HARMONICS; j++) { QTableWidgetItem *tableItem = new QTableWidgetItem(); @@ -152,56 +188,76 @@ void HarmonicsInstrument::initTable() } } -void HarmonicsInstrument::initPlot() +void HarmonicsInstrument::initPlot(PlotWidget *plot) { - m_plot->yAxis()->scaleDraw()->setFormatter(new MetricPrefixFormatter()); - m_plot->yAxis()->scaleDraw()->setFloatPrecision(2); - m_plot->yAxis()->scaleDraw()->setUnitType("%"); - m_plot->yAxis()->setInterval(0, 100); - - m_plot->xAxis()->scaleDraw()->setFormatter(new MetricPrefixFormatter()); - m_plot->xAxis()->scaleDraw()->setFloatPrecision(0); - m_plot->xAxis()->scaleDraw()->setUnitType(""); - m_plot->xAxis()->setInterval(HARMONICS_MIN_DEGREE, HARMONICS_MAX_DEGREE); - - m_plot->setShowYAxisLabels(true); - m_plot->setShowXAxisLabels(true); - m_plot->replot(); + plot->yAxis()->scaleDraw()->setFormatter(new MetricPrefixFormatter()); + plot->yAxis()->scaleDraw()->setFloatPrecision(2); + plot->yAxis()->scaleDraw()->setUnitType("%"); + plot->yAxis()->setInterval(0, 100); + + plot->xAxis()->scaleDraw()->setFormatter(new MetricPrefixFormatter()); + plot->xAxis()->scaleDraw()->setFloatPrecision(0); + plot->xAxis()->scaleDraw()->setUnitType(""); + plot->xAxis()->setInterval(HARMONICS_MIN_DEGREE, HARMONICS_MAX_DEGREE); + + plot->setShowYAxisLabels(true); + plot->setShowXAxisLabels(true); + plot->replot(); +} + +void HarmonicsInstrument::createCurrentPlots(QWidget *parent) +{ + QStringList currentChannels = {"ia", "ib", "ic"}; + int chIdx = 0; + for(const QString &channel : currentChannels) { + DockWrapperInterface *currentDock = createDockWrapper(m_chnls.key(channel)); + PlotWidget *currentPlot = new PlotWidget(parent); + initPlot(currentPlot); + QMap singleChannel = {{m_chnls.key(channel), channel}}; + setupPlotChannels(currentPlot, singleChannel, chIdx); + currentDock->setInnerWidget(currentPlot); + m_currentPlots[channel] = currentPlot; + m_dockableArea->addDockWrapper(currentDock, DockableAreaInterface::Direction_BOTTOM); + chIdx++; + } } -void HarmonicsInstrument::setupPlotChannels() +QMap +HarmonicsInstrument::setupPlotChannels(PlotWidget *plot, const QMap &channels, int startChIndex) { - int chNumber = 0; + QMap plotChannels; + int chNumber = startChIndex; bool first = true; - for(const QString &ch : m_chnls) { + for(const QString &ch : channels) { QPen chPen = QPen(QColor(StyleHelper::getChannelColor(chNumber)), 1); - PlotChannel *plotCh = new PlotChannel(m_chnls.key(ch), chPen, m_plot->xAxis(), m_plot->yAxis(), this); - m_plot->addPlotChannel(plotCh); + PlotChannel *plotCh = new PlotChannel(channels.key(ch), chPen, plot->xAxis(), plot->yAxis(), this); + plot->addPlotChannel(plotCh); plotCh->setStyle(PlotChannel::PCS_STICKS); plotCh->setThickness(10); plotCh->curve()->setRawSamples(m_xTime.data(), m_yValues[ch].data(), m_xTime.size()); - m_plotChnls[ch] = plotCh; + plotChannels.insert(ch, plotCh); if(first) { plotCh->setEnabled(true); - m_plot->selectChannel(plotCh); + plot->selectChannel(plotCh); first = false; } chNumber++; } + return plotChannels; } -QWidget *HarmonicsInstrument::createThdWidget() +QWidget *HarmonicsInstrument::createThdWidget(QWidget *parent) { - QWidget *thdWidget = new QWidget(this); + QWidget *thdWidget = new QWidget(parent); thdWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); QGridLayout *layout = new QGridLayout(thdWidget); - QLabel *title = new QLabel("THD:", this); + QLabel *title = new QLabel("THD:", thdWidget); layout->addWidget(title); int row = 1; int chnlIdx = 0; for(const QString &ch : m_chnls) { - MeasurementLabel *ml = new MeasurementLabel(this); + MeasurementLabel *ml = new MeasurementLabel(thdWidget); QString color = StyleHelper::getChannelColor(chnlIdx); ml->setColor(QColor(color)); ml->setName(m_chnls.key(ch)); @@ -251,6 +307,11 @@ QWidget *HarmonicsInstrument::createMenuGeneralSection(QWidget *parent) activeChnlCb->combo()->addItem(m_chnls.key(ch)); } m_table->selectRow(0); + + MenuOnOffSwitch *showCurrentPlots = new MenuOnOffSwitch(tr("Show overview plot"), generalSection); + showCurrentPlots->onOffswitch()->setChecked(false); + + connect(showCurrentPlots->onOffswitch(), &QAbstractButton::toggled, this, &HarmonicsInstrument::showPlots); connect(activeChnlCb->combo(), &QComboBox::currentTextChanged, this, &HarmonicsInstrument::onActiveChnlChannged); connect(activeChnlCb->combo(), QOverload::of(&QComboBox::activated), m_table, &QTableView::selectRow); @@ -261,6 +322,7 @@ QWidget *HarmonicsInstrument::createMenuGeneralSection(QWidget *parent) generalSection->add(harmonicType); generalSection->add(activeChnlCb); + generalSection->add(showCurrentPlots); return generalSection; } @@ -324,11 +386,6 @@ void HarmonicsInstrument::stop() { m_runBtn->setChecked(false); } void HarmonicsInstrument::toggleHarmonics(bool en) { m_running = en; - if(en) { - ResourceManager::open("pqm" + m_uri, this); - } else { - ResourceManager::close("pqm" + m_uri); - } Q_EMIT enableTool(en); } bool HarmonicsInstrument::selectedFromSameCol(QModelIndexList list) @@ -371,10 +428,12 @@ void HarmonicsInstrument::onAttrAvailable(QMap> m_yValues[ch].clear(); for(const QString &val : qAsConst(harmonics)) { double hValue = val.toDouble(&ok); - if(!ok) + if(!ok) { continue; - if(m_yValues[ch].size() >= NUMBER_OF_HARMONICS) + } + if(m_yValues[ch].size() >= NUMBER_OF_HARMONICS) { break; + } m_yValues[ch].push_back(hValue); } // thd labels update @@ -382,6 +441,9 @@ void HarmonicsInstrument::onAttrAvailable(QMap> } updateTable(); m_plot->replot(); + for(PlotWidget *plot : m_currentPlots) { + plot->replot(); + } if(m_singleBtn->isChecked()) { m_singleBtn->setChecked(false); } @@ -405,6 +467,7 @@ QPushButton *HarmonicsInstrument::createPQEventsBtn(QWidget *parent) btn->setIcon(bellIcon); btn->setLayoutDirection(Qt::RightToLeft); connect(btn, &QPushButton::toggled, btn, &QPushButton::setEnabled); + connect(btn, &QPushButton::clicked, this, &HarmonicsInstrument::resetEventsRequest); return btn; } diff --git a/packages/pqmon/plugins/pqm/src/pqmplugin.cpp b/packages/pqmon/plugins/pqm/src/pqmplugin.cpp index b66e4e34ed..9cb02b7a0f 100644 --- a/packages/pqmon/plugins/pqm/src/pqmplugin.cpp +++ b/packages/pqmon/plugins/pqm/src/pqmplugin.cpp @@ -20,6 +20,7 @@ */ #include "pqmplugin.h" +#include "preferenceshelper.h" #include "scopy-pqm_config.h" #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +64,33 @@ bool PQMPlugin::compatible(QString m_param, QString category) return ret; } +void PQMPlugin::initPreferences() +{ + Preferences *p = Preferences::GetInstance(); + p->init("pqm_concurrent", false); +} + +bool PQMPlugin::loadPreferencesPage() +{ + Preferences *p = Preferences::GetInstance(); + m_preferencesPage = new QWidget(); + QVBoxLayout *layout = new QVBoxLayout(m_preferencesPage); + + MenuSectionCollapseWidget *generalSection = new MenuSectionCollapseWidget( + "General", MenuCollapseSection::MHCW_NONE, MenuCollapseSection::MHW_BASEWIDGET); + generalSection->contentLayout()->setSpacing(10); + layout->addWidget(generalSection); + layout->setSpacing(0); + layout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + auto concurrentAcq = + PREFERENCE_CHECK_BOX(p, "pqm_concurrent", "Enable Concurrent Acquisition (EXPERIMENTAL)", + "Enable concurrent acquisition for PQMPlugin instruments.", generalSection); + + generalSection->contentLayout()->addWidget(concurrentAcq); + return true; +} + bool PQMPlugin::loadPage() { @@ -146,6 +175,8 @@ bool PQMPlugin::onConnect() m_acqManager = new AcquisitionManager(ctx, m_pingTask, this); bool hasFwVers = m_acqManager->hasFwVers(); + m_attrHandler = new AttrInstrumentHandler(m_param, this); + ToolMenuEntry *rmsTme = ToolMenuEntry::findToolMenuEntryById(m_toolList, "pqmrms"); RmsInstrument *rms = new RmsInstrument(rmsTme, m_param); rmsTme->setTool(rms); @@ -183,6 +214,12 @@ bool PQMPlugin::onConnect() &SettingsInstrument::attributeAvailable); connect(settings, &SettingsInstrument::setAttributes, m_acqManager, &AcquisitionManager::setConfigAttr); + connect(rms, &RmsInstrument::resetEventsRequest, harmonics, &HarmonicsInstrument::resetEventsBtn); + connect(harmonics, &HarmonicsInstrument::resetEventsRequest, rms, &RmsInstrument::resetEventsBtn); + + m_attrHandler->setRmsInstrument(rms); + m_attrHandler->setHarmonicsInstrument(harmonics); + for(auto &tool : m_toolList) { connect(tool->tool(), SIGNAL(enableTool(bool, QString)), m_acqManager, SLOT(toolEnabled(bool, QString))); @@ -204,6 +241,8 @@ bool PQMPlugin::onDisconnect() } delete(m_acqManager); m_acqManager = nullptr; + delete(m_attrHandler); + m_attrHandler = nullptr; clearPingTask(); ConnectionProvider *cp = ConnectionProvider::GetInstance(); cp->close(m_param); diff --git a/packages/pqmon/plugins/pqm/src/rmsinstrument.cpp b/packages/pqmon/plugins/pqm/src/rmsinstrument.cpp index 63d3b0e12c..229f3fa04f 100644 --- a/packages/pqmon/plugins/pqm/src/rmsinstrument.cpp +++ b/packages/pqmon/plugins/pqm/src/rmsinstrument.cpp @@ -130,6 +130,11 @@ RmsInstrument::RmsInstrument(ToolMenuEntry *tme, QString uri, QWidget *parent) pqEventsBtn->setChecked(m_running); } }); + connect(this, &RmsInstrument::resetEventsBtn, this, [this, pqEventsBtn]() { + if(pqEventsBtn->isChecked()) { + pqEventsBtn->setChecked(false); + } + }); tool->addWidgetToTopContainerHelper(m_runBtn, TTA_RIGHT); tool->addWidgetToTopContainerHelper(m_singleBtn, TTA_RIGHT); @@ -148,7 +153,6 @@ RmsInstrument::~RmsInstrument() { m_labels.clear(); m_attributes.clear(); - ResourceManager::close("pqm" + m_uri); } void RmsInstrument::createLabels(MeasurementsPanel *mPanel, QStringList chnls, QStringList labels, QString color) @@ -254,11 +258,6 @@ void RmsInstrument::stop() { m_runBtn->setChecked(false); } void RmsInstrument::toggleRms(bool en) { m_running = en; - if(en) { - ResourceManager::open("pqm" + m_uri, this); - } else { - ResourceManager::close("pqm" + m_uri); - } Q_EMIT enableTool(en); } @@ -340,6 +339,7 @@ QPushButton *RmsInstrument::createPQEventsBtn(QWidget *parent) btn->setIcon(bellIcon); btn->setLayoutDirection(Qt::RightToLeft); connect(btn, &QPushButton::toggled, btn, &QPushButton::setEnabled); + connect(btn, &QPushButton::clicked, this, &RmsInstrument::resetEventsRequest); return btn; } diff --git a/packages/pqmon/plugins/pqm/src/waveforminstrument.cpp b/packages/pqmon/plugins/pqm/src/waveforminstrument.cpp index 4e72749374..b1e58c6b5b 100644 --- a/packages/pqmon/plugins/pqm/src/waveforminstrument.cpp +++ b/packages/pqmon/plugins/pqm/src/waveforminstrument.cpp @@ -42,6 +42,7 @@ #include #include #include +#include using namespace scopy::pqm; @@ -52,6 +53,7 @@ WaveformInstrument::WaveformInstrument(ToolMenuEntry *tme, QString uri, QWidget , m_running(false) { initData(); + m_concurrentAcq = Preferences::get("pqm_concurrent").toBool(); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QHBoxLayout *layout = new QHBoxLayout(this); setLayout(layout); @@ -114,6 +116,8 @@ WaveformInstrument::WaveformInstrument(ToolMenuEntry *tme, QString uri, QWidget connect(m_runBtn, SIGNAL(toggled(bool)), this, SLOT(toggleWaveform(bool))); connect(m_singleBtn, &QAbstractButton::toggled, m_runBtn, &QAbstractButton::setDisabled); connect(m_singleBtn, SIGNAL(toggled(bool)), this, SLOT(toggleWaveform(bool))); + connect(Preferences::GetInstance(), &Preferences::preferenceChanged, this, + &WaveformInstrument::concurrentEnable); } WaveformInstrument::~WaveformInstrument() @@ -262,16 +266,34 @@ QWidget *WaveformInstrument::createMenuLogSection(QWidget *parent) return logSection; } -void WaveformInstrument::stop() { m_runBtn->setChecked(false); } - -void WaveformInstrument::toggleWaveform(bool en) +void WaveformInstrument::resourceManagerCheck(bool en) { - m_running = en; if(en) { ResourceManager::open("pqm" + m_uri, this); } else { ResourceManager::close("pqm" + m_uri); } +} + +void WaveformInstrument::concurrentEnable(QString pref, QVariant value) +{ + if(pref != "pqm_concurrent") { + return; + } + m_concurrentAcq = value.toBool(); + if(!m_concurrentAcq) { + m_runBtn->setChecked(false); + } +} + +void WaveformInstrument::stop() { m_runBtn->setChecked(false); } + +void WaveformInstrument::toggleWaveform(bool en) +{ + m_running = en; + if(!m_concurrentAcq) { + resourceManagerCheck(en); + } m_plottingStrategy->clearSamples(); Q_EMIT enableTool(en); }