From 504b7bf4c0a6fbc4ad14d8b954631371fe56d076 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 12:09:09 +0200 Subject: [PATCH 01/41] core/device: Added iconPixmap method. Signed-off-by: andreidanila1 --- core/include/core/device.h | 1 + core/include/core/deviceimpl.h | 1 + core/src/deviceimpl.cpp | 14 ++++++++++++++ 3 files changed, 16 insertions(+) diff --git a/core/include/core/device.h b/core/include/core/device.h index 9dd382241f..53a32956f5 100644 --- a/core/include/core/device.h +++ b/core/include/core/device.h @@ -48,6 +48,7 @@ class SCOPY_CORE_EXPORT Device virtual QString param() = 0; virtual QString displayParam() = 0; virtual QWidget *icon() = 0; + virtual QPixmap iconPixmap() = 0; virtual QWidget *page() = 0; diff --git a/core/include/core/deviceimpl.h b/core/include/core/deviceimpl.h index 5b6c7b2b8b..8209bdb86e 100644 --- a/core/include/core/deviceimpl.h +++ b/core/include/core/deviceimpl.h @@ -48,6 +48,7 @@ class SCOPY_CORE_EXPORT DeviceImpl : public QObject, public Device QString category() override; QString param() override; QWidget *icon() override; + QPixmap iconPixmap() override; QWidget *page() override; QList toolList() override; virtual void init() override; diff --git a/core/src/deviceimpl.cpp b/core/src/deviceimpl.cpp index 67d6c9d01d..8b07c6a097 100644 --- a/core/src/deviceimpl.cpp +++ b/core/src/deviceimpl.cpp @@ -435,6 +435,20 @@ QString DeviceImpl::param() { return m_param; } QWidget *DeviceImpl::icon() { return m_icon; } +QPixmap DeviceImpl::iconPixmap() +{ + QPixmap pixmap; + QLayoutItem *item = m_icon->layout()->itemAt(0); + if(!item || !item->widget()) { + return pixmap; + } + QLabel *iconLabel = dynamic_cast(item->widget()); + if(iconLabel) { + pixmap = iconLabel->grab(); + } + return pixmap; +} + QWidget *DeviceImpl::page() { return m_page; } QList DeviceImpl::toolList() From 20c03b632b903fd301d5d5075fa116ca3389afb7 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 12:27:45 +0200 Subject: [PATCH 02/41] gui/res: Added led icon. Signed-off-by: andreidanila1 --- gui/res/icons/circle_led.svg | 3 +++ gui/res/resources.qrc | 1 + 2 files changed, 4 insertions(+) create mode 100644 gui/res/icons/circle_led.svg diff --git a/gui/res/icons/circle_led.svg b/gui/res/icons/circle_led.svg new file mode 100644 index 0000000000..ce5766cc7c --- /dev/null +++ b/gui/res/icons/circle_led.svg @@ -0,0 +1,3 @@ + + + diff --git a/gui/res/resources.qrc b/gui/res/resources.qrc index a571a6a331..425a3a8358 100644 --- a/gui/res/resources.qrc +++ b/gui/res/resources.qrc @@ -169,6 +169,7 @@ icons/scopy-light/icons/search.svg Arial.ttf icons/notification_bell.svg + icons/circle_led.svg icons/scopy-default/icons/search.svg From 7d562a68468f035c2700c28a0abd719e9bd4a0af Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 5 Dec 2024 17:58:43 +0200 Subject: [PATCH 03/41] style/json/global: Added led_success and led_error colors. Signed-off-by: andreidanila1 --- gui/style/json/global.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gui/style/json/global.json b/gui/style/json/global.json index 2eac1689d2..df49d14f30 100644 --- a/gui/style/json/global.json +++ b/gui/style/json/global.json @@ -31,5 +31,7 @@ "ch7": "#c7c10a", "white": "#FFFFFF", "black": "#000000", +"led_success": "#2E9E6F", +"led_error": "#F64C5A", "run_button_color": "&interactive_primary_idle&" } From 5734945d1040ec384098c68504740da72a88d11b Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 12:14:58 +0200 Subject: [PATCH 04/41] gui/widgets: Added LedButton class. Signed-off-by: andreidanila1 --- gui/include/gui/widgets/ledbutton.h | 44 +++++++++++++++++++ gui/src/widgets/ledbutton.cpp | 65 +++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 gui/include/gui/widgets/ledbutton.h create mode 100644 gui/src/widgets/ledbutton.cpp diff --git a/gui/include/gui/widgets/ledbutton.h b/gui/include/gui/widgets/ledbutton.h new file mode 100644 index 0000000000..4f5a474341 --- /dev/null +++ b/gui/include/gui/widgets/ledbutton.h @@ -0,0 +1,44 @@ +/* + * 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 LEDBUTTON_H +#define LEDBUTTON_H + +#include +#include + +namespace scopy { +class LedButton : public QPushButton +{ + Q_OBJECT +public: + LedButton(QWidget *parent = nullptr); + ~LedButton(); + + void ledOn(bool ledState, int runningTimeMsec = 100); + void ledOff(); + +private: + QTimer *m_timer; +}; +} // namespace scopy + +#endif // LEDBUTTON_H diff --git a/gui/src/widgets/ledbutton.cpp b/gui/src/widgets/ledbutton.cpp new file mode 100644 index 0000000000..c69ce5562c --- /dev/null +++ b/gui/src/widgets/ledbutton.cpp @@ -0,0 +1,65 @@ +/* + * 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 "ledbutton.h" +#include "style.h" + +using namespace scopy; + +LedButton::LedButton(QWidget *parent) + : QPushButton(parent) +{ + setCheckable(true); + setVisible(false); + setAttribute(Qt::WA_TransparentForMouseEvents, true); + QIcon ledIcon; + ledIcon.addPixmap(Style::getPixmap(":/gui/icons/circle_led.svg", Style::getColor(json::global::led_success)), + QIcon::Normal, QIcon::On); + ledIcon.addPixmap(Style::getPixmap(":/gui/icons/circle_led.svg", Style::getColor(json::global::led_error)), + QIcon::Normal, QIcon::Off); + setIcon(ledIcon); + QSize size = QSize(Style::getDimension(json::global::unit_0_5), Style::getDimension(json::global::unit_0_5)); + setIconSize(size); + setFixedSize(size); + + m_timer = new QTimer(this); + connect(m_timer, &QTimer::timeout, this, &LedButton::ledOff); +} + +LedButton::~LedButton() {} + +void LedButton::ledOn(bool ledState, int runningTimeMsec) +{ + if(m_timer->isActive()) { + return; + } + setChecked(ledState); + setVisible(true); + m_timer->start(runningTimeMsec); +} + +void LedButton::ledOff() +{ + m_timer->stop(); + setVisible(false); +} + +#include "moc_ledbutton.cpp" From f2e22712470ce7a135abab0299d8bd39d2569450 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 22 Nov 2024 08:25:12 +0200 Subject: [PATCH 05/41] iioutil: Create iioeventemitter interface. Signed-off-by: andreidanila1 --- iioutil/include/iioutil/iioeventemitter.h | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 iioutil/include/iioutil/iioeventemitter.h diff --git a/iioutil/include/iioutil/iioeventemitter.h b/iioutil/include/iioutil/iioeventemitter.h new file mode 100644 index 0000000000..2b3f846b45 --- /dev/null +++ b/iioutil/include/iioutil/iioeventemitter.h @@ -0,0 +1,41 @@ +/* + * 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 IIOEVENTEMITTER_H +#define IIOEVENTEMITTER_H + +#include +namespace scopy { +const int IIO_SUCCESS = 0; +const int IIO_ERROR = -1; +typedef enum +{ + SINGLE, + STREAM +} IIOCallType; +class IIOEventEmitter +{ +public: + virtual void iioEvent(int retCode, scopy::IIOCallType type) = 0; +}; +} // namespace scopy +Q_DECLARE_METATYPE(scopy::IIOCallType); +#endif // IIOEVENTEMITTER_H From c80d840c9105c56aaa7226ad747445aeccce192a Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 12:38:43 +0200 Subject: [PATCH 06/41] gui/widgets/menucollapsesection: Create a new type of header widget. The ToolMenuHeaderWidget serves as the device section within the tool menu. This widget provides two key features: a device button and blinking LEDs (which can be controlled using the blinkLed signal). Signed-off-by: andreidanila1 --- gui/include/gui/widgets/menucollapsesection.h | 4 +- .../gui/widgets/toolmenuheaderwidget.h | 67 +++++++++++ gui/src/widgets/menucollapsesection.cpp | 4 + gui/src/widgets/toolmenuheaderwidget.cpp | 113 ++++++++++++++++++ 4 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 gui/include/gui/widgets/toolmenuheaderwidget.h create mode 100644 gui/src/widgets/toolmenuheaderwidget.cpp diff --git a/gui/include/gui/widgets/menucollapsesection.h b/gui/include/gui/widgets/menucollapsesection.h index 031dc8dbb2..283ca90b55 100644 --- a/gui/include/gui/widgets/menucollapsesection.h +++ b/gui/include/gui/widgets/menucollapsesection.h @@ -51,7 +51,8 @@ class SCOPY_GUI_EXPORT MenuCollapseSection : public QWidget typedef enum { MHW_BASEWIDGET, - MHW_COMPOSITEWIDGET + MHW_COMPOSITEWIDGET, + MHW_TOOLMENUWIDGET } MenuHeaderWidgetType; MenuCollapseSection(QString title, MenuCollapseSection::MenuHeaderCollapseStyle style = MHCW_ARROW, @@ -81,7 +82,6 @@ class SCOPY_GUI_EXPORT MenuCollapseHeader : public QAbstractButton MenuCollapseSection::MenuHeaderWidgetType headerType, QWidget *parent); ~MenuCollapseHeader(); QString title(); - QWidget *headerWidget() const; private: diff --git a/gui/include/gui/widgets/toolmenuheaderwidget.h b/gui/include/gui/widgets/toolmenuheaderwidget.h new file mode 100644 index 0000000000..9388067920 --- /dev/null +++ b/gui/include/gui/widgets/toolmenuheaderwidget.h @@ -0,0 +1,67 @@ +/* + * 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 TOOLMENUHEADERWIDGET_H +#define TOOLMENUHEADERWIDGET_H + +#include "iioutil/iioeventemitter.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace scopy { +class SCOPY_GUI_EXPORT ToolMenuHeaderWidget : public QWidget, public BaseHeader +{ + Q_OBJECT +public: + ToolMenuHeaderWidget(QString title, QWidget *parent); + ~ToolMenuHeaderWidget(); + + void setTitle(QString title) override; + QString title() override; + void setDeviceIcon(QPixmap icon); + void setUri(QString uri); + +Q_SIGNALS: + void blinkLed(int retCode, IIOCallType type); + +private Q_SLOTS: + void onBlinkLed(int retCode, IIOCallType type); + +private: + QTimer *m_timer; + LedButton *m_ledBtn; + QPushButton *m_deviceBtn; + QLineEdit *m_title; + QLabel *m_uriLabel; + + const int LED_ON_MSEC = 200; + const int WAITING_FACTOR = 10; +}; +} // namespace scopy + +#endif // TOOLMENUHEADERWIDGET_H diff --git a/gui/src/widgets/menucollapsesection.cpp b/gui/src/widgets/menucollapsesection.cpp index 03630ceaf2..102d1f5829 100644 --- a/gui/src/widgets/menucollapsesection.cpp +++ b/gui/src/widgets/menucollapsesection.cpp @@ -25,6 +25,7 @@ #include #include #include +#include Q_LOGGING_CATEGORY(CAT_MENU_COLLAPSE_SECTION, "MenuCollapseSection") @@ -50,6 +51,9 @@ MenuCollapseHeader::MenuCollapseHeader(QString title, MenuCollapseSection::MenuH case MenuCollapseSection::MHW_COMPOSITEWIDGET: m_headerWidget = new CompositeHeaderWidget(title, this); break; + case scopy::MenuCollapseSection::MHW_TOOLMENUWIDGET: + m_headerWidget = new ToolMenuHeaderWidget(title, this); + break; } switch(style) { diff --git a/gui/src/widgets/toolmenuheaderwidget.cpp b/gui/src/widgets/toolmenuheaderwidget.cpp new file mode 100644 index 0000000000..bb3cc10f77 --- /dev/null +++ b/gui/src/widgets/toolmenuheaderwidget.cpp @@ -0,0 +1,113 @@ +/* + * 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 "toolmenuheaderwidget.h" + +#include +#include + +using namespace scopy; + +ToolMenuHeaderWidget::ToolMenuHeaderWidget(QString title, QWidget *parent) +{ + QHBoxLayout *hLay = new QHBoxLayout(this); + hLay->setMargin(0); + hLay->setSpacing(10); + + QWidget *titleWidget = new QWidget(this); + QVBoxLayout *titleLay = new QVBoxLayout(titleWidget); + titleLay->setMargin(0); + titleLay->setSpacing(0); + + m_title = new QLineEdit(title, this); + m_title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + m_title->setEnabled(false); + m_title->setReadOnly(false); + StyleHelper::MenuCollapseHeaderLineEdit(m_title, "menuCollapseLabel"); + + m_uriLabel = new QLabel(titleWidget); + titleLay->addWidget(m_title); + titleLay->addWidget(m_uriLabel); + + m_ledBtn = new LedButton(this); + m_deviceBtn = new QPushButton(this); + m_deviceBtn->setCheckable(true); + + int offset = Style::getDimension(json::global::unit_0_5) / 2; + HoverWidget *ledHover = new HoverWidget(m_ledBtn, m_deviceBtn, this); + ledHover->setStyleSheet("background-color: transparent; border: 0px;"); + ledHover->setAnchorPos(HoverPosition::HP_BOTTOMRIGHT); + ledHover->setContentPos(HoverPosition::HP_TOPLEFT); + ledHover->setVisible(true); + ledHover->setAnchorOffset({offset, offset}); + ledHover->raise(); + + hLay->addWidget(m_deviceBtn); + hLay->addWidget(titleWidget); + hLay->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + m_timer = new QTimer(this); + m_timer->setInterval(LED_ON_MSEC * WAITING_FACTOR); + connect(m_timer, &QTimer::timeout, m_timer, &QTimer::stop); + + connect(this, &ToolMenuHeaderWidget::blinkLed, this, &ToolMenuHeaderWidget::onBlinkLed); +} + +ToolMenuHeaderWidget::~ToolMenuHeaderWidget() {} + +void ToolMenuHeaderWidget::setTitle(QString title) { m_title->setText(title); } + +QString ToolMenuHeaderWidget::title() { return m_title->text(); } + +void ToolMenuHeaderWidget::setDeviceIcon(QPixmap icon) +{ + m_deviceBtn->setIcon(QIcon(icon)); + m_deviceBtn->setIconSize( + QSize(Style::getDimension(json::global::unit_2), Style::getDimension(json::global::unit_2))); + m_deviceBtn->setFixedSize( + QSize(Style::getDimension(json::global::unit_2), Style::getDimension(json::global::unit_2))); +} + +void ToolMenuHeaderWidget::setUri(QString uri) +{ + m_uriLabel->clear(); + m_uriLabel->setText(uri); +} + +void ToolMenuHeaderWidget::onBlinkLed(int retCode, IIOCallType type) +{ + switch(type) { + case IIOCallType::SINGLE: + m_timer->stop(); + break; + case IIOCallType::STREAM: + if(m_timer->isActive()) { + return; + } + m_timer->start(); + break; + default: + break; + } + m_ledBtn->ledOn(retCode >= 0, LED_ON_MSEC); +} + +#include "moc_toolmenuheaderwidget.cpp" From d32bbaf120f55ed6431daedaa7ceb7dafc27dc69 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 14:10:20 +0200 Subject: [PATCH 07/41] pluginbase/toolmenuentry: Added iioEvent signal. Signed-off-by: andreidanila1 --- pluginbase/include/pluginbase/toolmenuentry.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pluginbase/include/pluginbase/toolmenuentry.h b/pluginbase/include/pluginbase/toolmenuentry.h index e83a97a164..6fd17e34f6 100644 --- a/pluginbase/include/pluginbase/toolmenuentry.h +++ b/pluginbase/include/pluginbase/toolmenuentry.h @@ -22,6 +22,7 @@ #ifndef TOOLMENUENTRY_H #define TOOLMENUENTRY_H +#include "iioutil/iioeventemitter.h" #include "scopy-pluginbase_export.h" #include @@ -186,6 +187,12 @@ public Q_SLOTS: */ void runClicked(bool); + /** + * @brief iioEvent + * The signal must be emitted whenever an iio command is executed + */ + void iioEvent(int retCode, scopy::IIOCallType type); + private: QString m_id; QString m_uuid; From 046cd66521db9fa93decc27aa194c6e5ddf3966c Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 14:23:03 +0200 Subject: [PATCH 08/41] core/toolmenumanager: Use ToolMenuWidget for device section. The DeviceInfo struct has been introduced to encapsulate all the essential details about the devices, ensuring better organization and maintainability. Additionally, the onIioEvent slot has been implemented to handle IIO events, triggering the blinking LEDs accordingly. Signed-off-by: andreidanila1 --- core/include/core/toolmenumanager.h | 16 +++++++- core/src/scopymainwindow.cpp | 3 +- core/src/toolmenumanager.cpp | 58 +++++++++++++++++++++-------- 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/core/include/core/toolmenumanager.h b/core/include/core/toolmenumanager.h index 930ec2983f..8df30af99c 100644 --- a/core/include/core/toolmenumanager.h +++ b/core/include/core/toolmenumanager.h @@ -34,6 +34,15 @@ #include "scopy-core_export.h" namespace scopy { + +typedef struct +{ + QString name; + QString param; + QPixmap icon; + QList tools; +} DeviceInfo; + class SCOPY_CORE_EXPORT ToolMenuManager : public QObject { Q_OBJECT @@ -41,7 +50,7 @@ class SCOPY_CORE_EXPORT ToolMenuManager : public QObject ToolMenuManager(ToolStack *ts, DetachedToolWindowManager *dtm, ToolMenu *toolMenu, QObject *parent = nullptr); ~ToolMenuManager(); - void addMenuItem(QString deviceId, QString devName, QList tools, int itemIndex = -1); + void addMenuItem(QString deviceId, DeviceInfo dInfo, int itemIndex = -1); void removeMenuItem(QString deviceId); void changeToolListContents(QString deviceId, QList tools); @@ -52,6 +61,7 @@ public Q_SLOTS: void deviceConnected(QString id); void deviceDisconnected(QString id); void onDisplayNameChanged(QString id, QString devName); + void onIioEvent(QString id, int retCode, IIOCallType type); Q_SIGNALS: void requestToolSelect(QString id); @@ -68,8 +78,9 @@ private Q_SLOTS: void showTool(ToolMenuItem *toolMenuItem); void selectTool(ToolMenuItem *toolMenuItem, bool on); void setTmeAttached(ToolMenuEntry *tme); - MenuSectionCollapseWidget *createMenuSectionItem(QString deviceName, QString uri = ""); + MenuSectionCollapseWidget *createMenuSectionItem(QString devName, QString uri, QPixmap icon); ToolMenuItem *createToolMenuItem(ToolMenuEntry *tme, QWidget *parent = nullptr); + MenuCollapseHeader *getCollapseSectionHeader(MenuSectionCollapseWidget *section); QString m_prevItem; QStringList m_connectedDev; @@ -77,6 +88,7 @@ private Q_SLOTS: DetachedToolWindowManager *m_dtm; ToolMenu *m_toolMenu; QMap m_itemMap; + QMap m_dInfoMap; }; } // namespace scopy diff --git a/core/src/scopymainwindow.cpp b/core/src/scopymainwindow.cpp index f3c6b3f016..e6ad9de711 100644 --- a/core/src/scopymainwindow.cpp +++ b/core/src/scopymainwindow.cpp @@ -603,7 +603,8 @@ void ScopyMainWindow::initApi() void ScopyMainWindow::addDeviceToUi(QString id, Device *d) { - m_toolMenuManager->addMenuItem(id, d->displayName(), d->toolList()); + DeviceInfo dInfo = {d->displayName(), d->param(), d->iconPixmap(), d->toolList()}; + m_toolMenuManager->addMenuItem(id, dInfo); hp->addDevice(id, d); } diff --git a/core/src/toolmenumanager.cpp b/core/src/toolmenumanager.cpp index 3ada849ba9..0f3a0d90e8 100644 --- a/core/src/toolmenumanager.cpp +++ b/core/src/toolmenumanager.cpp @@ -28,6 +28,7 @@ #include #include #include +#include Q_LOGGING_CATEGORY(CAT_TOOLMENUMANAGER, "ToolMenuManager") using namespace scopy; @@ -37,28 +38,31 @@ ToolMenuManager::ToolMenuManager(ToolStack *ts, DetachedToolWindowManager *dtm, , m_ts(ts) , m_dtm(dtm) , m_toolMenu(toolMenu) -{} +{ + qRegisterMetaType("scopy::IIOCallType"); +} ToolMenuManager::~ToolMenuManager() {} -void ToolMenuManager::addMenuItem(QString deviceId, QString devName, QList tools, int itemIndex) +void ToolMenuManager::addMenuItem(QString deviceId, DeviceInfo dInfo, int itemIndex) { - QString param; - if(!tools.isEmpty()) - param = tools.at(0)->param(); - MenuSectionCollapseWidget *devSection = createMenuSectionItem(devName, param); + MenuSectionCollapseWidget *devSection = createMenuSectionItem(dInfo.name, dInfo.param, dInfo.icon); QButtonGroup *menuBtnGroup = m_toolMenu->btnGroup(); - for(ToolMenuEntry *tme : tools) { + for(ToolMenuEntry *tme : qAsConst(dInfo.tools)) { ToolMenuItem *toolMenuItem = createToolMenuItem(tme, devSection); devSection->add(toolMenuItem); menuBtnGroup->addButton(toolMenuItem); connect(tme, &ToolMenuEntry::updateTool, this, &ToolMenuManager::updateTool); connect(tme, &ToolMenuEntry::updateToolAttached, this, [this, toolMenuItem](bool oldAttach) { updateToolAttached(oldAttach, toolMenuItem); }); + connect(tme, &ToolMenuEntry::iioEvent, this, [this, deviceId](int retCode, scopy::IIOCallType type) { + onIioEvent(deviceId, retCode, type); + }); Q_EMIT tme->updateToolEntry(); } m_toolMenu->add(itemIndex, deviceId, devSection); m_itemMap[deviceId] = devSection; + m_dInfoMap[deviceId] = dInfo; qDebug(CAT_TOOLMENUMANAGER) << "Menu item with id" << deviceId << "has been added"; } @@ -85,11 +89,11 @@ void ToolMenuManager::changeToolListContents(QString deviceId, QListdisconnect(this); } + m_dInfoMap[deviceId].tools = tools; MenuSectionCollapseWidget *menuItem = m_itemMap[deviceId]; - QString devName = menuItem->collapseSection()->title(); int itemIndex = m_toolMenu->indexOf(menuItem); removeMenuItem(deviceId); - addMenuItem(deviceId, devName, tools, itemIndex); + addMenuItem(deviceId, m_dInfoMap[deviceId], itemIndex); showMenuItem(deviceId); } @@ -131,6 +135,22 @@ void ToolMenuManager::deviceDisconnected(QString id) void ToolMenuManager::onDisplayNameChanged(QString id, QString devName) { m_itemMap[id]->collapseSection()->setTitle(devName); + m_dInfoMap[id].name = devName; +} + +void ToolMenuManager::onIioEvent(QString id, int retCode, IIOCallType type) +{ + if(!m_itemMap.contains(id)) { + return; + } + MenuCollapseHeader *collapseHeader = getCollapseSectionHeader(m_itemMap[id]); + if(!collapseHeader) { + return; + } + ToolMenuHeaderWidget *thw = dynamic_cast(collapseHeader->headerWidget()); + if(thw) { + Q_EMIT thw->blinkLed(retCode, type); + } } void ToolMenuManager::updateTool(QWidget *old) @@ -268,20 +288,21 @@ void ToolMenuManager::setTmeAttached(ToolMenuEntry *tme) tme->setAttached(!tme->attached()); } -MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(QString deviceName, QString uri) +MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(QString devName, QString uri, QPixmap icon) { MenuSectionCollapseWidget *section = new MenuSectionCollapseWidget( - deviceName, MenuCollapseSection::MHCW_ARROW, MenuCollapseSection::MHW_COMPOSITEWIDGET, m_toolMenu); + devName, MenuCollapseSection::MHCW_ARROW, MenuCollapseSection::MHW_TOOLMENUWIDGET, m_toolMenu); section->contentLayout()->setSpacing(0); section->menuSection()->layout()->setMargin(0); section->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - MenuCollapseHeader *collapseHeader = dynamic_cast(section->collapseSection()->header()); + MenuCollapseHeader *collapseHeader = getCollapseSectionHeader(section); if(collapseHeader) { - CompositeHeaderWidget *chw = dynamic_cast(collapseHeader->headerWidget()); - if(chw) { - chw->add(new QLabel(uri, chw)); - chw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); + ToolMenuHeaderWidget *thw = dynamic_cast(collapseHeader->headerWidget()); + if(thw) { + thw->setUri(uri); + thw->setDeviceIcon(icon); + thw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); } Style::setStyle(collapseHeader, style::properties::widget::bottomBorder); } @@ -304,4 +325,9 @@ ToolMenuItem *ToolMenuManager::createToolMenuItem(ToolMenuEntry *tme, QWidget *p return toolMenuItem; } +MenuCollapseHeader *ToolMenuManager::getCollapseSectionHeader(MenuSectionCollapseWidget *section) +{ + return dynamic_cast(section->collapseSection()->header()); +} + #include "moc_toolmenumanager.cpp" From dd396438394f75e1449729fda1b17ddf1bd3b67d Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 14:53:18 +0200 Subject: [PATCH 09/41] plugins/swiot: Emit iioEvent when needed. The signal is received by the tool menu through the ToolMenuEntry. Signed-off-by: andreidanila1 --- .../swiot/include/swiot/ad74413r/buffermenu.h | 4 +- .../include/swiot/ad74413r/buffermenuview.h | 3 +- .../swiot/include/swiot/faults/faultsdevice.h | 4 +- .../swiot/include/swiot/faults/faultspage.h | 4 +- .../max14906/diodigitalchannelcontroller.h | 7 +- plugins/swiot/include/swiot/readerthread.h | 4 +- plugins/swiot/include/swiot/swiotcontroller.h | 4 +- .../include/swiot/swiotreadtemperaturetask.h | 4 +- plugins/swiot/src/ad74413r/ad74413r.cpp | 2 + plugins/swiot/src/ad74413r/buffermenu.cpp | 68 +++++++++++++++++++ plugins/swiot/src/ad74413r/buffermenuview.cpp | 1 + plugins/swiot/src/config/configmodel.cpp | 16 +++++ plugins/swiot/src/config/configmodel.h | 5 +- plugins/swiot/src/config/swiotconfig.cpp | 5 +- plugins/swiot/src/config/swiotconfig.h | 4 +- plugins/swiot/src/faults/faults.cpp | 1 + plugins/swiot/src/faults/faultsdevice.cpp | 10 +++ plugins/swiot/src/faults/faultspage.cpp | 3 + .../max14906/diodigitalchannelcontroller.cpp | 6 ++ plugins/swiot/src/max14906/max14906.cpp | 2 + plugins/swiot/src/readerthread.cpp | 8 +++ plugins/swiot/src/swiotcontroller.cpp | 5 ++ plugins/swiot/src/swiotplugin.cpp | 6 +- .../swiot/src/swiotreadtemperaturetask.cpp | 2 + 24 files changed, 166 insertions(+), 12 deletions(-) diff --git a/plugins/swiot/include/swiot/ad74413r/buffermenu.h b/plugins/swiot/include/swiot/ad74413r/buffermenu.h index 791d5cf27f..0fa5576734 100644 --- a/plugins/swiot/include/swiot/ad74413r/buffermenu.h +++ b/plugins/swiot/include/swiot/ad74413r/buffermenu.h @@ -25,13 +25,14 @@ #include #include #include +#include #define OUTPUT_CHNL "output" #define INPUT_CHNL "input" namespace scopy::swiot { -class BufferMenu : public QWidget +class BufferMenu : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -60,6 +61,7 @@ public Q_SLOTS: void freqChangeEnd(); void thresholdChangeStart(); void thresholdChangeEnd(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; protected: IIOWidget *m_samplingFreq; diff --git a/plugins/swiot/include/swiot/ad74413r/buffermenuview.h b/plugins/swiot/include/swiot/ad74413r/buffermenuview.h index b57bab7bd9..bf3a486069 100644 --- a/plugins/swiot/include/swiot/ad74413r/buffermenuview.h +++ b/plugins/swiot/include/swiot/ad74413r/buffermenuview.h @@ -30,7 +30,7 @@ #include namespace scopy::swiot { -class BufferMenuView : public QWidget +class BufferMenuView : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -56,6 +56,7 @@ class BufferMenuView : public QWidget void samplingFreqWritten(bool written); void runBtnsPressed(bool en); + void iioEvent(int retCode, scopy::IIOCallType type); private: void createConnections(); diff --git a/plugins/swiot/include/swiot/faults/faultsdevice.h b/plugins/swiot/include/swiot/faults/faultsdevice.h index d4dcfb5ffd..cf6027ccdd 100644 --- a/plugins/swiot/include/swiot/faults/faultsdevice.h +++ b/plugins/swiot/include/swiot/faults/faultsdevice.h @@ -29,11 +29,12 @@ #include #include +#include namespace scopy::swiot { class FaultsGroup; -class FaultsDevice : public QWidget +class FaultsDevice : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -55,6 +56,7 @@ public Q_SLOTS: void specialFaultsUpdated(int index, QString channelFunction); void faultNumericUpdated(); void faultRegisterRead(int iReg, uint32_t value); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private Q_SLOTS: void updateMinimumHeight(); diff --git a/plugins/swiot/include/swiot/faults/faultspage.h b/plugins/swiot/include/swiot/faults/faultspage.h index 2acf6029dc..5b7ad248b8 100644 --- a/plugins/swiot/include/swiot/faults/faultspage.h +++ b/plugins/swiot/include/swiot/faults/faultspage.h @@ -31,7 +31,7 @@ namespace scopy::swiot { class FaultsDevice; -class FaultsPage : public QWidget +class FaultsPage : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -39,6 +39,8 @@ class FaultsPage : public QWidget ~FaultsPage(); void update(); +Q_SIGNALS: + void iioEvent(int retCode, scopy::IIOCallType type); private: QString m_uri; diff --git a/plugins/swiot/include/swiot/max14906/diodigitalchannelcontroller.h b/plugins/swiot/include/swiot/max14906/diodigitalchannelcontroller.h index 77689c1ab6..cbb1d74cb5 100644 --- a/plugins/swiot/include/swiot/max14906/diodigitalchannelcontroller.h +++ b/plugins/swiot/include/swiot/max14906/diodigitalchannelcontroller.h @@ -25,9 +25,10 @@ #include #include +#include namespace scopy::swiot { -class DioDigitalChannelController : public QWidget +class DioDigitalChannelController : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -36,6 +37,10 @@ class DioDigitalChannelController : public QWidget ~DioDigitalChannelController() override; DioDigitalChannel *getDigitalChannel() const; + +Q_SIGNALS: + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; + private Q_SLOTS: void createWriteCurrentLimitCommand(int index); void createWriteRawCommand(bool value); diff --git a/plugins/swiot/include/swiot/readerthread.h b/plugins/swiot/include/swiot/readerthread.h index b0029307a7..e42e48c9f7 100644 --- a/plugins/swiot/include/swiot/readerthread.h +++ b/plugins/swiot/include/swiot/readerthread.h @@ -31,9 +31,10 @@ #include #include +#include namespace scopy::swiot { -class ReaderThread : public QThread +class ReaderThread : public QThread, public IIOEventEmitter { Q_OBJECT public: @@ -77,6 +78,7 @@ public Q_SLOTS: void readerThreadFinished(); void bufferRefilled(QMap> bufferData, int bufferCounter); void channelDataChanged(int channelId, double value); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private Q_SLOTS: void bufferRefillCommandFinished(scopy::Command *cmd); diff --git a/plugins/swiot/include/swiot/swiotcontroller.h b/plugins/swiot/include/swiot/swiotcontroller.h index 3653da809d..6fbe0354ce 100644 --- a/plugins/swiot/include/swiot/swiotcontroller.h +++ b/plugins/swiot/include/swiot/swiotcontroller.h @@ -31,7 +31,7 @@ #include namespace scopy::swiot { -class SwiotController : public QObject +class SwiotController : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -60,6 +60,8 @@ public Q_SLOTS: void modeAttributeChanged(QString mode); void isRuntimeCtxChanged(bool isRuntimeCtx); void writeModeFailed(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; + private Q_SLOTS: void writeModeCommandFinished(scopy::Command *cmd); void readModeCommandFinished(scopy::Command *cmd); diff --git a/plugins/swiot/include/swiot/swiotreadtemperaturetask.h b/plugins/swiot/include/swiot/swiotreadtemperaturetask.h index 1877e5a2df..5dfbdf886f 100644 --- a/plugins/swiot/include/swiot/swiotreadtemperaturetask.h +++ b/plugins/swiot/include/swiot/swiotreadtemperaturetask.h @@ -27,9 +27,10 @@ #include #include +#include namespace scopy::swiot { -class SwiotReadTemperatureTask : public QThread +class SwiotReadTemperatureTask : public QThread, public IIOEventEmitter { Q_OBJECT public: @@ -39,6 +40,7 @@ class SwiotReadTemperatureTask : public QThread Q_SIGNALS: void newTemperature(double value); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private Q_SLOTS: void readRawCommandFinished(scopy::Command *cmd); diff --git a/plugins/swiot/src/ad74413r/ad74413r.cpp b/plugins/swiot/src/ad74413r/ad74413r.cpp index ed50e32807..df5097be5c 100644 --- a/plugins/swiot/src/ad74413r/ad74413r.cpp +++ b/plugins/swiot/src/ad74413r/ad74413r.cpp @@ -128,6 +128,7 @@ void Ad74413r::setupConnections() &BufferAcquisitionHandler::onBufferRefilled, Qt::QueuedConnection); connect(m_readerThread, &ReaderThread::readerThreadFinished, this, &Ad74413r::onReaderThreadFinished, Qt::QueuedConnection); + connect(m_readerThread, &ReaderThread::iioEvent, m_tme, &ToolMenuEntry::iioEvent); connect(m_acqHandler, &BufferAcquisitionHandler::bufferDataReady, this, &Ad74413r::onBufferRefilled); connect(m_acqHandler, &BufferAcquisitionHandler::singleCaptureFinished, this, &Ad74413r::onSingleCaptureFinished, Qt::QueuedConnection); @@ -508,6 +509,7 @@ void Ad74413r::setupChannel(int chnlIdx, QString function) connect(menu, &BufferMenuView::diagnosticFunctionUpdated, this, &Ad74413r::onDiagnosticFunctionUpdated); connect(menu, &BufferMenuView::samplingFreqWritten, this, &Ad74413r::samplingFreqWritten); connect(menu, &BufferMenuView::thresholdWritten, this, &Ad74413r::onThresholdWritten); + connect(menu, &BufferMenuView::iioEvent, m_tme, &ToolMenuEntry::iioEvent); connect(this, &Ad74413r::broadcastThreshold, menu, &BufferMenuView::broadcastThreshold); connect(this, &Ad74413r::updateDiagSamplingFreq, menu, &BufferMenuView::updateDiagSamplingFreq); } diff --git a/plugins/swiot/src/ad74413r/buffermenu.cpp b/plugins/swiot/src/ad74413r/buffermenu.cpp index 521064033d..96bfa428a8 100644 --- a/plugins/swiot/src/ad74413r/buffermenu.cpp +++ b/plugins/swiot/src/ad74413r/buffermenu.cpp @@ -53,6 +53,11 @@ BufferMenu::BufferMenu(QWidget *parent, QString chnlFunction, Connection *conn, &BufferMenu::freqChangeStart); connect(dynamic_cast(m_samplingFreq->getDataStrategy()), &CmdQChannelAttrDataStrategy::emitStatus, this, &BufferMenu::freqChangeEnd); + connect(dynamic_cast(m_samplingFreq->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } } @@ -124,6 +129,11 @@ CurrentInLoopMenu::CurrentInLoopMenu(QWidget *parent, QString chnlFunction, Conn &CurrentInLoopMenu::updateCnvtLabel); connect(dynamic_cast(dacCode->getDataStrategy()), &CmdQChannelAttrDataStrategy::sendData, this, &CurrentInLoopMenu::updateCnvtLabel); + connect(dynamic_cast(dacCode->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } CurrentInLoopMenu::~CurrentInLoopMenu() {} @@ -161,6 +171,10 @@ DigitalInLoopMenu::DigitalInLoopMenu(QWidget *parent, QString chnlFunction, Conn connect(dynamic_cast(m_threshold->getUiStrategy()), &EditableGuiStrategy::emitData, this, &BufferMenu::thresholdChangeStart); connect(dataStrategy, &CmdQChannelAttrDataStrategy::emitStatus, this, &DigitalInLoopMenu::onEmitStatus); + connect(dataStrategy, &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); // dac code - output channel IIOWidget *dacCode = IIOWidgetBuilder(this) .connection(const_cast(m_connection)) @@ -192,6 +206,11 @@ DigitalInLoopMenu::DigitalInLoopMenu(QWidget *parent, QString chnlFunction, Conn &DigitalInLoopMenu::updateCnvtLabel); connect(dynamic_cast(dacCode->getDataStrategy()), &CmdQChannelAttrDataStrategy::sendData, this, &DigitalInLoopMenu::updateCnvtLabel); + connect(dynamic_cast(dacCode->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } DigitalInLoopMenu::~DigitalInLoopMenu() {} @@ -271,6 +290,11 @@ VoltageOutMenu::VoltageOutMenu(QWidget *parent, QString chnlFunction, Connection &VoltageOutMenu::updateCnvtLabel); connect(dynamic_cast(dacCode->getDataStrategy()), &CmdQChannelAttrDataStrategy::sendData, this, &VoltageOutMenu::updateCnvtLabel); + connect(dynamic_cast(dacCode->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); // slew - output channel IIOWidget *slewOptions = IIOWidgetBuilder(this) @@ -280,6 +304,11 @@ VoltageOutMenu::VoltageOutMenu(QWidget *parent, QString chnlFunction, Connection .optionsValues("0 1") .buildSingle(); addMenuWidget(slewOptions); + connect(dynamic_cast(slewOptions->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); // slew step - output channel IIOWidget *slewStep = IIOWidgetBuilder(this) @@ -290,6 +319,11 @@ VoltageOutMenu::VoltageOutMenu(QWidget *parent, QString chnlFunction, Connection .uiStrategy(IIOWidgetBuilder::UIS::ComboUi) .buildSingle(); addMenuWidget(slewStep); + connect(dynamic_cast(slewStep->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); // slew rate - output channel IIOWidget *slewRate = IIOWidgetBuilder(this) @@ -300,6 +334,11 @@ VoltageOutMenu::VoltageOutMenu(QWidget *parent, QString chnlFunction, Connection .uiStrategy(IIOWidgetBuilder::UIS::ComboUi) .buildSingle(); addMenuWidget(slewRate); + connect(dynamic_cast(slewRate->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } VoltageOutMenu::~VoltageOutMenu() {} @@ -354,6 +393,11 @@ CurrentOutMenu::CurrentOutMenu(QWidget *parent, QString chnlFunction, Connection &CurrentOutMenu::updateCnvtLabel); connect(dynamic_cast(dacCode->getDataStrategy()), &CmdQChannelAttrDataStrategy::sendData, this, &CurrentOutMenu::updateCnvtLabel); + connect(dynamic_cast(dacCode->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); // slew - output channel IIOWidget *slewOptions = IIOWidgetBuilder(this) @@ -363,6 +407,11 @@ CurrentOutMenu::CurrentOutMenu(QWidget *parent, QString chnlFunction, Connection .optionsValues("0 1") .buildSingle(); addMenuWidget(slewOptions); + connect(dynamic_cast(slewOptions->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); // slew step - output channel IIOWidget *slewStep = IIOWidgetBuilder(this) @@ -373,6 +422,11 @@ CurrentOutMenu::CurrentOutMenu(QWidget *parent, QString chnlFunction, Connection .uiStrategy(IIOWidgetBuilder::UIS::ComboUi) .buildSingle(); addMenuWidget(slewStep); + connect(dynamic_cast(slewStep->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); // slew rate - output channel IIOWidget *slewRate = IIOWidgetBuilder(this) @@ -383,6 +437,11 @@ CurrentOutMenu::CurrentOutMenu(QWidget *parent, QString chnlFunction, Connection .uiStrategy(IIOWidgetBuilder::UIS::ComboUi) .buildSingle(); addMenuWidget(slewRate); + connect(dynamic_cast(slewRate->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } CurrentOutMenu::~CurrentOutMenu() {} @@ -420,6 +479,11 @@ DiagnosticMenu::DiagnosticMenu(QWidget *parent, QString chnlFunction, Connection [=, this](QString data, QString dataOptions) { Q_EMIT diagnosticFunctionUpdated(); }); connect(dynamic_cast(m_samplingFreq->getDataStrategy()), &CmdQChannelAttrDataStrategy::emitStatus, this, &DiagnosticMenu::onSamplingFreqWrite); + connect(dynamic_cast(diagOptions->getDataStrategy()), + &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } DiagnosticMenu::~DiagnosticMenu() {} @@ -463,6 +527,10 @@ DigitalInMenu::DigitalInMenu(QWidget *parent, QString chnlFunction, Connection * connect(dynamic_cast(m_threshold->getUiStrategy()), &EditableGuiStrategy::emitData, this, &BufferMenu::thresholdChangeStart); connect(dataStrategy, &CmdQChannelAttrDataStrategy::emitStatus, this, &DigitalInMenu::onEmitStatus); + connect(dataStrategy, &CmdQChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } DigitalInMenu::~DigitalInMenu() {} diff --git a/plugins/swiot/src/ad74413r/buffermenuview.cpp b/plugins/swiot/src/ad74413r/buffermenuview.cpp index 08413cf42d..6f76ce0f55 100644 --- a/plugins/swiot/src/ad74413r/buffermenuview.cpp +++ b/plugins/swiot/src/ad74413r/buffermenuview.cpp @@ -86,6 +86,7 @@ void BufferMenuView::createConnections() connect(this, &BufferMenuView::updateDiagSamplingFreq, m_swiotAdvMenu, &BufferMenu::onDiagSamplingChange); connect(m_swiotAdvMenu, &BufferMenu::freqChangeStart, this, [&]() { Q_EMIT samplingFreqWritten(false); }); connect(m_swiotAdvMenu, &BufferMenu::freqChangeEnd, this, [&]() { Q_EMIT samplingFreqWritten(true); }); + connect(m_swiotAdvMenu, &BufferMenu::iioEvent, this, &BufferMenuView::iioEvent); connect(this, &BufferMenuView::runBtnsPressed, m_swiotAdvMenu, &BufferMenu::onRunBtnsPressed); } diff --git a/plugins/swiot/src/config/configmodel.cpp b/plugins/swiot/src/config/configmodel.cpp index 61300e1f30..c77fe5f321 100644 --- a/plugins/swiot/src/config/configmodel.cpp +++ b/plugins/swiot/src/config/configmodel.cpp @@ -51,6 +51,7 @@ void ConfigModel::readEnabled() [=, this](scopy::Command *cmd) { IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } @@ -66,6 +67,7 @@ void ConfigModel::readEnabled() qCritical(CAT_SWIOT_CONFIG) << "Error: could not read attribute \"enable\" on channel" << m_channelId << "error id ->" << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_commandQueue->enqueue(enabledChnCmd); @@ -80,6 +82,7 @@ void ConfigModel::writeEnabled(const QString &enabled) [=, this](scopy::Command *cmd) { IioDeviceAttributeWrite *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { @@ -89,6 +92,7 @@ void ConfigModel::writeEnabled(const QString &enabled) } else { Q_EMIT configChannelEnabled(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_commandQueue->enqueue(enabledChnCmd); @@ -102,6 +106,7 @@ void ConfigModel::readDevice() [=, this](scopy::Command *cmd) { IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } @@ -112,6 +117,7 @@ void ConfigModel::readDevice() qDebug(CAT_SWIOT_CONFIG) << "Can't read value from device on channel" << m_channelId << "error id ->" << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_commandQueue->enqueue(deviceChnCmd); @@ -126,6 +132,7 @@ void ConfigModel::writeDevice(const QString &device) [=, this](scopy::Command *cmd) { IioDeviceAttributeWrite *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { @@ -135,6 +142,7 @@ void ConfigModel::writeDevice(const QString &device) } else { Q_EMIT configChannelDevice(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_commandQueue->enqueue(deviceChnCmd); @@ -149,6 +157,7 @@ void ConfigModel::readFunction() [=, this](scopy::Command *cmd) { IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } @@ -159,6 +168,7 @@ void ConfigModel::readFunction() qCritical(CAT_SWIOT_CONFIG) << "Error: could not read attribute \"function\" on channel" << m_channelId << "error id ->" << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_commandQueue->enqueue(functionChnCmd); @@ -173,6 +183,7 @@ void ConfigModel::writeFunction(const QString &function) [=, this](scopy::Command *cmd) { IioDeviceAttributeWrite *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { @@ -182,6 +193,7 @@ void ConfigModel::writeFunction(const QString &function) } else { Q_EMIT configChannelFunction(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_commandQueue->enqueue(functionChnCmd); @@ -196,6 +208,7 @@ void ConfigModel::readDeviceAvailable() [=, this](scopy::Command *cmd) { IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } @@ -208,6 +221,7 @@ void ConfigModel::readDeviceAvailable() << "Error: could not read attribute \"function available\" on channel" << m_channelId << "error id ->" << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_commandQueue->enqueue(deviceAvailableChnCmd); @@ -222,6 +236,7 @@ void ConfigModel::readFunctionAvailable() [=, this](scopy::Command *cmd) { IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } @@ -234,6 +249,7 @@ void ConfigModel::readFunctionAvailable() << "Error: could not read attribute \"device available\" on channel" << m_channelId << "error id ->" << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_commandQueue->enqueue(functionAvailableChnCmd); diff --git a/plugins/swiot/src/config/configmodel.h b/plugins/swiot/src/config/configmodel.h index dd88a3ef88..098cd36a60 100644 --- a/plugins/swiot/src/config/configmodel.h +++ b/plugins/swiot/src/config/configmodel.h @@ -21,6 +21,7 @@ #ifndef CONFIGMODEL_H #define CONFIGMODEL_H +#include "iioutil/iioeventemitter.h" #include #include @@ -33,7 +34,7 @@ extern "C" } namespace scopy::swiot { -class ConfigModel : public QObject +class ConfigModel : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -62,6 +63,8 @@ class ConfigModel : public QObject void configChannelDevice(); void configChannelFunction(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE); + private: struct iio_device *m_device; int m_channelId; diff --git a/plugins/swiot/src/config/swiotconfig.cpp b/plugins/swiot/src/config/swiotconfig.cpp index b083f0379c..0ac81c703a 100644 --- a/plugins/swiot/src/config/swiotconfig.cpp +++ b/plugins/swiot/src/config/swiotconfig.cpp @@ -34,9 +34,11 @@ using namespace scopy::swiot; -SwiotConfig::SwiotConfig(QString uri, QWidget *parent) +SwiotConfig::SwiotConfig(QString uri, ToolMenuEntry *tme, QWidget *parent) : QWidget(parent) , m_uri(uri) + , m_tme(tme) + { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QHBoxLayout *layout = new QHBoxLayout(this); @@ -132,6 +134,7 @@ void SwiotConfig::buildGridLayout() QObject::connect(configController, &ConfigController::clearDrawArea, this, [this]() { m_drawArea->deactivateConnections(); }); + QObject::connect(configModel, &ConfigModel::iioEvent, m_tme, &ToolMenuEntry::iioEvent); } // The apply button will always be at the end of the channel widgets m_chnlsGrid->layout()->addWidget(m_applyBtn); diff --git a/plugins/swiot/src/config/swiotconfig.h b/plugins/swiot/src/config/swiotconfig.h index 9fe65b124a..b5a63b6541 100644 --- a/plugins/swiot/src/config/swiotconfig.h +++ b/plugins/swiot/src/config/swiotconfig.h @@ -22,6 +22,7 @@ #define SWIOTCONFIG_H #include "configcontroller.h" +#include "pluginbase/toolmenuentry.h" #include "src/config/drawarea.h" #include @@ -40,7 +41,7 @@ class SwiotConfig : public QWidget { Q_OBJECT public: - SwiotConfig(QString uri, QWidget *parent = nullptr); + SwiotConfig(QString uri, ToolMenuEntry *tme, QWidget *parent = nullptr); ~SwiotConfig(); public Q_SLOTS: @@ -52,6 +53,7 @@ public Q_SLOTS: void configBtnPressed(); private: + ToolMenuEntry *m_tme; QString m_uri; QMap m_iioDevices; iio_context *m_context; diff --git a/plugins/swiot/src/faults/faults.cpp b/plugins/swiot/src/faults/faults.cpp index 8859c1a104..27f11506d9 100644 --- a/plugins/swiot/src/faults/faults.cpp +++ b/plugins/swiot/src/faults/faults.cpp @@ -101,6 +101,7 @@ void Faults::connectSignalsAndSlots() }); QObject::connect(m_tme, &ToolMenuEntry::runToggled, m_runBtn, &QPushButton::setChecked); + QObject::connect(m_faultsPage, &FaultsPage::iioEvent, m_tme, &ToolMenuEntry::iioEvent); } void Faults::onBackBtnPressed() diff --git a/plugins/swiot/src/faults/faultsdevice.cpp b/plugins/swiot/src/faults/faultsdevice.cpp index 78cf615160..cd361322e1 100644 --- a/plugins/swiot/src/faults/faultsdevice.cpp +++ b/plugins/swiot/src/faults/faultsdevice.cpp @@ -188,19 +188,23 @@ void FaultsDevice::readRegister() IioRegisterRead *tcmd = dynamic_cast(cmd); if(!tcmd) { qCritical(CAT_SWIOT_FAULTS) << m_name << "faults register could not be read."; + Q_EMIT iioEvent(IIO_ERROR); return; } uint32_t reg = tcmd->getResult(); if(tcmd->getReturnCode() < 0) { qCritical(CAT_SWIOT_FAULTS) << m_name << "faults register could not be read."; + Q_EMIT iioEvent(IIO_ERROR); } else { qDebug(CAT_SWIOT_FAULTS) << m_name << "faults register read val:" << reg; try { Q_EMIT faultRegisterRead(i, reg); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(std::invalid_argument &exception) { qCritical(CAT_SWIOT_FAULTS) << m_name << "faults register could not be read."; + Q_EMIT iioEvent(IIO_ERROR); } } }, @@ -214,16 +218,19 @@ void FaultsDevice::functionConfigCmdFinished(scopy::Command *cmd) IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { qCritical(CAT_SWIOT_FAULTS) << "Error: cannot read swiot special fault property"; + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { qCritical(CAT_SWIOT_FAULTS) << "Error: cannot read swiot special fault property"; + } else { int cmdIndex = m_functionConfigCmds.indexOf(cmd); char *readFunction = tcmd->getResult(); Q_EMIT specialFaultsUpdated(cmdIndex, QString(readFunction)); disconnect(cmd, &scopy::Command::finished, this, &FaultsDevice::deviceConfigCmdFinished); + Q_EMIT iioEvent(IIO_SUCCESS); } } @@ -232,11 +239,13 @@ void FaultsDevice::deviceConfigCmdFinished(scopy::Command *cmd) IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { qCritical(CAT_SWIOT_FAULTS) << "Error: cannot read swiot special fault config property"; + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { qCritical(CAT_SWIOT_FAULTS) << "Error: cannot read swiot special fault config property"; + Q_EMIT iioEvent(IIO_ERROR); } else { char *readDevice = tcmd->getResult(); int cmdIndex = m_deviceConfigCmds.indexOf(cmd); @@ -249,6 +258,7 @@ void FaultsDevice::deviceConfigCmdFinished(scopy::Command *cmd) &FaultsDevice::functionConfigCmdFinished, Qt::QueuedConnection); disconnect(cmd, &scopy::Command::finished, this, &FaultsDevice::deviceConfigCmdFinished); m_cmdQueue->enqueue(m_functionConfigCmds.at(cmdIndex)); + Q_EMIT iioEvent(IIO_SUCCESS); } } } diff --git a/plugins/swiot/src/faults/faultspage.cpp b/plugins/swiot/src/faults/faultspage.cpp index 28348c28a0..773d4f4749 100644 --- a/plugins/swiot/src/faults/faultspage.cpp +++ b/plugins/swiot/src/faults/faultspage.cpp @@ -21,6 +21,7 @@ #include "faults/faultspage.h" #include "swiot_logging_categories.h" #include +#include #include #include @@ -80,6 +81,7 @@ void FaultsPage::setupDevices() QVector faultRegistersAddr = {0x02e}; m_ad74413rFaultsDevice = new FaultsDevice("ad74413r", ":/swiot/swiot_faults.json", m_uri, faultRegistersAddr, this); + connect(m_ad74413rFaultsDevice, &FaultsDevice::iioEvent, this, &FaultsPage::iioEvent); } else { qCritical(CAT_SWIOT_FAULTS) << "Error: did not find ad74413r device."; } @@ -88,6 +90,7 @@ void FaultsPage::setupDevices() QVector faultRegistersAddr = {0x04, 0x05, 0x06, 0x07}; m_max14906FaultsDevice = new FaultsDevice("max14906", ":/swiot/swiot_faults.json", m_uri, faultRegistersAddr, this); + connect(m_max14906FaultsDevice, &FaultsDevice::iioEvent, this, &FaultsPage::iioEvent); } else { qCritical(CAT_SWIOT_FAULTS) << "Error: did not find max14906 device."; } diff --git a/plugins/swiot/src/max14906/diodigitalchannelcontroller.cpp b/plugins/swiot/src/max14906/diodigitalchannelcontroller.cpp index d2f3c833a4..acff2b369c 100644 --- a/plugins/swiot/src/max14906/diodigitalchannelcontroller.cpp +++ b/plugins/swiot/src/max14906/diodigitalchannelcontroller.cpp @@ -91,6 +91,7 @@ void DioDigitalChannelController::createWriteRawCommand(bool value) [=, this](scopy::Command *cmd) { IioChannelAttributeWrite *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { @@ -98,6 +99,7 @@ void DioDigitalChannelController::createWriteRawCommand(bool value) << "Could not write value " << value << " to channel " << m_channelName << " error code" << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_cmdQueue->enqueue(writeRawCmd); @@ -221,24 +223,28 @@ void DioDigitalChannelController::writeCurrentLimitCmdFinished(Command *cmd) { IioChannelAttributeWrite *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { qCritical(CAT_SWIOT_MAX14906) << "Could not write current limit value to channel " << m_channelName << " error code " << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); } void DioDigitalChannelController::writeTypeCmdFinished(Command *cmd) { IioChannelAttributeWrite *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { qCritical(CAT_SWIOT_MAX14906) << "Could not write attr to channel " << m_channelName << " error code " << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); } #include "moc_diodigitalchannelcontroller.cpp" diff --git a/plugins/swiot/src/max14906/max14906.cpp b/plugins/swiot/src/max14906/max14906.cpp index 57ca5bbea5..254140d880 100644 --- a/plugins/swiot/src/max14906/max14906.cpp +++ b/plugins/swiot/src/max14906/max14906.cpp @@ -131,6 +131,7 @@ void Max14906::connectSignalsAndSlots() connect(m_max14906SettingsTab, &DioSettingsTab::timeValueChanged, this, &Max14906::timerChanged); connect(m_qTimer, &QTimer::timeout, this, [&]() { m_readerThread->start(); }); connect(m_readerThread, &ReaderThread::started, this, [&]() { m_qTimer->start(1000); }); + connect(m_readerThread, &ReaderThread::iioEvent, m_tme, &ToolMenuEntry::iioEvent); connect(m_tme, &ToolMenuEntry::runToggled, m_runBtn, &QPushButton::setChecked); } @@ -269,6 +270,7 @@ void Max14906::initChannels() m_channelControls.insert(i, channel_control); m_readerThread->addDioChannel(i, channel); + connect(channel_control, &DioDigitalChannelController::iioEvent, m_tme, &ToolMenuEntry::iioEvent); connect(m_readerThread, &ReaderThread::channelDataChanged, channel_control, [this, i](int index, double value) { if(i == index) { diff --git a/plugins/swiot/src/readerthread.cpp b/plugins/swiot/src/readerthread.cpp index 5c19c223d0..4dd588a433 100644 --- a/plugins/swiot/src/readerthread.cpp +++ b/plugins/swiot/src/readerthread.cpp @@ -66,11 +66,13 @@ void ReaderThread::createDioChannelCommand(int index) [=, this](scopy::Command *cmd) { IioChannelAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } auto channel = tcmd->getChannel(); if(!channel) { + Q_EMIT iioEvent(IIO_ERROR); return; } int channelIndex = m_dioChannels.key(channel); @@ -87,6 +89,7 @@ void ReaderThread::createDioChannelCommand(int index) qCritical(CAT_SWIOT_MAX14906) << "Failed to acquire data on DioReaderThread " << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); }, Qt::QueuedConnection); m_cmdQueue->enqueue(dioChannelReadCommand); @@ -171,9 +174,11 @@ void ReaderThread::bufferRefillCommandFinished(scopy::Command *cmd) std::unique_lock lock(m_mutex); IioBufferRefill *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); return; } if(m_bufferInvalid) { + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); return; } if(tcmd->getReturnCode() > 0) { @@ -200,6 +205,7 @@ void ReaderThread::bufferRefillCommandFinished(scopy::Command *cmd) qDebug(CAT_SWIOT_AD74413R) << "Refill error " << QString(strerror(-tcmd->getReturnCode())); } start(); + Q_EMIT iioEvent(tcmd->getReturnCode(), IIOCallType::STREAM); } void ReaderThread::bufferCreateCommandFinished(scopy::Command *cmd) @@ -207,6 +213,7 @@ void ReaderThread::bufferCreateCommandFinished(scopy::Command *cmd) std::unique_lock lock(m_mutex); IioDeviceCreateBuffer *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() < 0) { @@ -216,6 +223,7 @@ void ReaderThread::bufferCreateCommandFinished(scopy::Command *cmd) m_bufferInvalid = false; start(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); } void ReaderThread::bufferCancelCommandFinished(scopy::Command *cmd) diff --git a/plugins/swiot/src/swiotcontroller.cpp b/plugins/swiot/src/swiotcontroller.cpp index a7f3eac5c5..9cc3b0f7e6 100644 --- a/plugins/swiot/src/swiotcontroller.cpp +++ b/plugins/swiot/src/swiotcontroller.cpp @@ -90,6 +90,7 @@ void SwiotController::startTemperatureTask() temperatureTask = new SwiotReadTemperatureTask(uri, this); temperatureTimer = new CyclicalTask(temperatureTask); connect(temperatureTask, &SwiotReadTemperatureTask::newTemperature, this, &SwiotController::readTemperature); + connect(temperatureTask, &SwiotReadTemperatureTask::iioEvent, this, &SwiotController::iioEvent); temperatureTimer->start(2000); m_temperatureReadEn = true; } @@ -102,6 +103,7 @@ void SwiotController::stopTemperatureTask() temperatureTask->requestInterruption(); temperatureTimer->stop(); disconnect(temperatureTask, &SwiotReadTemperatureTask::newTemperature, this, &SwiotController::readTemperature); + disconnect(temperatureTask, &SwiotReadTemperatureTask::iioEvent, this, &SwiotController::iioEvent); temperatureTimer->deleteLater(); temperatureTask->deleteLater(); m_temperatureReadEn = false; @@ -141,6 +143,7 @@ void SwiotController::writeModeCommandFinished(scopy::Command *cmd) { IioDeviceAttributeWrite *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() >= 0) { @@ -174,6 +177,7 @@ void SwiotController::readModeCommandFinished(scopy::Command *cmd) { IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() >= 0) { @@ -184,6 +188,7 @@ void SwiotController::readModeCommandFinished(scopy::Command *cmd) qDebug(CAT_SWIOT) << R"(Critical error: could not read mode attribute, error code:)" << tcmd->getReturnCode(); } + Q_EMIT iioEvent(tcmd->getReturnCode()); } void SwiotController::setIsRuntimeCtx(bool runtimeCtx) diff --git a/plugins/swiot/src/swiotplugin.cpp b/plugins/swiot/src/swiotplugin.cpp index 2ced510b72..15525d2811 100644 --- a/plugins/swiot/src/swiotplugin.cpp +++ b/plugins/swiot/src/swiotplugin.cpp @@ -200,6 +200,8 @@ bool SWIOTPlugin::onDisconnect() tme->setTool(nullptr); } + disconnect(m_swiotController, &SwiotController::iioEvent, ad74413rTme, &ToolMenuEntry::iioEvent); + disconnect(m_swiotController, &SwiotController::iioEvent, configTme, &ToolMenuEntry::iioEvent); disconnect(dynamic_cast(configTme->tool()), &SwiotConfig::writeModeAttribute, this, &SWIOTPlugin::setCtxMode); disconnect(dynamic_cast(ad74413rTme->tool()), &Ad74413r::configBtnPressed, m_runtime, @@ -344,8 +346,10 @@ void SWIOTPlugin::setupToolList() ad74413rTme->setTool(new swiot::Ad74413r(m_param, ad74413rTme)); max14906Tme->setTool(new swiot::Max14906(m_param, max14906Tme)); faultsTme->setTool(new swiot::Faults(m_param, faultsTme)); + connect(m_swiotController, &SwiotController::iioEvent, ad74413rTme, &ToolMenuEntry::iioEvent); } else { - configTme->setTool(new swiot::SwiotConfig(m_param)); + configTme->setTool(new swiot::SwiotConfig(m_param, configTme)); + connect(m_swiotController, &SwiotController::iioEvent, configTme, &ToolMenuEntry::iioEvent); } connect(dynamic_cast(configTme->tool()), &SwiotConfig::writeModeAttribute, this, diff --git a/plugins/swiot/src/swiotreadtemperaturetask.cpp b/plugins/swiot/src/swiotreadtemperaturetask.cpp index 8cf2cd98e7..fbadd86d46 100644 --- a/plugins/swiot/src/swiotreadtemperaturetask.cpp +++ b/plugins/swiot/src/swiotreadtemperaturetask.cpp @@ -100,6 +100,7 @@ void SwiotReadTemperatureTask::readRawCommandFinished(Command *cmd) } IioChannelAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { + Q_EMIT iioEvent(IIO_ERROR); return; } if(tcmd->getReturnCode() >= 0) { @@ -116,6 +117,7 @@ void SwiotReadTemperatureTask::readRawCommandFinished(Command *cmd) qDebug(CAT_SWIOT) << "Error, could not read \"raw\" attribute from " << DEVICE_NAME << ". Temperature not available."; } + Q_EMIT iioEvent(tcmd->getReturnCode()); } void SwiotReadTemperatureTask::readScaleCommandFinished(Command *cmd) From 940745c3f65df761b56e9fb94419ff62cb23f766 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 15:20:34 +0200 Subject: [PATCH 10/41] plugins/pqm: Emit iioEvent when needed. The signal is received by the tool menu through the ToolMenuEntry. Signed-off-by: andreidanila1 --- plugins/pqm/include/pqm/acquisitionmanager.h | 5 ++-- plugins/pqm/src/acquisitionmanager.cpp | 28 +++++++++++++++++--- plugins/pqm/src/pqmplugin.cpp | 1 + 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/plugins/pqm/include/pqm/acquisitionmanager.h b/plugins/pqm/include/pqm/acquisitionmanager.h index bd1ab1e416..a09521cc97 100644 --- a/plugins/pqm/include/pqm/acquisitionmanager.h +++ b/plugins/pqm/include/pqm/acquisitionmanager.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include @@ -37,7 +37,7 @@ #define BUFFER_SIZE 256 #define DEVICE_PQM "pqm" namespace scopy::pqm { -class AcquisitionManager : public QObject +class AcquisitionManager : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -56,6 +56,7 @@ public Q_SLOTS: void bufferDataAvailable(QMap>); void logData(PqmDataLogger::ActiveInstrument instr, const QString &filePath); void pqEvent(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::STREAM) override; private Q_SLOTS: void futureReadData(); diff --git a/plugins/pqm/src/acquisitionmanager.cpp b/plugins/pqm/src/acquisitionmanager.cpp index 683422b3f1..8afeac3d9f 100644 --- a/plugins/pqm/src/acquisitionmanager.cpp +++ b/plugins/pqm/src/acquisitionmanager.cpp @@ -151,9 +151,11 @@ bool AcquisitionManager::readPqmAttributes() { iio_device *dev = iio_context_find_device(m_ctx, DEVICE_PQM); if(!dev) { + Q_EMIT iioEvent(IIO_ERROR); qDebug(CAT_PQM_ACQ) << "Device is unavailable!"; return false; } + int retCode = IIO_SUCCESS; int attrNo = iio_device_get_attrs_count(dev); int chnlsNo = iio_device_get_channels_count(dev); const char *attrName = nullptr; @@ -161,8 +163,12 @@ bool AcquisitionManager::readPqmAttributes() char dest[MAX_ATTR_SIZE]; for(int i = 0; i < attrNo; i++) { attrName = iio_device_get_attr(dev, i); - iio_device_attr_read(dev, attrName, dest, MAX_ATTR_SIZE); + int ret = iio_device_attr_read(dev, attrName, dest, MAX_ATTR_SIZE); m_pqmAttr[DEVICE_PQM][attrName] = QString(dest); + retCode |= ret; + if(ret < 0) { + qWarning(CAT_PQM_ACQ) << "Cannot read device attribute:" << attrName; + } } for(int i = 0; i < chnlsNo; i++) { iio_channel *chnl = iio_device_get_channel(dev, i); @@ -170,24 +176,36 @@ bool AcquisitionManager::readPqmAttributes() chnlId = iio_channel_get_name(chnl); for(int j = 0; j < attrNo; j++) { attrName = iio_channel_get_attr(chnl, j); - iio_channel_attr_read(chnl, attrName, dest, MAX_ATTR_SIZE); + int ret = iio_channel_attr_read(chnl, attrName, dest, MAX_ATTR_SIZE); m_pqmAttr[chnlId][attrName] = QString(dest); + retCode |= ret; + if(ret < 0) { + qWarning(CAT_PQM_ACQ) << "Cannot read channel" << chnlId << "attribute:" << attrName; + } } } m_pqmLog->acquireAttrData(m_pqmAttr); handlePQEvents(); m_pqmLog->log(); + if(m_tools["settings"]) { + Q_EMIT iioEvent(retCode, IIOCallType::SINGLE); + } else { + Q_EMIT iioEvent(retCode); + } + return true; } bool AcquisitionManager::readBufferedData() { if(!m_buffer) { + Q_EMIT iioEvent(IIO_ERROR); qWarning(CAT_PQM_ACQ) << "The buffer is NULL!"; return false; } ssize_t ret = iio_buffer_refill(m_buffer); if(ret < 0) { + Q_EMIT iioEvent(IIO_ERROR); qWarning(CAT_PQM_ACQ) << "An error occurred while refilling! [" << ret << "]"; return false; } @@ -208,6 +226,7 @@ bool AcquisitionManager::readBufferedData() m_bufferData[chnl].push_back(d_ptr); samplesCounter++; } + Q_EMIT iioEvent(IIO_SUCCESS); m_pqmLog->log(); return true; } @@ -263,8 +282,10 @@ void AcquisitionManager::setData(QMap> attr) { QMutexLocker locker(&m_mutex); iio_device *dev = iio_context_find_device(m_ctx, DEVICE_PQM); - if(!dev) + if(!dev) { + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::SINGLE); return; + } const QStringList keys = attr[DEVICE_PQM].keys(); for(const QString &key : keys) { if(m_pqmAttr[DEVICE_PQM].contains(key) && @@ -274,6 +295,7 @@ void AcquisitionManager::setData(QMap> attr) iio_device_attr_write(dev, key.toStdString().c_str(), newVal.toStdString().c_str()); } } + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::SINGLE); } void AcquisitionManager::setProcessData(bool en) diff --git a/plugins/pqm/src/pqmplugin.cpp b/plugins/pqm/src/pqmplugin.cpp index b29b4fa2c7..918ae7e1bb 100644 --- a/plugins/pqm/src/pqmplugin.cpp +++ b/plugins/pqm/src/pqmplugin.cpp @@ -173,6 +173,7 @@ bool PQMPlugin::onConnect() for(auto &tool : m_toolList) { connect(tool->tool(), SIGNAL(enableTool(bool, QString)), m_acqManager, SLOT(toolEnabled(bool, QString))); + connect(m_acqManager, &AcquisitionManager::iioEvent, tool, &ToolMenuEntry::iioEvent); } return true; } From 61a4546255a447d46324c62dbc5f8bf8d8f91867 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 15:21:47 +0200 Subject: [PATCH 11/41] plugins/dac: Emit iioEvent when needed. The signal is received by the tool menu through the ToolMenuEntry. Signed-off-by: andreidanila1 --- plugins/dac/src/bufferdacaddon.cpp | 5 +++++ plugins/dac/src/dacaddon.h | 4 +++- plugins/dac/src/dacdatamanager.cpp | 8 ++++++++ plugins/dac/src/dacdatamanager.h | 4 +++- plugins/dac/src/dacdatamodel.cpp | 13 ++++++++++++- plugins/dac/src/dacdatamodel.h | 4 +++- plugins/dac/src/dacinstrument.cpp | 2 ++ plugins/dac/src/dacinstrument.h | 4 +++- plugins/dac/src/dacplugin.cpp | 1 + plugins/dac/src/ddsdacaddon.cpp | 2 ++ plugins/dac/src/ddsdacaddon.h | 5 ++++- plugins/dac/src/txchannel.cpp | 1 + plugins/dac/src/txchannel.h | 5 ++++- plugins/dac/src/txnode.cpp | 2 ++ plugins/dac/src/txnode.h | 6 +++++- plugins/dac/src/txtone.cpp | 16 +++++++++++++++- plugins/dac/src/txtone.h | 4 +++- 17 files changed, 76 insertions(+), 10 deletions(-) diff --git a/plugins/dac/src/bufferdacaddon.cpp b/plugins/dac/src/bufferdacaddon.cpp index 2aa727de52..2947310fbb 100644 --- a/plugins/dac/src/bufferdacaddon.cpp +++ b/plugins/dac/src/bufferdacaddon.cpp @@ -445,6 +445,11 @@ QWidget *BufferDacAddon::createAttrMenu(TxNode *node, QWidget *parent) for(IIOWidget *w : qAsConst(attrWidgets)) { layout->addWidget(w); detectSamplingFrequency(w); + connect(dynamic_cast(w->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } attr->contentLayout()->addLayout(layout); diff --git a/plugins/dac/src/dacaddon.h b/plugins/dac/src/dacaddon.h index 2360eb544b..53cfd49cd3 100644 --- a/plugins/dac/src/dacaddon.h +++ b/plugins/dac/src/dacaddon.h @@ -22,13 +22,14 @@ #ifndef DACADDON_H_ #define DACADDON_H_ +#include "iioutil/iioeventemitter.h" #include #include #include namespace scopy { namespace dac { -class DacAddon : public QWidget +class DacAddon : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -42,6 +43,7 @@ class DacAddon : public QWidget Q_SIGNALS: void running(bool enabled); void requestChannelMenu(QString uuid); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; protected: QMap m_channelBtns; diff --git a/plugins/dac/src/dacdatamanager.cpp b/plugins/dac/src/dacdatamanager.cpp index 7014352c83..a78d1b7ddc 100644 --- a/plugins/dac/src/dacdatamanager.cpp +++ b/plugins/dac/src/dacdatamanager.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -87,6 +88,7 @@ DacDataManager::DacDataManager(struct iio_device *dev, QWidget *parent) // Setup menu widget m_widget = createMenu(); + connect(m_model, &DacDataModel::iioEvent, this, &DacDataManager::iioEvent); } DacDataManager::~DacDataManager() {} @@ -115,6 +117,11 @@ QWidget *DacDataManager::createAttrMenu(QWidget *parent) for(auto w : attrWidgets) { layout->addWidget(w); + connect(dynamic_cast(w->getDataStrategy()), + &DeviceAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } attr->contentLayout()->addLayout(layout); @@ -186,6 +193,7 @@ void DacDataManager::setupDacMode(QString mode_name, unsigned int mode) } connect(dac, &DacAddon::requestChannelMenu, this, &DacDataManager::handleChannelMenuRequest); connect(dac, &DacAddon::running, this, &DacDataManager::running); + connect(dac, &DacAddon::iioEvent, this, &DacDataManager::iioEvent); dacAddonStack->add(QString::number(mode), dac); m_mode->combo()->addItem(mode_name, mode); } diff --git a/plugins/dac/src/dacdatamanager.h b/plugins/dac/src/dacdatamanager.h index a583f49205..b5b50ed71d 100644 --- a/plugins/dac/src/dacdatamanager.h +++ b/plugins/dac/src/dacdatamanager.h @@ -22,6 +22,7 @@ #ifndef DACDATAMANAGER_H #define DACDATAMANAGER_H +#include "iioutil/iioeventemitter.h" #include #include #include @@ -39,7 +40,7 @@ namespace scopy { namespace dac { class DacDataModel; class DacAddon; -class DacDataManager : public QWidget +class DacDataManager : public QWidget, IIOEventEmitter { Q_OBJECT public: @@ -75,6 +76,7 @@ private Q_SLOTS: Q_SIGNALS: void running(bool toggled); void requestMenu(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private: QVBoxLayout *m_layout; diff --git a/plugins/dac/src/dacdatamodel.cpp b/plugins/dac/src/dacdatamodel.cpp index e2519be64d..6a6eaab7a8 100644 --- a/plugins/dac/src/dacdatamodel.cpp +++ b/plugins/dac/src/dacdatamodel.cpp @@ -248,10 +248,12 @@ bool DacDataModel::validateBufferParams() auto enabledChannelsCount = getEnabledChannelsCount(); ssize_t s_size = iio_device_get_sample_size(m_dev); + if(!s_size || enabledChannelsCount == 0) { auto msg = "Unable to create buffer, no channel enabled."; qDebug(CAT_DAC_DATA) << msg; Q_EMIT log(msg); + Q_EMIT iioEvent(IIO_ERROR); return false; } @@ -259,6 +261,7 @@ bool DacDataModel::validateBufferParams() auto msg = "Unable to create buffer due to data size."; qDebug(CAT_DAC_DATA) << msg; Q_EMIT log(msg); + Q_EMIT iioEvent(IIO_ERROR); return false; } @@ -266,6 +269,7 @@ bool DacDataModel::validateBufferParams() auto msg = "Not enough data columns for all enabled channels."; qDebug(CAT_DAC_DATA) << msg; Q_EMIT log(msg); + Q_EMIT iioEvent(IIO_ERROR); return false; } @@ -273,6 +277,7 @@ bool DacDataModel::validateBufferParams() auto msg = "Unable to create buffer due to incompatible channels enabled."; qDebug(CAT_DAC_DATA) << msg; Q_EMIT log(msg); + Q_EMIT iioEvent(IIO_ERROR); return false; } @@ -289,10 +294,11 @@ bool DacDataModel::validateBufferParams() auto msg = "Unable to create buffer due to high decimation."; qDebug(CAT_DAC_DATA) << msg; Q_EMIT log(msg); + Q_EMIT iioEvent(IIO_ERROR); return false; } } - + Q_EMIT iioEvent(IIO_SUCCESS); return true; } @@ -331,6 +337,7 @@ void DacDataModel::push() QString logMsg = QString("Unable to create buffer: %1").arg(strerror(errno)); qDebug(CAT_DAC_DATA) << logMsg; Q_EMIT log(logMsg); + Q_EMIT iioEvent(IIO_ERROR); return; } @@ -383,6 +390,7 @@ void DacDataModel::push() if(m_interrupted) { Q_EMIT log(QString("Aborting thread...")); } + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); } void DacDataModel::start() { initBuffer(); } @@ -419,6 +427,7 @@ bool DacDataModel::initBufferDac() QString uuid = iio_device_get_name(m_dev); uuid += ":" + id; m_bufferTxs.insert(uuid, new TxNode(uuid, chn, this)); + connect(m_bufferTxs[uuid], &TxNode::iioEvent, this, &DacDataModel::iioEvent); } } return (txCount != 0); @@ -453,6 +462,7 @@ bool DacDataModel::initDdsDac() if(!parentTxNode) { parentTxNode = new TxNode(txNameCurrent, nullptr, this); m_ddsTxs.insert(txNameCurrent, parentTxNode); + connect(parentTxNode, &TxNode::iioEvent, this, &DacDataModel::iioEvent); } if(txNodesNames.size() == 2) { QString toneName = txNodesNames.at(1); @@ -462,6 +472,7 @@ bool DacDataModel::initDdsDac() QString toneName = txNodesNames.at(2); TxNode *complexChnNode = parentTxNode->addChildNode(complexChnName, nullptr); complexChnNode->addChildNode(toneName, chn); + connect(complexChnNode, &TxNode::iioEvent, this, &DacDataModel::iioEvent); } } return (ddsTonesCount != 0); diff --git a/plugins/dac/src/dacdatamodel.h b/plugins/dac/src/dacdatamodel.h index fb64fac8b6..39457d3ae9 100644 --- a/plugins/dac/src/dacdatamodel.h +++ b/plugins/dac/src/dacdatamodel.h @@ -22,6 +22,7 @@ #ifndef DACDATAMODEL_H #define DACDATAMODEL_H +#include "iioutil/iioeventemitter.h" #include #include #include @@ -32,7 +33,7 @@ namespace scopy { namespace dac { class TxNode; -class DacDataModel : public QObject +class DacDataModel : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -67,6 +68,7 @@ class DacDataModel : public QObject void invalidRunParams(); void updateBuffersize(unsigned int bf); void updateKernelBuffers(unsigned int kb); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; public Q_SLOTS: void reset(); diff --git a/plugins/dac/src/dacinstrument.cpp b/plugins/dac/src/dacinstrument.cpp index e1ae5d4fe5..4a4932cff3 100644 --- a/plugins/dac/src/dacinstrument.cpp +++ b/plugins/dac/src/dacinstrument.cpp @@ -241,6 +241,8 @@ void DacInstrument::setupDacDataManagers() for(MenuControlButton *btn : qAsConst(menuBtns)) { devicesGroup->addButton(btn); } + + connect(dm, &DacDataManager::iioEvent, this, &DacInstrument::iioEvent); break; } } diff --git a/plugins/dac/src/dacinstrument.h b/plugins/dac/src/dacinstrument.h index 9ee604382d..3506f39481 100644 --- a/plugins/dac/src/dacinstrument.h +++ b/plugins/dac/src/dacinstrument.h @@ -21,6 +21,7 @@ #ifndef DACINSTRUMENT_H #define DACINSTRUMENT_H +#include "iioutil/iioeventemitter.h" #include "scopy-dac_export.h" #include @@ -38,7 +39,7 @@ namespace scopy { namespace dac { class DacDataManager; -class SCOPY_DAC_EXPORT DacInstrument : public QWidget +class SCOPY_DAC_EXPORT DacInstrument : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -51,6 +52,7 @@ public Q_SLOTS: void dacRunning(bool toggled); Q_SIGNALS: void running(bool toggled); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private: void setupDacDataManagers(); diff --git a/plugins/dac/src/dacplugin.cpp b/plugins/dac/src/dacplugin.cpp index cf6e03f403..dc2a377fb1 100644 --- a/plugins/dac/src/dacplugin.cpp +++ b/plugins/dac/src/dacplugin.cpp @@ -116,6 +116,7 @@ bool DACPlugin::onConnect() m_toolList[0]->setTool(dac); m_toolList[0]->setEnabled(true); m_toolList[0]->setRunBtnVisible(true); + connect(dynamic_cast(dac), &DacInstrument::iioEvent, m_toolList[0], &ToolMenuEntry::iioEvent); connect(m_toolList.last(), &ToolMenuEntry::runToggled, dynamic_cast(dac), &DacInstrument::runToggled); connect(dynamic_cast(dac), &DacInstrument::running, m_toolList[0], &ToolMenuEntry::setRunning); diff --git a/plugins/dac/src/ddsdacaddon.cpp b/plugins/dac/src/ddsdacaddon.cpp index 57631c39b3..7e67948f80 100644 --- a/plugins/dac/src/ddsdacaddon.cpp +++ b/plugins/dac/src/ddsdacaddon.cpp @@ -146,6 +146,7 @@ QWidget *DdsDacAddon::setupDdsTx(TxNode *txNode) QWidget *DdsDacAddon::setupTxMode(TxNode *txNode, unsigned int mode) { TxMode *txModeWidget = new TxMode(txNode, mode, this); + connect(txModeWidget, &TxMode::iioEvent, this, &DdsDacAddon::iioEvent); return txModeWidget; } @@ -184,6 +185,7 @@ TxMode::TxMode(TxNode *node, unsigned int mode, QWidget *parent) } else { txChn->setVisible(false); } + connect(txChn, &TxChannel::iioEvent, this, &TxMode::iioEvent); } auto emitterChannel = m_txChannels.at(0); diff --git a/plugins/dac/src/ddsdacaddon.h b/plugins/dac/src/ddsdacaddon.h index d244df1c0b..a3f6494259 100644 --- a/plugins/dac/src/ddsdacaddon.h +++ b/plugins/dac/src/ddsdacaddon.h @@ -48,7 +48,7 @@ class DdsDacAddon : public DacAddon QWidget *setupTxMode(TxNode *txNode, unsigned int mode); }; -class TxMode : public QWidget +class TxMode : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -66,6 +66,9 @@ class TxMode : public QWidget void read(); void enable(bool enable); +Q_SIGNALS: + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; + private: TxNode *m_node; unsigned int m_mode; diff --git a/plugins/dac/src/txchannel.cpp b/plugins/dac/src/txchannel.cpp index 681e4ddce6..cde5a2fa8c 100644 --- a/plugins/dac/src/txchannel.cpp +++ b/plugins/dac/src/txchannel.cpp @@ -120,6 +120,7 @@ TxTone *TxChannel::setupTxTone(TxNode *nodeTone, unsigned int index) { TxTone *tone = new TxTone(nodeTone, index, this); m_tones.insert(index, tone); + connect(tone, &TxTone::iioEvent, this, &TxChannel::iioEvent); return tone; } diff --git a/plugins/dac/src/txchannel.h b/plugins/dac/src/txchannel.h index 697851a4f0..6420e8a6d7 100644 --- a/plugins/dac/src/txchannel.h +++ b/plugins/dac/src/txchannel.h @@ -22,6 +22,7 @@ #ifndef TXCHANNEL_H #define TXCHANNEL_H +#include "iioutil/iioeventemitter.h" #include #include @@ -29,7 +30,7 @@ namespace scopy { namespace dac { class TxNode; class TxTone; -class TxChannel : public QWidget +class TxChannel : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -46,6 +47,8 @@ class TxChannel : public QWidget QMap getToneMenus() const; Q_SIGNALS: void resetChannelScales(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; + public Q_SLOTS: void scaleUpdated(int toneIdx, QString oldScale, QString newScale); diff --git a/plugins/dac/src/txnode.cpp b/plugins/dac/src/txnode.cpp index 6a297438c5..b9a9f95bfb 100644 --- a/plugins/dac/src/txnode.cpp +++ b/plugins/dac/src/txnode.cpp @@ -75,12 +75,14 @@ bool TxNode::enableDds(bool enable) int ret = iio_channel_attr_write_bool(m_channel, "raw", enable); if(ret < 0) { qDebug(CAT_DAC_DATA) << QString("Can't enable DDS channel, error: %1").arg(ret); + Q_EMIT iioEvent(ret); return false; } qDebug(CAT_DAC_DATA) << QString("DDS channel %1 enabled: %2, ret code %3") .arg(m_txUuid) .arg(enable) .arg(ret); + Q_EMIT iioEvent(ret); } else { qDebug(CAT_DAC_DATA) << QString("%1 not a DDS channel").arg(m_txUuid); return false; diff --git a/plugins/dac/src/txnode.h b/plugins/dac/src/txnode.h index de914af139..1a7c9e8aad 100644 --- a/plugins/dac/src/txnode.h +++ b/plugins/dac/src/txnode.h @@ -22,6 +22,7 @@ #ifndef TXNODE_H #define TXNODE_H +#include "iioutil/iioeventemitter.h" #include #include #include @@ -31,7 +32,7 @@ namespace scopy { namespace dac { -class TxNode : public QObject +class TxNode : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -51,6 +52,9 @@ class TxNode : public QObject const QColor &getColor() const; void setColor(const QColor &newColor); +Q_SIGNALS: + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; + private: QString m_txUuid; QMap m_childNodes = {}; diff --git a/plugins/dac/src/txtone.cpp b/plugins/dac/src/txtone.cpp index 9a98f41fb4..41dd240db7 100644 --- a/plugins/dac/src/txtone.cpp +++ b/plugins/dac/src/txtone.cpp @@ -62,6 +62,11 @@ TxTone::TxTone(TxNode *node, unsigned int idx, QWidget *parent) .buildSingle(); m_frequency->setUItoDataConversion(std::bind(&TxTone::frequencyUItoDS, this, std::placeholders::_1)); m_frequency->setDataToUIConversion(std::bind(&TxTone::frequencyDStoUI, this, std::placeholders::_1)); + connect(dynamic_cast(m_frequency->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); m_scale = IIOWidgetBuilder(this) .channel(m_node->getChannel()) @@ -71,6 +76,11 @@ TxTone::TxTone(TxNode *node, unsigned int idx, QWidget *parent) .buildSingle(); m_scale->setUItoDataConversion(std::bind(&TxTone::scaleUItoDS, std::placeholders::_1)); m_scale->setDataToUIConversion(std::bind(&TxTone::scaleDStoUI, std::placeholders::_1)); + connect(dynamic_cast(m_scale->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); m_phase = IIOWidgetBuilder(this) .channel(m_node->getChannel()) @@ -78,9 +88,13 @@ TxTone::TxTone(TxNode *node, unsigned int idx, QWidget *parent) .uiStrategy(IIOWidgetBuilder::UIS::EditableUi) .parent(this) .buildSingle(); - m_phase->setUItoDataConversion(std::bind(&TxTone::phaseUItoDS, this, std::placeholders::_1)); m_phase->setDataToUIConversion(std::bind(&TxTone::phaseDStoUI, this, std::placeholders::_1)); + connect(dynamic_cast(m_phase->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); connect(dynamic_cast(m_frequency->getDataStrategy()), &ChannelAttrDataStrategy::emitStatus, this, &TxTone::forwardFreqChange); diff --git a/plugins/dac/src/txtone.h b/plugins/dac/src/txtone.h index cdb1421153..7259a479d2 100644 --- a/plugins/dac/src/txtone.h +++ b/plugins/dac/src/txtone.h @@ -22,13 +22,14 @@ #ifndef TXTONE_H #define TXTONE_H +#include "iioutil/iioeventemitter.h" #include #include namespace scopy { namespace dac { class TxNode; -class TxTone : public QWidget +class TxTone : public QWidget, public IIOEventEmitter { Q_OBJECT public: @@ -47,6 +48,7 @@ class TxTone : public QWidget void frequencyUpdated(unsigned int toneIdx, QString frequency); void scaleUpdated(unsigned int toneIdx, QString oldScale, QString scale); void phaseUpdated(unsigned int toneIdx, QString phase); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; public Q_SLOTS: void updateFrequency(QString frequency); From 85ef99843aff4eed63fda2db224972a1fa2f4e5c Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 15:27:46 +0200 Subject: [PATCH 12/41] plugins/debugger: Emit iioEvent when needed. The signal is received by the tool menu through the ToolMenuEntry. Signed-off-by: andreidanila1 --- .../include/debugger/iioexplorerinstrument.h | 5 ++++- plugins/debugger/include/debugger/iiomodel.h | 4 +++- plugins/debugger/src/debuggerplugin.cpp | 1 + .../src/iioexplorer/iioexplorerinstrument.cpp | 2 ++ plugins/debugger/src/iioexplorer/iiomodel.cpp | 18 ++++++++++++++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/plugins/debugger/include/debugger/iioexplorerinstrument.h b/plugins/debugger/include/debugger/iioexplorerinstrument.h index 7cbc3e3cbb..789d8af161 100644 --- a/plugins/debugger/include/debugger/iioexplorerinstrument.h +++ b/plugins/debugger/include/debugger/iioexplorerinstrument.h @@ -39,7 +39,7 @@ #include namespace scopy::debugger { -class SCOPY_DEBUGGER_EXPORT IIOExplorerInstrument : public QWidget +class SCOPY_DEBUGGER_EXPORT IIOExplorerInstrument : public QWidget, public IIOEventEmitter { Q_OBJECT friend class IIOExplorerInstrument_API; @@ -51,6 +51,9 @@ class SCOPY_DEBUGGER_EXPORT IIOExplorerInstrument : public QWidget void saveSettings(QSettings &); void loadSettings(QSettings &); +Q_SIGNALS: + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; + private Q_SLOTS: void applySelection(const QItemSelection &selected, const QItemSelection &deselected); void filterAndExpand(const QString &text); diff --git a/plugins/debugger/include/debugger/iiomodel.h b/plugins/debugger/include/debugger/iiomodel.h index a47bb2c5b1..c7c6725200 100644 --- a/plugins/debugger/include/debugger/iiomodel.h +++ b/plugins/debugger/include/debugger/iiomodel.h @@ -27,10 +27,11 @@ #include #include #include +#include #include "iiostandarditem.h" namespace scopy::debugger { -class IIOModel : public QObject +class IIOModel : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -42,6 +43,7 @@ class IIOModel : public QObject Q_SIGNALS: void emitLog(QDateTime timestamp, bool isRead, QString path, QString oldValue, QString newValue, int returnCode); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private: void iioTreeSetup(); diff --git a/plugins/debugger/src/debuggerplugin.cpp b/plugins/debugger/src/debuggerplugin.cpp index f360a0c555..02bbaba933 100644 --- a/plugins/debugger/src/debuggerplugin.cpp +++ b/plugins/debugger/src/debuggerplugin.cpp @@ -131,6 +131,7 @@ bool DebuggerPlugin::onConnect() if(m_useDebuggerV2) { m_iioDebugger = new IIOExplorerInstrument(m_conn->context(), nullptr, nullptr); dbgTme->setTool(m_iioDebugger); + connect(m_iioDebugger, &IIOExplorerInstrument::iioEvent, dbgTme, &ToolMenuEntry::iioEvent); } else { dbgTme->setTool(new DebuggerInstrument(m_conn->context(), nullptr, nullptr)); } diff --git a/plugins/debugger/src/iioexplorer/iioexplorerinstrument.cpp b/plugins/debugger/src/iioexplorer/iioexplorerinstrument.cpp index bdc4e0162d..144d8d6d2f 100644 --- a/plugins/debugger/src/iioexplorer/iioexplorerinstrument.cpp +++ b/plugins/debugger/src/iioexplorer/iioexplorerinstrument.cpp @@ -147,6 +147,8 @@ void IIOExplorerInstrument::setupUi() setLayout(new QVBoxLayout(this)); layout()->setContentsMargins(0, 0, 0, 0); layout()->addWidget(m_tabWidget); + + connect(m_iioModel, &IIOModel::iioEvent, this, &IIOExplorerInstrument::iioEvent); } void IIOExplorerInstrument::connectSignalsAndSlots() diff --git a/plugins/debugger/src/iioexplorer/iiomodel.cpp b/plugins/debugger/src/iioexplorer/iiomodel.cpp index 2efa13adde..25220e5472 100644 --- a/plugins/debugger/src/iioexplorer/iiomodel.cpp +++ b/plugins/debugger/src/iioexplorer/iiomodel.cpp @@ -20,6 +20,9 @@ */ #include "iiomodel.h" +#include "datastrategy/channelattrdatastrategy.h" +#include "datastrategy/contextattrdatastrategy.h" +#include "datastrategy/deviceattrdatastrategy.h" #include #define BUFFER_SIZE 256 @@ -88,6 +91,11 @@ void IIOModel::generateCtxAttributes() IIOStandardItem::ContextAttribute); attrItem->setEditable(false); m_rootItem->appendRow(attrItem); + connect(dynamic_cast(ctxWidget->getDataStrategy()), + &ContextAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } } @@ -130,6 +138,11 @@ void IIOModel::generateDeviceAttributes() attrItem->setDevice(m_currentDevice); attrItem->setEditable(false); m_currentDeviceItem->appendRow(attrItem); + connect(dynamic_cast(m_devList[j]->getDataStrategy()), + &DeviceAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } } @@ -169,6 +182,11 @@ void IIOModel::generateChannelAttributes() attr_item->setChannel(m_currentChannel); attr_item->setEditable(false); m_currentChannelItem->appendRow(attr_item); + connect(dynamic_cast(m_chnlList[i]->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } } From 7d49ff605c2a12eb4386c5c0ebeed1953f12324b Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 15:29:36 +0200 Subject: [PATCH 13/41] plugins/regmap: Emit iioEvent when needed. The signal is received by the tool menu through the ToolMenuEntry. Signed-off-by: andreidanila1 --- plugins/regmap/src/readwrite/iioregisterreadstrategy.cpp | 1 + plugins/regmap/src/readwrite/iioregisterreadstrategy.hpp | 2 -- plugins/regmap/src/readwrite/iioregisterwritestrategy.cpp | 1 + plugins/regmap/src/readwrite/iregisterreadstrategy.hpp | 5 ++++- plugins/regmap/src/readwrite/iregisterwritestrategy.hpp | 5 ++++- plugins/regmap/src/regmapplugin.cpp | 4 ++++ 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/plugins/regmap/src/readwrite/iioregisterreadstrategy.cpp b/plugins/regmap/src/readwrite/iioregisterreadstrategy.cpp index e8206ff003..e2d9ca2f5a 100644 --- a/plugins/regmap/src/readwrite/iioregisterreadstrategy.cpp +++ b/plugins/regmap/src/readwrite/iioregisterreadstrategy.cpp @@ -47,6 +47,7 @@ void IIORegisterReadStrategy::read(uint32_t address) << "device read success for register " << address << " with value " << reg_val; Q_EMIT readDone(address, reg_val); } + Q_EMIT iioEvent(read); } uint32_t IIORegisterReadStrategy::getAddressSpace() const { return addressSpace; } diff --git a/plugins/regmap/src/readwrite/iioregisterreadstrategy.hpp b/plugins/regmap/src/readwrite/iioregisterreadstrategy.hpp index a4ad7fc080..3bfb251045 100644 --- a/plugins/regmap/src/readwrite/iioregisterreadstrategy.hpp +++ b/plugins/regmap/src/readwrite/iioregisterreadstrategy.hpp @@ -38,8 +38,6 @@ class IIORegisterReadStrategy : public IRegisterReadStrategy uint32_t getAddressSpace() const; void setAddressSpace(uint32_t newAddressSpace); -Q_SIGNALS: - private: struct iio_device *dev; uint32_t addressSpace = 0; diff --git a/plugins/regmap/src/readwrite/iioregisterwritestrategy.cpp b/plugins/regmap/src/readwrite/iioregisterwritestrategy.cpp index afb44a113f..fc4c7d1474 100644 --- a/plugins/regmap/src/readwrite/iioregisterwritestrategy.cpp +++ b/plugins/regmap/src/readwrite/iioregisterwritestrategy.cpp @@ -43,6 +43,7 @@ void IIORegisterWriteStrategy::write(uint32_t address, uint32_t val) << "device write successfull for register " << address << " with value " << val; Q_EMIT writeSuccess(address); } + Q_EMIT iioEvent(write); } uint32_t IIORegisterWriteStrategy::getAddressSpace() const { return addressSpace; } diff --git a/plugins/regmap/src/readwrite/iregisterreadstrategy.hpp b/plugins/regmap/src/readwrite/iregisterreadstrategy.hpp index 8cfd6b8e21..5a84f098f8 100644 --- a/plugins/regmap/src/readwrite/iregisterreadstrategy.hpp +++ b/plugins/regmap/src/readwrite/iregisterreadstrategy.hpp @@ -24,8 +24,10 @@ #include +#include + namespace scopy::regmap { -class IRegisterReadStrategy : public QObject +class IRegisterReadStrategy : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -34,6 +36,7 @@ class IRegisterReadStrategy : public QObject Q_SIGNALS: void readDone(uint32_t address, uint32_t value); void readError(const char *err); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; }; } // namespace scopy::regmap #endif // IREGISTERREADSTRATEGY_HPP diff --git a/plugins/regmap/src/readwrite/iregisterwritestrategy.hpp b/plugins/regmap/src/readwrite/iregisterwritestrategy.hpp index 5c9ada3f2c..54606480d5 100644 --- a/plugins/regmap/src/readwrite/iregisterwritestrategy.hpp +++ b/plugins/regmap/src/readwrite/iregisterwritestrategy.hpp @@ -24,8 +24,10 @@ #include +#include + namespace scopy::regmap { -class IRegisterWriteStrategy : public QObject +class IRegisterWriteStrategy : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -34,6 +36,7 @@ class IRegisterWriteStrategy : public QObject Q_SIGNALS: void writeError(const char *err); void writeSuccess(uint32_t address); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; }; } // namespace scopy::regmap #endif // IREGISTERWRITESTRATEGY_HPP diff --git a/plugins/regmap/src/regmapplugin.cpp b/plugins/regmap/src/regmapplugin.cpp index 3a5a1d8862..40788cd1aa 100644 --- a/plugins/regmap/src/regmapplugin.cpp +++ b/plugins/regmap/src/regmapplugin.cpp @@ -222,6 +222,10 @@ bool RegmapPlugin::onConnect() } else { generateDevice(templatePath, dev, devName, iioReadStrategy, iioWriteStrategy); } + connect(iioReadStrategy, &IIORegisterReadStrategy::iioEvent, m_toolList.last(), + &ToolMenuEntry::iioEvent); + connect(iioWriteStrategy, &IIORegisterWriteStrategy::iioEvent, m_toolList.last(), + &ToolMenuEntry::iioEvent); } m_toolList[0]->setEnabled(true); From 9b9910b43cf2644eb971c4eee2bc8aee5326ec7b Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 15:35:33 +0200 Subject: [PATCH 14/41] plugins/datalogger: Emit iioEvent when needed. The signal is received by the tool menu through the ToolMenuEntry. Signed-off-by: andreidanila1 --- .../include/datalogger/dataacquisitionmanager.hpp | 5 ++++- .../include/datalogger/datamonitor/datamonitormodel.hpp | 5 ++++- .../datalogger/datamonitor/readabledatamonitormodel.hpp | 2 -- .../datalogger/datamonitor/readstrategy/ireadstrategy.hpp | 4 +++- plugins/datalogger/include/datalogger/datamonitortool.h | 3 ++- .../include/datalogger/menus/channelattributesmenu.hpp | 5 ++++- plugins/datalogger/src/dataloggerplugin.cpp | 5 +++++ .../datalogger/src/datamonitor/dmmdatamonitormodel.cpp | 1 + .../src/datamonitor/readstrategy/dmmreadstrategy.cpp | 4 +++- plugins/datalogger/src/datamonitortool.cpp | 8 ++++++-- plugins/datalogger/src/menus/channelattributesmenu.cpp | 5 +++++ 11 files changed, 37 insertions(+), 10 deletions(-) diff --git a/plugins/datalogger/include/datalogger/dataacquisitionmanager.hpp b/plugins/datalogger/include/datalogger/dataacquisitionmanager.hpp index 1de94880e2..109997a771 100644 --- a/plugins/datalogger/include/datalogger/dataacquisitionmanager.hpp +++ b/plugins/datalogger/include/datalogger/dataacquisitionmanager.hpp @@ -26,13 +26,15 @@ #include #include +#include + #include "datamonitor/datamonitormodel.hpp" #include "scopy-datalogger_export.h" namespace scopy { namespace datamonitor { -class SCOPY_DATALOGGER_EXPORT DataAcquisitionManager : public QObject +class SCOPY_DATALOGGER_EXPORT DataAcquisitionManager : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -56,6 +58,7 @@ class SCOPY_DATALOGGER_EXPORT DataAcquisitionManager : public QObject void monitorAdded(DataMonitorModel *monitor); void monitorRemoved(QString monitorName); void deviceRemoved(QString deviceName); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private: QMap *m_activeMonitorsMap; diff --git a/plugins/datalogger/include/datalogger/datamonitor/datamonitormodel.hpp b/plugins/datalogger/include/datalogger/datamonitor/datamonitormodel.hpp index 1a201cb786..fceae44fa0 100644 --- a/plugins/datalogger/include/datalogger/datamonitor/datamonitormodel.hpp +++ b/plugins/datalogger/include/datalogger/datamonitor/datamonitormodel.hpp @@ -29,10 +29,12 @@ #include #include +#include + namespace scopy { namespace datamonitor { -class SCOPY_DATALOGGER_EXPORT DataMonitorModel : public QObject +class SCOPY_DATALOGGER_EXPORT DataMonitorModel : public QObject, public IIOEventEmitter { Q_OBJECT @@ -83,6 +85,7 @@ class SCOPY_DATALOGGER_EXPORT DataMonitorModel : public QObject void minValueUpdated(double value); void maxValueUpdated(double value); void dataCleared(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; protected: void setDataStorageSize(); diff --git a/plugins/datalogger/include/datalogger/datamonitor/readabledatamonitormodel.hpp b/plugins/datalogger/include/datalogger/datamonitor/readabledatamonitormodel.hpp index 125a9f3f1f..a138aa30a0 100644 --- a/plugins/datalogger/include/datalogger/datamonitor/readabledatamonitormodel.hpp +++ b/plugins/datalogger/include/datalogger/datamonitor/readabledatamonitormodel.hpp @@ -42,8 +42,6 @@ class SCOPY_DATALOGGER_EXPORT ReadableDataMonitorModel : public DataMonitorModel void setReadStrategy(IReadStrategy *newReadStrategy); void resetMinMax(); -signals: - private: IReadStrategy *m_readStrategy; }; diff --git a/plugins/datalogger/include/datalogger/datamonitor/readstrategy/ireadstrategy.hpp b/plugins/datalogger/include/datalogger/datamonitor/readstrategy/ireadstrategy.hpp index b258d246f5..bbe5966435 100644 --- a/plugins/datalogger/include/datalogger/datamonitor/readstrategy/ireadstrategy.hpp +++ b/plugins/datalogger/include/datalogger/datamonitor/readstrategy/ireadstrategy.hpp @@ -23,11 +23,12 @@ #define IREGISTERREADSTRATEGY_HPP #include +#include #include "../../scopy-datalogger_export.h" namespace scopy { namespace datamonitor { -class SCOPY_DATALOGGER_EXPORT IReadStrategy : public QObject +class SCOPY_DATALOGGER_EXPORT IReadStrategy : public QObject, public IIOEventEmitter { Q_OBJECT public: @@ -36,6 +37,7 @@ class SCOPY_DATALOGGER_EXPORT IReadStrategy : public QObject Q_SIGNALS: void readDone(double time, double value); void readError(const char *err); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; }; } // namespace datamonitor } // namespace scopy diff --git a/plugins/datalogger/include/datalogger/datamonitortool.h b/plugins/datalogger/include/datalogger/datamonitortool.h index 8d4661cc52..a210abab9f 100644 --- a/plugins/datalogger/include/datalogger/datamonitortool.h +++ b/plugins/datalogger/include/datalogger/datamonitortool.h @@ -44,7 +44,7 @@ namespace scopy::datamonitor { class SevenSegmentDisplay; class DataMonitorSettings; -class SCOPY_DATALOGGER_EXPORT DatamonitorTool : public QWidget +class SCOPY_DATALOGGER_EXPORT DatamonitorTool : public QWidget, public IIOEventEmitter { friend class DataLogger_API; friend class DataMonitorStyleHelper; @@ -61,6 +61,7 @@ class SCOPY_DATALOGGER_EXPORT DatamonitorTool : public QWidget void runToggled(bool toggled); void settingsTitleChanged(QString newTitle); void requestDeleteTool(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private: MenuControlButton *monitorsButton; diff --git a/plugins/datalogger/include/datalogger/menus/channelattributesmenu.hpp b/plugins/datalogger/include/datalogger/menus/channelattributesmenu.hpp index fb08d9596a..57ce443da1 100644 --- a/plugins/datalogger/include/datalogger/menus/channelattributesmenu.hpp +++ b/plugins/datalogger/include/datalogger/menus/channelattributesmenu.hpp @@ -29,11 +29,14 @@ namespace scopy { namespace datamonitor { -class SCOPY_DATALOGGER_EXPORT ChannelAttributesMenu : public QWidget +class SCOPY_DATALOGGER_EXPORT ChannelAttributesMenu : public QWidget, public IIOEventEmitter { Q_OBJECT public: explicit ChannelAttributesMenu(DataMonitorModel *model, QWidget *parent = nullptr); + +Q_SIGNALS: + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; }; } // namespace datamonitor } // namespace scopy diff --git a/plugins/datalogger/src/dataloggerplugin.cpp b/plugins/datalogger/src/dataloggerplugin.cpp index e3a062660f..484a35ad10 100644 --- a/plugins/datalogger/src/dataloggerplugin.cpp +++ b/plugins/datalogger/src/dataloggerplugin.cpp @@ -102,6 +102,8 @@ bool DataLoggerPlugin::onConnect() foreach(ReadableDataMonitorModel *monitor, dmmList) { m_dataAcquisitionManager->getDataMonitorMap()->insert(monitor->getName(), monitor); + connect(monitor, &ReadableDataMonitorModel::iioEvent, m_dataAcquisitionManager, + &DataAcquisitionManager::iioEvent); } Preferences *p = Preferences::GetInstance(); @@ -201,6 +203,9 @@ void DataLoggerPlugin::addNewTool() Q_EMIT toolListChanged(); m_toolList.last()->setTool(datamonitorTool); + connect(datamonitorTool, &DatamonitorTool::iioEvent, m_toolList.last(), &ToolMenuEntry::iioEvent); + connect(m_dataAcquisitionManager, &DataAcquisitionManager::iioEvent, m_toolList.last(), + &ToolMenuEntry::iioEvent); if(m_toolList.length() > 1) { requestTool(tool_name); } diff --git a/plugins/datalogger/src/datamonitor/dmmdatamonitormodel.cpp b/plugins/datalogger/src/datamonitor/dmmdatamonitormodel.cpp index b1fede1993..b17affc79f 100644 --- a/plugins/datalogger/src/datamonitor/dmmdatamonitormodel.cpp +++ b/plugins/datalogger/src/datamonitor/dmmdatamonitormodel.cpp @@ -50,6 +50,7 @@ DmmDataMonitorModel::DmmDataMonitorModel(QString name, QColor color, UnitOfMeasu setDataStorageSize(); setReadStrategy(readStrategy); + connect(readStrategy, &DMMReadStrategy::iioEvent, this, &DmmDataMonitorModel::iioEvent); } iio_channel *DmmDataMonitorModel::iioChannel() const { return m_iioChannel; } diff --git a/plugins/datalogger/src/datamonitor/readstrategy/dmmreadstrategy.cpp b/plugins/datalogger/src/datamonitor/readstrategy/dmmreadstrategy.cpp index b269059d15..0c8ac8e007 100644 --- a/plugins/datalogger/src/datamonitor/readstrategy/dmmreadstrategy.cpp +++ b/plugins/datalogger/src/datamonitor/readstrategy/dmmreadstrategy.cpp @@ -47,11 +47,12 @@ void DMMReadStrategy::read() char err[1024]; iio_strerror(-(int)readRaw, err, sizeof(err)); qDebug() << "device read error " << err; - + Q_EMIT iioEvent(readRaw); } else if(readScale < 0) { char err[1024]; iio_strerror(-(int)readScale, err, sizeof(err)); qDebug() << "device read error " << err; + Q_EMIT iioEvent(readScale); } else { double result = (raw + m_offset) * scale * m_umScale; qDebug() << "dmm read success "; @@ -60,6 +61,7 @@ void DMMReadStrategy::read() double currentTime = QwtDate::toDouble(timeTracker->lastReadValue()); Q_EMIT readDone(currentTime, result); + Q_EMIT iioEvent(IIO_SUCCESS); } } diff --git a/plugins/datalogger/src/datamonitortool.cpp b/plugins/datalogger/src/datamonitortool.cpp index 137c9e7982..90eecf94bc 100644 --- a/plugins/datalogger/src/datamonitortool.cpp +++ b/plugins/datalogger/src/datamonitortool.cpp @@ -269,7 +269,9 @@ DatamonitorTool::DatamonitorTool(DataAcquisitionManager *dataAcquisitionManager, ////generate channel settings for compatible monitors foreach(QString monitor, m_dataAcquisitionManager->getDataMonitorMap()->keys()) { auto monitorModel = m_dataAcquisitionManager->getDataMonitorMap()->value(monitor); - tool->rightStack()->add(monitor, new ChannelAttributesMenu(monitorModel, this)); + ChannelAttributesMenu *chnlAttrMenu = new ChannelAttributesMenu(monitorModel, this); + tool->rightStack()->add(monitor, chnlAttrMenu); + connect(chnlAttrMenu, &ChannelAttributesMenu::iioEvent, this, &DatamonitorTool::iioEvent); } /////////////////monitor selection menu /////////////// @@ -282,7 +284,9 @@ DatamonitorTool::DatamonitorTool(DataAcquisitionManager *dataAcquisitionManager, connect(m_dataAcquisitionManager, &DataAcquisitionManager::monitorAdded, this, [=, this](DataMonitorModel *monitor) { m_monitorSelectionMenu->addMonitor(monitor); - tool->rightStack()->add(monitor->getName(), new ChannelAttributesMenu(monitor, this)); + ChannelAttributesMenu *chnlAttrMenu = new ChannelAttributesMenu(monitor, this); + tool->rightStack()->add(monitor->getName(), chnlAttrMenu); + connect(chnlAttrMenu, &ChannelAttributesMenu::iioEvent, this, &DatamonitorTool::iioEvent); }); connect(m_dataAcquisitionManager, &DataAcquisitionManager::monitorRemoved, this, diff --git a/plugins/datalogger/src/menus/channelattributesmenu.cpp b/plugins/datalogger/src/menus/channelattributesmenu.cpp index 1051210e89..606c66979d 100644 --- a/plugins/datalogger/src/menus/channelattributesmenu.cpp +++ b/plugins/datalogger/src/menus/channelattributesmenu.cpp @@ -20,6 +20,7 @@ */ #include "menus/channelattributesmenu.hpp" +#include "datastrategy/channelattrdatastrategy.h" #include #include @@ -66,6 +67,10 @@ ChannelAttributesMenu::ChannelAttributesMenu(DataMonitorModel *model, QWidget *p for(auto w : attrWidgets) { attrLayout->addWidget(w); + connect(dynamic_cast(w->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, + bool isReadOp) { Q_EMIT iioEvent(returnCode); }); } } else { From 98b1cf3ec0fb0096e9ba7c1fac39267504361ffc Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 21 Nov 2024 15:36:01 +0200 Subject: [PATCH 15/41] plugins/adc: Emit iioEvent when needed. The signal is received by the tool menu through the ToolMenuEntry. Signed-off-by: andreidanila1 --- plugins/adc/src/adcfftinstrumentcontroller.cpp | 5 ++++- plugins/adc/src/adcinstrumentcontroller.cpp | 3 +++ plugins/adc/src/adcinstrumentcontroller.h | 7 ++++++- plugins/adc/src/adctimeinstrumentcontroller.cpp | 3 +++ plugins/adc/src/freq/grfftchannelcomponent.cpp | 6 ++++++ plugins/adc/src/freq/grfftchannelcomponent.h | 5 ++++- plugins/adc/src/grdevicecomponent.cpp | 11 +++++++++++ plugins/adc/src/grdevicecomponent.h | 9 ++++++++- plugins/adc/src/time/grtimechannelcomponent.cpp | 11 +++++++++++ plugins/adc/src/time/grtimechannelcomponent.h | 5 ++++- 10 files changed, 60 insertions(+), 5 deletions(-) diff --git a/plugins/adc/src/adcfftinstrumentcontroller.cpp b/plugins/adc/src/adcfftinstrumentcontroller.cpp index 7fd56adaae..d10d02eb35 100644 --- a/plugins/adc/src/adcfftinstrumentcontroller.cpp +++ b/plugins/adc/src/adcfftinstrumentcontroller.cpp @@ -122,13 +122,13 @@ void ADCFFTInstrumentController::createIIODevice(AcqTreeNode *node) { GRIIODeviceSourceNode *griiodsn = dynamic_cast(node); GRDeviceComponent *d = new GRDeviceComponent(griiodsn); - addComponent(d); m_ui->addDevice(d->ctrl(), d); m_acqNodeComponentMap[griiodsn] = (d); m_fftPlotSettingsComponent->addSampleRateProvider(d); addComponent(d); + connect(d, &GRDeviceComponent::iioEvent, this, &ADCInstrumentController::iioEvent); connect(m_fftPlotSettingsComponent, &FFTPlotManagerSettings::samplingInfoChanged, this, [=](SamplingInfo p) { d->setBufferSize(p.bufferSize); }); } @@ -141,6 +141,7 @@ void ADCFFTInstrumentController::createIIOFloatChannel(AcqTreeNode *node) GRFFTChannelComponent *c = new GRFFTChannelComponent(griiofcn, dynamic_cast(m_plotComponentManager->plot(0)), grtsc, chIdP->pen(idx), m_ui->rightStack); + connect(c, &GRFFTChannelComponent::iioEvent, this, &ADCInstrumentController::iioEvent); Q_ASSERT(grtsc); m_plotComponentManager->addChannel(c); @@ -164,6 +165,7 @@ void ADCFFTInstrumentController::createIIOFloatChannel(AcqTreeNode *node) m_ui->addChannel(c->ctrl(), c, cw); + connect(dc, &GRDeviceComponent::iioEvent, this, &ADCInstrumentController::iioEvent); connect(c->ctrl(), &QAbstractButton::clicked, this, [=]() { m_plotComponentManager->selectChannel(c); }); grtsc->addChannel(c); // For matching Sink To Channels @@ -228,6 +230,7 @@ void ADCFFTInstrumentController::createIIOComplexChannel(AcqTreeNode *node_I, Ac m_ui->addChannel(c->ctrl(), c, cw); + connect(dc, &GRDeviceComponent::iioEvent, this, &ADCInstrumentController::iioEvent); connect(c->ctrl(), &QAbstractButton::clicked, this, [=]() { m_plotComponentManager->selectChannel(c); }); grtsc->addChannel(c); // For matching Sink To Channels diff --git a/plugins/adc/src/adcinstrumentcontroller.cpp b/plugins/adc/src/adcinstrumentcontroller.cpp index 7399e8cd34..cade0ec89b 100644 --- a/plugins/adc/src/adcinstrumentcontroller.cpp +++ b/plugins/adc/src/adcinstrumentcontroller.cpp @@ -57,10 +57,12 @@ ADCInstrumentController::ADCInstrumentController(ToolMenuEntry *tme, QString uri update(); if(m_refreshTimerRunning) m_plotTimer->start(); + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); }, Qt::QueuedConnection); m_ui = new ADCInstrument(tme, nullptr); + connect(this, &ADCInstrumentController::iioEvent, m_tme, &ToolMenuEntry::iioEvent); } ADCInstrumentController::~ADCInstrumentController() {} @@ -110,6 +112,7 @@ void ADCInstrumentController::start() ResourceManager::open("adc" + m_uri, this); bool ret = m_dataProvider->start(); if(!ret) { + Q_EMIT iioEvent(IIO_ERROR); Q_EMIT requestDisconnect(); } } diff --git a/plugins/adc/src/adcinstrumentcontroller.h b/plugins/adc/src/adcinstrumentcontroller.h index 538d187aa9..7a21e64345 100644 --- a/plugins/adc/src/adcinstrumentcontroller.h +++ b/plugins/adc/src/adcinstrumentcontroller.h @@ -30,6 +30,7 @@ #include #include #include +#include #include "adcacquisitionmanager.h" namespace scopy { @@ -43,7 +44,8 @@ class ADCInstrument; class SCOPY_ADC_EXPORT ADCInstrumentController : public QObject, public AcqNodeChannelAware, public MetaComponent, - public ResourceUser + public ResourceUser, + public IIOEventEmitter { Q_OBJECT public: @@ -71,6 +73,9 @@ public Q_SLOTS: virtual void start(); virtual void stop() override; +Q_SIGNALS: + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; + protected Q_SLOTS: virtual void stopUpdates(); virtual void startUpdates(); diff --git a/plugins/adc/src/adctimeinstrumentcontroller.cpp b/plugins/adc/src/adctimeinstrumentcontroller.cpp index 52d5644635..ecc1529db1 100644 --- a/plugins/adc/src/adctimeinstrumentcontroller.cpp +++ b/plugins/adc/src/adctimeinstrumentcontroller.cpp @@ -167,6 +167,7 @@ void ADCTimeInstrumentController::createIIODevice(AcqTreeNode *node) m_timePlotSettingsComponent->addSampleRateProvider(d); addComponent(d); + connect(d, &GRDeviceComponent::iioEvent, this, &ADCInstrumentController::iioEvent); connect(m_timePlotSettingsComponent, &TimePlotManagerSettings::bufferSizeChanged, d, &GRDeviceComponent::setBufferSize); } @@ -179,6 +180,7 @@ void ADCTimeInstrumentController::createIIOFloatChannel(AcqTreeNode *node) GRTimeChannelComponent *c = new GRTimeChannelComponent(griiofcn, dynamic_cast(m_plotComponentManager->plot(0)), grtsc, chIdP->pen(idx), m_ui->rightStack); + connect(c, &GRTimeChannelComponent::iioEvent, this, &ADCInstrumentController::iioEvent); Q_ASSERT(grtsc); m_plotComponentManager->addChannel(c); @@ -215,6 +217,7 @@ void ADCTimeInstrumentController::createIIOFloatChannel(AcqTreeNode *node) m_defaultCh = c; m_plotComponentManager->selectChannel(c); } + connect(dc, &GRDeviceComponent::iioEvent, this, &ADCInstrumentController::iioEvent); } void ADCTimeInstrumentController::createImportFloatChannel(AcqTreeNode *node) diff --git a/plugins/adc/src/freq/grfftchannelcomponent.cpp b/plugins/adc/src/freq/grfftchannelcomponent.cpp index df2d1cc8b0..dfb51d905e 100644 --- a/plugins/adc/src/freq/grfftchannelcomponent.cpp +++ b/plugins/adc/src/freq/grfftchannelcomponent.cpp @@ -20,6 +20,7 @@ */ #include "grfftchannelcomponent.h" +#include "datastrategy/channelattrdatastrategy.h" #include #include #include @@ -286,6 +287,11 @@ QWidget *GRFFTChannelComponent::createChAttrMenu(iio_channel *ch, QString title, for(auto w : attrWidgets) { layout->addWidget(w); + connect(dynamic_cast(w->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } section->contentLayout()->addLayout(layout); diff --git a/plugins/adc/src/freq/grfftchannelcomponent.h b/plugins/adc/src/freq/grfftchannelcomponent.h index 1259c305b3..b147665923 100644 --- a/plugins/adc/src/freq/grfftchannelcomponent.h +++ b/plugins/adc/src/freq/grfftchannelcomponent.h @@ -40,6 +40,7 @@ #include #include #include +#include namespace scopy { namespace adc { @@ -151,7 +152,8 @@ class SCOPY_ADC_EXPORT GRFFTChannelComponent : public ChannelComponent, public GRChannel, public MeasurementProvider, public SampleRateProvider, - public FFTChannel + public FFTChannel, + public IIOEventEmitter { Q_OBJECT public: @@ -198,6 +200,7 @@ public Q_SLOTS: void powerOffsetChanged(double); void windowChanged(int); void windowCorrectionChanged(bool); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private: double m_powerOffset; diff --git a/plugins/adc/src/grdevicecomponent.cpp b/plugins/adc/src/grdevicecomponent.cpp index 7ade95098b..f6e85bfb11 100644 --- a/plugins/adc/src/grdevicecomponent.cpp +++ b/plugins/adc/src/grdevicecomponent.cpp @@ -20,6 +20,7 @@ */ #include "grdevicecomponent.h" +#include "datastrategy/deviceattrdatastrategy.h" #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include using namespace scopy; using namespace scopy::adc; @@ -116,6 +118,10 @@ QWidget *GRDeviceComponent::createChCommonAttrMenu(QWidget *parent) for(auto w : attrWidgets) { layout->addWidget(w); + connect(dynamic_cast(w->getDataStrategy()), &MultiDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } attr->contentLayout()->addLayout(layout); @@ -145,6 +151,11 @@ QWidget *GRDeviceComponent::createAttrMenu(QWidget *parent) for(auto w : attrWidgets) { layout->addWidget(w); + connect(dynamic_cast(w->getDataStrategy()), + &DeviceAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } attr->contentLayout()->addLayout(layout); diff --git a/plugins/adc/src/grdevicecomponent.h b/plugins/adc/src/grdevicecomponent.h index 5a972970e0..276d92a691 100644 --- a/plugins/adc/src/grdevicecomponent.h +++ b/plugins/adc/src/grdevicecomponent.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -38,7 +39,10 @@ namespace scopy::adc { // class GRTimeChannelAddon; -class SCOPY_ADC_EXPORT GRDeviceComponent : public QWidget, public ToolComponent, public SampleRateProvider +class SCOPY_ADC_EXPORT GRDeviceComponent : public QWidget, + public ToolComponent, + public SampleRateProvider, + public IIOEventEmitter { Q_OBJECT public: @@ -61,6 +65,9 @@ public Q_SLOTS: void removeChannel(ChannelComponent *c); void addChannel(ChannelComponent *c); +Q_SIGNALS: + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; + private: QString name; QWidget *widget; diff --git a/plugins/adc/src/time/grtimechannelcomponent.cpp b/plugins/adc/src/time/grtimechannelcomponent.cpp index 81c008a646..c2df3f697f 100644 --- a/plugins/adc/src/time/grtimechannelcomponent.cpp +++ b/plugins/adc/src/time/grtimechannelcomponent.cpp @@ -20,6 +20,7 @@ */ #include "grtimechannelcomponent.h" +#include "datastrategy/channelattrdatastrategy.h" #include #include #include @@ -95,6 +96,11 @@ QWidget *GRTimeChannelComponent::createYAxisMenu(QWidget *parent) .channel(m_src->channel()) .attribute(m_src->scaleAttribute()) .buildSingle(); + connect(dynamic_cast(m_scaleWidget->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } m_yCtrl = new MenuPlotAxisRangeControl(m_timePlotComponentChannel->m_timePlotYAxis, m_yaxisMenu); @@ -210,6 +216,11 @@ QWidget *GRTimeChannelComponent::createAttrMenu(QWidget *parent) for(auto w : attrWidgets) { layout->addWidget(w); + connect(dynamic_cast(w->getDataStrategy()), + &ChannelAttrDataStrategy::emitStatus, this, + [this](QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp) { + Q_EMIT iioEvent(returnCode); + }); } section->contentLayout()->addLayout(layout); diff --git a/plugins/adc/src/time/grtimechannelcomponent.h b/plugins/adc/src/time/grtimechannelcomponent.h index 025fe27bbe..adf0d1e7cb 100644 --- a/plugins/adc/src/time/grtimechannelcomponent.h +++ b/plugins/adc/src/time/grtimechannelcomponent.h @@ -35,6 +35,7 @@ #include "adcinterfaces.h" #include #include +#include #include "time/timeplotcomponent.h" namespace scopy { @@ -84,7 +85,8 @@ class SCOPY_ADC_EXPORT GRTimeChannelComponent : public ChannelComponent, public GRChannel, public MeasurementProvider, public SampleRateProvider, - public ScaleProvider + public ScaleProvider, + public IIOEventEmitter { Q_OBJECT @@ -129,6 +131,7 @@ public Q_SLOTS: Q_SIGNALS: void yModeChanged(); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; private: GRIIOFloatChannelNode *m_node; From e1cc054a2605b4e56fb0e22ddec8f0977bfc3668 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 22 Nov 2024 12:32:54 +0200 Subject: [PATCH 16/41] plugins/m2k: Emit iioEvent when needed. The signal is received by the tool menu through the ToolMenuEntry. Signed-off-by: andreidanila1 --- plugins/m2k/src/old/digitalio.cpp | 1 + plugins/m2k/src/old/dmm.cpp | 5 +++++ .../src/old/logicanalyzer/logic_analyzer.cpp | 5 +++++ plugins/m2k/src/old/m2ktool.cpp | 1 + plugins/m2k/src/old/m2ktool.hpp | 5 ++++- plugins/m2k/src/old/network_analyzer.cpp | 8 +++++++- plugins/m2k/src/old/oscilloscope.cpp | 18 +++++++++++++++++- .../old/patterngenerator/pattern_generator.cpp | 5 ++++- plugins/m2k/src/old/power_controller.cpp | 10 ++++++++++ plugins/m2k/src/old/signal_generator.cpp | 11 +++++++++-- plugins/m2k/src/old/spectrum_analyzer.cpp | 8 ++++++++ 11 files changed, 71 insertions(+), 6 deletions(-) diff --git a/plugins/m2k/src/old/digitalio.cpp b/plugins/m2k/src/old/digitalio.cpp index 9063e5ffb6..28316ab97b 100644 --- a/plugins/m2k/src/old/digitalio.cpp +++ b/plugins/m2k/src/old/digitalio.cpp @@ -257,6 +257,7 @@ void DigitalIO::updateUi() if(groups[1]->ui->inout->isChecked()) { groups[1]->ui->horizontalSlider->setValue(gpigrp2); } + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); } } diff --git a/plugins/m2k/src/old/dmm.cpp b/plugins/m2k/src/old/dmm.cpp index 17adcbbffa..2f0f09b61c 100644 --- a/plugins/m2k/src/old/dmm.cpp +++ b/plugins/m2k/src/old/dmm.cpp @@ -415,12 +415,15 @@ void DMM::checkAndUpdateGainMode(const std::vector &volts) if(currentChannelGain[i] == libm2k::analog::PLUS_MINUS_2_5V) { // only show out of range for +/- 2.5 errorLabels[i]->setText("Out of range"); + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); } else { errorLabels[i]->setText(""); + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); } } } else { errorLabels[i]->setText(""); + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); } } @@ -851,8 +854,10 @@ void DMM::writeAllSettingsToHardware() trigger->setAnalogMode(i, libm2k::ALWAYS); } } + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { qDebug(CAT_VOLTMETER) << "Can't write to hardware: " << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } } diff --git a/plugins/m2k/src/old/logicanalyzer/logic_analyzer.cpp b/plugins/m2k/src/old/logicanalyzer/logic_analyzer.cpp index df05a2638b..d9fed8d052 100644 --- a/plugins/m2k/src/old/logicanalyzer/logic_analyzer.cpp +++ b/plugins/m2k/src/old/logicanalyzer/logic_analyzer.cpp @@ -2114,6 +2114,7 @@ void LogicAnalyzer::startStop(bool start) m_m2kDigital->setKernelBuffersCountIn(1); } catch(libm2k::m2k_exception &e) { qDebug() << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } chunk_size = bufferSizeAdjusted; @@ -2178,6 +2179,7 @@ void LogicAnalyzer::startStop(bool start) m_m2kDigital->setKernelBuffersCountIn(m_currentKernelBuffers); } catch(libm2k::m2k_exception &e) { qDebug() << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } // time for one kernel buffer + 100ms for the transfer @@ -2227,6 +2229,7 @@ void LogicAnalyzer::startStop(bool start) } catch(libm2k::m2k_exception &e) { qDebug() << e.what() << " code: " << e.iioCode(); + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); break; } @@ -2235,6 +2238,7 @@ void LogicAnalyzer::startStop(bool start) } Q_EMIT dataAvailable(absIndex - captureSize, absIndex, m_buffer); + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); QMetaObject::invokeMethod(&m_plot, // trigger replot on Main Thread "replot", Qt::QueuedConnection); @@ -2299,6 +2303,7 @@ void LogicAnalyzer::startStop(bool start) m_m2kDigital->cancelAcquisition(); // cancelBufferIn } catch(...) { qDebug() << "Error"; + Q_EMIT iioEvent(IIO_ERROR); } m_captureThread->join(); diff --git a/plugins/m2k/src/old/m2ktool.cpp b/plugins/m2k/src/old/m2ktool.cpp index b8a2afdeba..b7ef750f0a 100644 --- a/plugins/m2k/src/old/m2ktool.cpp +++ b/plugins/m2k/src/old/m2ktool.cpp @@ -41,6 +41,7 @@ M2kTool::M2kTool(ToolMenuEntry *tme, ApiObject *api, const QString &name, QWidge tme->setEnabled(true); p = Preferences::GetInstance(); connect(p, &Preferences::preferenceChanged, this, &M2kTool::readPreferences); + connect(this, &M2kTool::iioEvent, tme, &ToolMenuEntry::iioEvent); M2kTool::readPreferences(); Style::GetInstance()->setM2KStylesheet(this); } diff --git a/plugins/m2k/src/old/m2ktool.hpp b/plugins/m2k/src/old/m2ktool.hpp index 7939d2cfff..10eb2d58d7 100644 --- a/plugins/m2k/src/old/m2ktool.hpp +++ b/plugins/m2k/src/old/m2ktool.hpp @@ -34,6 +34,8 @@ #include #include +#include + class QJSEngine; class QPushButton; @@ -47,7 +49,7 @@ class ApiObject; class ToolLauncher; namespace m2k { -class M2kTool : public QWidget, public ResourceUser +class M2kTool : public QWidget, public ResourceUser, public IIOEventEmitter { Q_OBJECT @@ -66,6 +68,7 @@ class M2kTool : public QWidget, public ResourceUser Q_SIGNALS: void detachedState(bool detached); + void iioEvent(int retCode, scopy::IIOCallType type = IIOCallType::SINGLE) override; public Q_SLOTS: virtual void run(); diff --git a/plugins/m2k/src/old/network_analyzer.cpp b/plugins/m2k/src/old/network_analyzer.cpp index 4d02d68a19..d9ec0e268d 100644 --- a/plugins/m2k/src/old/network_analyzer.cpp +++ b/plugins/m2k/src/old/network_analyzer.cpp @@ -1197,6 +1197,7 @@ void NetworkAnalyzer::goertzel() m_m2k_analogout->push(buffers); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); return; } } @@ -1229,6 +1230,7 @@ void NetworkAnalyzer::goertzel() } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_NETWORK_ANALYZER) << e.what(); + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); } } @@ -1245,6 +1247,7 @@ void NetworkAnalyzer::goertzel() } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_NETWORK_ANALYZER) << e.what(); + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); return; } if(m_stop) { @@ -1311,7 +1314,7 @@ void NetworkAnalyzer::goertzel() m_averaged_count = 0; } } - + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); m_m2k_analogout->stop(); // Process was cancelled @@ -1648,6 +1651,7 @@ void NetworkAnalyzer::startStop(bool pressed) } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_NETWORK_ANALYZER) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } m_dBgraph.sweepDone(); m_phaseGraph.sweepDone(); @@ -1658,6 +1662,7 @@ void NetworkAnalyzer::startStop(bool pressed) m_m2k_analogin->setKernelBuffersCount(KERNEL_BUFFERS_DEFAULT); } catch(libm2k::m2k_exception &e) { qDebug() << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } } @@ -1676,6 +1681,7 @@ std::vector NetworkAnalyzer::generateSinWave(unsigned int chn_idx, doubl } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_NETWORK_ANALYZER) << e.what(); + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); } } diff --git a/plugins/m2k/src/old/oscilloscope.cpp b/plugins/m2k/src/old/oscilloscope.cpp index 46b8a643af..032244fcf0 100644 --- a/plugins/m2k/src/old/oscilloscope.cpp +++ b/plugins/m2k/src/old/oscilloscope.cpp @@ -2287,7 +2287,9 @@ void Oscilloscope::import() } catch(FileManagerException &ex) { import_error = QString(ex.what()); Q_EMIT importFileLoaded(false); + Q_EMIT iioEvent(IIO_ERROR); } + Q_EMIT iioEvent(IIO_SUCCESS); } unsigned int Oscilloscope::find_curve_number() @@ -4767,9 +4769,11 @@ void Oscilloscope::resetStreamingFlag(bool enable) try { m_m2k_analogin->getTrigger()->setAnalogStreamingFlag(false); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_OSCILLOSCOPE) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } cleanBuffersAllSinks(); @@ -4780,9 +4784,11 @@ void Oscilloscope::resetStreamingFlag(bool enable) if(enable && !d_displayOneBuffer) { m_m2k_analogin->getTrigger()->setAnalogStreamingFlag(true); } + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_OSCILLOSCOPE) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } /* Single capture done */ @@ -4840,6 +4846,7 @@ void Oscilloscope::onPlotNewData() updateBufferPreviewer(); trigger_input = true; // used to read trigger status from Js + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); } void Oscilloscope::onTriggerModeChanged(int mode) @@ -4964,10 +4971,11 @@ void Oscilloscope::setGainMode(uint chnIdx, libm2k::analog::M2K_RANGE gain_mode) try { libm2k::analog::ANALOG_IN_CHANNEL chn = static_cast(chnIdx); runInHwThreadPool(m_m2k_analogin->setRange(chn, gain_mode)); - + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_OSCILLOSCOPE) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } @@ -4986,10 +4994,12 @@ void Oscilloscope::setChannelHwOffset(uint chnIdx, double offset) try { libm2k::analog::ANALOG_IN_CHANNEL chn = static_cast(chnIdx); runInHwThreadPool(m_m2k_analogin->setVerticalOffset(chn, offset);); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_OSCILLOSCOPE) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } } @@ -5036,8 +5046,10 @@ void Oscilloscope::writeAllSettingsToHardware() } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_OSCILLOSCOPE) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } + Q_EMIT iioEvent(IIO_SUCCESS); setSampleRate(active_sample_rate); } for(size_t i = 0; i < nb_channels; i++) { @@ -5132,9 +5144,11 @@ void Oscilloscope::setSampleRate(double sample_rate) m_m2k_analogin->setSampleRate(sample_rate); m_m2k_analogin->setOversamplingRatio(1); } + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e) qDebug(CAT_M2K_OSCILLOSCOPE) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } }); } @@ -5154,10 +5168,12 @@ double Oscilloscope::getSampleRate() } sr = (double)(sr / osr); } + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); return sr; } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_OSCILLOSCOPE) << e.what(); + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); return 0; } } diff --git a/plugins/m2k/src/old/patterngenerator/pattern_generator.cpp b/plugins/m2k/src/old/patterngenerator/pattern_generator.cpp index a02b25181b..5d52030264 100644 --- a/plugins/m2k/src/old/patterngenerator/pattern_generator.cpp +++ b/plugins/m2k/src/old/patterngenerator/pattern_generator.cpp @@ -745,10 +745,11 @@ void PatternGenerator::startStop(bool start) 0.2 + static_cast(m_bufferSize) / static_cast(m_sampleRate); // * 1000.0 (timeout is in seconds, start expects milliseconds) m_singleTimer->start(timeout * 1000.0); - + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug() << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } else { try { @@ -764,9 +765,11 @@ void PatternGenerator::startStop(bool start) m_m2kDigital->enableChannel(i, false); } } + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug() << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } diff --git a/plugins/m2k/src/old/power_controller.cpp b/plugins/m2k/src/old/power_controller.cpp index 424c291ab7..fd36234f93 100644 --- a/plugins/m2k/src/old/power_controller.cpp +++ b/plugins/m2k/src/old/power_controller.cpp @@ -153,9 +153,11 @@ void PowerController::dac1_set_value(double value) { try { m_m2k_powersupply->pushChannel(0, value); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_POWERCONTROL) << "Can't write push value: " << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } averageVoltageCh1.clear(); @@ -171,9 +173,11 @@ void PowerController::dac2_set_value(double value) { try { m_m2k_powersupply->pushChannel(1, value); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_POWERCONTROL) << "Can't write push value: " << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } averageVoltageCh2.clear(); } @@ -182,9 +186,11 @@ void PowerController::dac1_set_enabled(bool enabled) { try { m_m2k_powersupply->enableChannel(0, enabled); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_POWERCONTROL) << "Can't enable channel: " << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } averageVoltageCh1.clear(); @@ -199,9 +205,11 @@ void PowerController::dac2_set_enabled(bool enabled) { try { m_m2k_powersupply->enableChannel(1, enabled); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_POWERCONTROL) << "Can't enable channel: " << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } averageVoltageCh2.clear(); setDynamicProperty(ui->dac2, "running", enabled); @@ -230,9 +238,11 @@ void PowerController::update_lcd() try { value1 = m_m2k_powersupply->readChannel(0); value2 = m_m2k_powersupply->readChannel(1); + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_POWERCONTROL) << "Can't read value: " << e.what(); + Q_EMIT iioEvent(IIO_ERROR, IIOCallType::STREAM); } averageVoltageCh1.push_back(value1); diff --git a/plugins/m2k/src/old/signal_generator.cpp b/plugins/m2k/src/old/signal_generator.cpp index bdd306308b..109e7242bb 100644 --- a/plugins/m2k/src/old/signal_generator.cpp +++ b/plugins/m2k/src/old/signal_generator.cpp @@ -1109,8 +1109,9 @@ bool SignalGenerator::loadParametersFromFile(QSharedPointerfile_nr_of_samples.push_back(0); ptr->file_type = FORMAT_NO_FILE; } - if(!ok) + if(!ok) { return false; + } riff_header_t riff; chunk_header_t chunk; @@ -1122,6 +1123,7 @@ bool SignalGenerator::loadParametersFromFile(QSharedPointersetCyclic(true); m_m2k_analogout->push(buffers); + Q_EMIT iioEvent(IIO_SUCCESS); } void SignalGenerator::run() { start(); } @@ -1395,9 +1398,11 @@ void SignalGenerator::stop() ui->run_button->toggle(false); buffers.clear(); m_m2k_analogout->stop(); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_SIGNAL_GENERATOR) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } ResourceManager::close("m2k-dac" + m_uri); } @@ -1558,11 +1563,12 @@ void SignalGenerator::loadFileChannelData(int chIdx) return; } #endif - + Q_EMIT iioEvent(IIO_SUCCESS); } catch(FileManagerException &e) { ptr->file_message = QString::fromLocal8Bit(e.what()); ptr->file_nr_of_samples.push_back(0); ptr->file_type = FORMAT_NO_FILE; + Q_EMIT iioEvent(IIO_ERROR); } } @@ -1686,6 +1692,7 @@ gr::basic_block_sptr SignalGenerator::getSource(QWidget *obj, double samp_rate, } catch(std::runtime_error &e) { ptr->file_message = QString::fromLocal8Bit(e.what()); fs = blocks::null_source::make(sizeof(float)); + Q_EMIT iioEvent(IIO_ERROR); } for(size_t i = 0; i < ptr->file_nr_of_channels; i++) { if(i == ptr->file_channel) { diff --git a/plugins/m2k/src/old/spectrum_analyzer.cpp b/plugins/m2k/src/old/spectrum_analyzer.cpp index 4db1b3dc3a..d1cc7c5ad6 100644 --- a/plugins/m2k/src/old/spectrum_analyzer.cpp +++ b/plugins/m2k/src/old/spectrum_analyzer.cpp @@ -447,9 +447,11 @@ SpectrumAnalyzer::SpectrumAnalyzer(libm2k::context::M2k *m2k, QString uri, Filte if(canConvRawToVolts) { fft_plot->setScaleFactor(crt_channel, m_m2k_analogin->getScalingFactor(chn)); } + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_SPECTRUM_ANALYZER) << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } if(started) { @@ -525,6 +527,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(libm2k::context::M2k *m2k, QString uri, Filte iio->stop(fft_ids[i]); } } + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); }); connect(waterfall_plot, &WaterfallDisplayPlot::newWaterfallData, this, [=]() { @@ -539,6 +542,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(libm2k::context::M2k *m2k, QString uri, Filte iio->stop(waterfall_ids[i]); } } + Q_EMIT iioEvent(IIO_SUCCESS, IIOCallType::STREAM); }); connect(fft_plot, SIGNAL(currentAverageIndex(unsigned int, unsigned int)), @@ -2572,9 +2576,11 @@ void SpectrumAnalyzer::writeAllSettingsToHardware() } } } + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_SPECTRUM_ANALYZER) << "Can't write settings to hardware: " << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } @@ -2688,9 +2694,11 @@ void SpectrumAnalyzer::setSampleRate(double sr) if(m_m2k_analogin) { try { m_m2k_analogin->setOversamplingRatio(sample_rate_divider); + Q_EMIT iioEvent(IIO_SUCCESS); } catch(libm2k::m2k_exception &e) { HANDLE_EXCEPTION(e); qDebug(CAT_M2K_SPECTRUM_ANALYZER) << "Can't write oversampling ratio: " << e.what(); + Q_EMIT iioEvent(IIO_ERROR); } } From 9298818af1b7c3534d8495fcc14ff9bf59bea28a Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Mon, 25 Nov 2024 15:48:00 +0200 Subject: [PATCH 17/41] core/toolmenumanager: Handle devicePressed signal. The signal is emitted by the ToolMenuHeader widget and it is forwarded by the ToolMenuManager to the scopymainwindow. Signed-off-by: andreidanila1 --- core/include/core/scopymainwindow.h | 1 + core/include/core/toolmenumanager.h | 3 ++- core/src/scopymainwindow.cpp | 10 +++++++++- core/src/toolmenumanager.cpp | 12 +++++++----- gui/include/gui/widgets/toolmenuheaderwidget.h | 1 + gui/src/widgets/toolmenuheaderwidget.cpp | 2 ++ 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/core/include/core/scopymainwindow.h b/core/include/core/scopymainwindow.h index 5e4263e017..027b3e2b4d 100644 --- a/core/include/core/scopymainwindow.h +++ b/core/include/core/scopymainwindow.h @@ -108,6 +108,7 @@ public Q_SLOTS: void handleScanner(); void enableScanner(); void deviceAutoconnect(); + void showDevicePage(QString id, ToolStack *ts); protected: void closeEvent(QCloseEvent *event) override; diff --git a/core/include/core/toolmenumanager.h b/core/include/core/toolmenumanager.h index 8df30af99c..5d00c19f32 100644 --- a/core/include/core/toolmenumanager.h +++ b/core/include/core/toolmenumanager.h @@ -65,6 +65,7 @@ public Q_SLOTS: Q_SIGNALS: void requestToolSelect(QString id); + void requestDevicePage(QString id); private Q_SLOTS: void updateTool(QWidget *old); @@ -78,7 +79,7 @@ private Q_SLOTS: void showTool(ToolMenuItem *toolMenuItem); void selectTool(ToolMenuItem *toolMenuItem, bool on); void setTmeAttached(ToolMenuEntry *tme); - MenuSectionCollapseWidget *createMenuSectionItem(QString devName, QString uri, QPixmap icon); + MenuSectionCollapseWidget *createMenuSectionItem(QString deviceId, DeviceInfo dInfo); ToolMenuItem *createToolMenuItem(ToolMenuEntry *tme, QWidget *parent = nullptr); MenuCollapseHeader *getCollapseSectionHeader(MenuSectionCollapseWidget *section); diff --git a/core/src/scopymainwindow.cpp b/core/src/scopymainwindow.cpp index e6ad9de711..ea2fedaac3 100644 --- a/core/src/scopymainwindow.cpp +++ b/core/src/scopymainwindow.cpp @@ -174,7 +174,6 @@ ScopyMainWindow::ScopyMainWindow(QWidget *parent) } enableScanner(); - connect(dm, &DeviceManager::deviceChangedToolList, m_toolMenuManager, &ToolMenuManager::changeToolListContents); connect(dm, SIGNAL(deviceConnected(QString, Device *)), m_toolMenuManager, SLOT(deviceConnected(QString))); connect(dm, SIGNAL(deviceDisconnected(QString, Device *)), m_toolMenuManager, @@ -182,6 +181,8 @@ ScopyMainWindow::ScopyMainWindow(QWidget *parent) connect(dm, &DeviceManager::requestTool, m_toolMenuManager, &ToolMenuManager::showMenuItem); connect(m_toolMenuManager, &ToolMenuManager::requestToolSelect, ts, &ToolStack::show); connect(m_toolMenuManager, &ToolMenuManager::requestToolSelect, dtm, &DetachedToolWindowManager::show); + connect(m_toolMenuManager, &ToolMenuManager::requestDevicePage, this, + [this, ts](QString id) { showDevicePage(id, ts); }); connect(hp, &ScopyHomePage::displayNameChanged, m_toolMenuManager, &ToolMenuManager::onDisplayNameChanged); connect(hp, &ScopyHomePage::newDeviceAvailable, dm, &DeviceManager::addDevice); @@ -254,6 +255,13 @@ void ScopyMainWindow::deviceAutoconnect() } } +void ScopyMainWindow::showDevicePage(QString id, ToolStack *ts) +{ + QString hpKey = ts->getKey(hp); + ts->show(hpKey); + hp->viewDevice(id); +} + void ScopyMainWindow::save() { QString selectedFilter; diff --git a/core/src/toolmenumanager.cpp b/core/src/toolmenumanager.cpp index 0f3a0d90e8..09e5f9929f 100644 --- a/core/src/toolmenumanager.cpp +++ b/core/src/toolmenumanager.cpp @@ -46,7 +46,7 @@ ToolMenuManager::~ToolMenuManager() {} void ToolMenuManager::addMenuItem(QString deviceId, DeviceInfo dInfo, int itemIndex) { - MenuSectionCollapseWidget *devSection = createMenuSectionItem(dInfo.name, dInfo.param, dInfo.icon); + MenuSectionCollapseWidget *devSection = createMenuSectionItem(deviceId, dInfo); QButtonGroup *menuBtnGroup = m_toolMenu->btnGroup(); for(ToolMenuEntry *tme : qAsConst(dInfo.tools)) { ToolMenuItem *toolMenuItem = createToolMenuItem(tme, devSection); @@ -288,10 +288,10 @@ void ToolMenuManager::setTmeAttached(ToolMenuEntry *tme) tme->setAttached(!tme->attached()); } -MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(QString devName, QString uri, QPixmap icon) +MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(QString deviceId, DeviceInfo dInfo) { MenuSectionCollapseWidget *section = new MenuSectionCollapseWidget( - devName, MenuCollapseSection::MHCW_ARROW, MenuCollapseSection::MHW_TOOLMENUWIDGET, m_toolMenu); + dInfo.name, MenuCollapseSection::MHCW_ARROW, MenuCollapseSection::MHW_TOOLMENUWIDGET, m_toolMenu); section->contentLayout()->setSpacing(0); section->menuSection()->layout()->setMargin(0); section->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -300,9 +300,11 @@ MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(QString devNam if(collapseHeader) { ToolMenuHeaderWidget *thw = dynamic_cast(collapseHeader->headerWidget()); if(thw) { - thw->setUri(uri); - thw->setDeviceIcon(icon); + thw->setUri(dInfo.param); + thw->setDeviceIcon(dInfo.icon); thw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); + connect(thw->deviceBtn(), &QPushButton::pressed, this, + [this, deviceId]() { Q_EMIT requestDevicePage(deviceId); }); } Style::setStyle(collapseHeader, style::properties::widget::bottomBorder); } diff --git a/gui/include/gui/widgets/toolmenuheaderwidget.h b/gui/include/gui/widgets/toolmenuheaderwidget.h index 9388067920..e5b9e2a765 100644 --- a/gui/include/gui/widgets/toolmenuheaderwidget.h +++ b/gui/include/gui/widgets/toolmenuheaderwidget.h @@ -45,6 +45,7 @@ class SCOPY_GUI_EXPORT ToolMenuHeaderWidget : public QWidget, public BaseHeader QString title() override; void setDeviceIcon(QPixmap icon); void setUri(QString uri); + QPushButton *deviceBtn() const; Q_SIGNALS: void blinkLed(int retCode, IIOCallType type); diff --git a/gui/src/widgets/toolmenuheaderwidget.cpp b/gui/src/widgets/toolmenuheaderwidget.cpp index bb3cc10f77..c4a2e97fd0 100644 --- a/gui/src/widgets/toolmenuheaderwidget.cpp +++ b/gui/src/widgets/toolmenuheaderwidget.cpp @@ -110,4 +110,6 @@ void ToolMenuHeaderWidget::onBlinkLed(int retCode, IIOCallType type) m_ledBtn->ledOn(retCode >= 0, LED_ON_MSEC); } +QPushButton *ToolMenuHeaderWidget::deviceBtn() const { return m_deviceBtn; } + #include "moc_toolmenuheaderwidget.cpp" From 623c28739096fec3eb4133595dff83212b0d4e14 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Tue, 26 Nov 2024 16:23:19 +0200 Subject: [PATCH 18/41] gui/style/json/global: Added border_width_2 dimension. Signed-off-by: andreidanila1 --- gui/style/json/global.json | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/style/json/global.json b/gui/style/json/global.json index df49d14f30..45a2e23835 100644 --- a/gui/style/json/global.json +++ b/gui/style/json/global.json @@ -20,6 +20,7 @@ "padding_2": "12", "padding_interactive": "5", "border_width": "1", +"border_width_2": "4", "border_width_interactive": "1", "ch0": "#E76423", "ch1": "#B16EE0", From 683800c5c26edd3d60b87f1c6fef8a5f011b3b21 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Tue, 26 Nov 2024 16:25:46 +0200 Subject: [PATCH 19/41] gui/style/properties/widget: Added ledBorder qss. This QSS is applied to style tool menu device items. Signed-off-by: andreidanila1 --- gui/style/qss/properties/widget/ledBorder.qss | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 gui/style/qss/properties/widget/ledBorder.qss diff --git a/gui/style/qss/properties/widget/ledBorder.qss b/gui/style/qss/properties/widget/ledBorder.qss new file mode 100644 index 0000000000..8a4c6ea510 --- /dev/null +++ b/gui/style/qss/properties/widget/ledBorder.qss @@ -0,0 +1,9 @@ +QWidget[&&property&&=false] { + border-left: &border_width_2& solid transparent; + border-radius: 0; +} + +QWidget[&&property&&=true] { + border-left: &border_width_2& solid &led_success&; + border-radius: 0; +} From feb1dcc56caf55037712206b2ac4b9ab0246705a Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Wed, 27 Nov 2024 12:37:11 +0200 Subject: [PATCH 20/41] core: Added device_menu_item preference. If this preference is enabled, the device header will be a ToolMenuHeaderWidget, featuring the device icon and a status LED. Otherwise, the header will contain only the name and the uri of the device. Signed-off-by: andreidanila1 --- core/include/core/toolmenumanager.h | 6 ++- core/src/scopypreferencespage.cpp | 2 + core/src/toolmenumanager.cpp | 59 +++++++++++++++++++++++------ 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/core/include/core/toolmenumanager.h b/core/include/core/toolmenumanager.h index 5d00c19f32..779fd19b15 100644 --- a/core/include/core/toolmenumanager.h +++ b/core/include/core/toolmenumanager.h @@ -79,9 +79,13 @@ private Q_SLOTS: void showTool(ToolMenuItem *toolMenuItem); void selectTool(ToolMenuItem *toolMenuItem, bool on); void setTmeAttached(ToolMenuEntry *tme); - MenuSectionCollapseWidget *createMenuSectionItem(QString deviceId, DeviceInfo dInfo); + MenuSectionCollapseWidget *createMenuSectionItem(const DeviceInfo &dInfo, const QString &deviceId); ToolMenuItem *createToolMenuItem(ToolMenuEntry *tme, QWidget *parent = nullptr); MenuCollapseHeader *getCollapseSectionHeader(MenuSectionCollapseWidget *section); + void initHeaderWidget(MenuCollapseSection::MenuHeaderWidgetType type, MenuCollapseHeader *header, + const DeviceInfo &dInfo, const QString &deviceId); + void initToolMenuHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo, const QString &deviceId); + void initCompositeHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo); QString m_prevItem; QStringList m_connectedDev; diff --git a/core/src/scopypreferencespage.cpp b/core/src/scopypreferencespage.cpp index c8bf42f718..3446825320 100644 --- a/core/src/scopypreferencespage.cpp +++ b/core/src/scopypreferencespage.cpp @@ -281,6 +281,8 @@ QWidget *ScopyPreferencesPage::buildGeneralPreferencesPage() "Connect to multiple devices (EXPERIMENTAL)", generalSection)); generalSection->contentLayout()->addWidget(PreferencesHelper::addPreferenceCheckBox( p, "general_scan_for_devices", "Regularly scan for new devices", generalSection)); + generalSection->contentLayout()->addWidget(PreferencesHelper::addPreferenceCheckBox( + p, "device_menu_item", "Use detailed device header for tool menu", generalSection)); // Auto-connect m_autoConnectWidget = new MenuSectionCollapseWidget("Session devices", MenuCollapseSection::MHCW_NONE, diff --git a/core/src/toolmenumanager.cpp b/core/src/toolmenumanager.cpp index 09e5f9929f..92402f5f71 100644 --- a/core/src/toolmenumanager.cpp +++ b/core/src/toolmenumanager.cpp @@ -46,7 +46,7 @@ ToolMenuManager::~ToolMenuManager() {} void ToolMenuManager::addMenuItem(QString deviceId, DeviceInfo dInfo, int itemIndex) { - MenuSectionCollapseWidget *devSection = createMenuSectionItem(deviceId, dInfo); + MenuSectionCollapseWidget *devSection = createMenuSectionItem(dInfo, deviceId); QButtonGroup *menuBtnGroup = m_toolMenu->btnGroup(); for(ToolMenuEntry *tme : qAsConst(dInfo.tools)) { ToolMenuItem *toolMenuItem = createToolMenuItem(tme, devSection); @@ -288,24 +288,20 @@ void ToolMenuManager::setTmeAttached(ToolMenuEntry *tme) tme->setAttached(!tme->attached()); } -MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(QString deviceId, DeviceInfo dInfo) +MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(const DeviceInfo &dInfo, const QString &deviceId) { - MenuSectionCollapseWidget *section = new MenuSectionCollapseWidget( - dInfo.name, MenuCollapseSection::MHCW_ARROW, MenuCollapseSection::MHW_TOOLMENUWIDGET, m_toolMenu); + MenuCollapseSection::MenuHeaderWidgetType type = Preferences::get("device_menu_item").toBool() + ? MenuCollapseSection::MHW_TOOLMENUWIDGET + : MenuCollapseSection::MHW_COMPOSITEWIDGET; + MenuSectionCollapseWidget *section = + new MenuSectionCollapseWidget(dInfo.name, MenuCollapseSection::MHCW_ARROW, type, m_toolMenu); section->contentLayout()->setSpacing(0); section->menuSection()->layout()->setMargin(0); section->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); MenuCollapseHeader *collapseHeader = getCollapseSectionHeader(section); if(collapseHeader) { - ToolMenuHeaderWidget *thw = dynamic_cast(collapseHeader->headerWidget()); - if(thw) { - thw->setUri(dInfo.param); - thw->setDeviceIcon(dInfo.icon); - thw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); - connect(thw->deviceBtn(), &QPushButton::pressed, this, - [this, deviceId]() { Q_EMIT requestDevicePage(deviceId); }); - } + initHeaderWidget(type, collapseHeader, dInfo, deviceId); Style::setStyle(collapseHeader, style::properties::widget::bottomBorder); } section->setCollapsed(false); @@ -313,6 +309,45 @@ MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(QString device return section; } +void ToolMenuManager::initHeaderWidget(MenuCollapseSection::MenuHeaderWidgetType type, MenuCollapseHeader *header, + const DeviceInfo &dInfo, const QString &deviceId) +{ + switch(type) { + case MenuCollapseSection::MHW_TOOLMENUWIDGET: + initToolMenuHeaderWidget(header, dInfo, deviceId); + break; + case MenuCollapseSection::MHW_COMPOSITEWIDGET: + initCompositeHeaderWidget(header, dInfo); + break; + default: + break; + } +} + +void ToolMenuManager::initToolMenuHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo, + const QString &deviceId) +{ + ToolMenuHeaderWidget *thw = dynamic_cast(header->headerWidget()); + if(!thw) { + return; + } + thw->setUri(dInfo.param); + thw->setDeviceIcon(dInfo.icon); + thw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); + connect(thw->deviceBtn(), &QPushButton::pressed, this, + [this, deviceId]() { Q_EMIT requestDevicePage(deviceId); }); +} + +void ToolMenuManager::initCompositeHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo) +{ + CompositeHeaderWidget *chw = dynamic_cast(header->headerWidget()); + if(!chw) { + return; + } + chw->add(new QLabel(dInfo.param)); + chw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); +} + ToolMenuItem *ToolMenuManager::createToolMenuItem(ToolMenuEntry *tme, QWidget *parent) { ToolMenuItem *toolMenuItem = new ToolMenuItem(tme->uuid(), tme->name(), tme->icon(), parent); From 3925fdcd8d767ece817d82f4b7af3f23d1ed3538 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Tue, 26 Nov 2024 17:55:38 +0200 Subject: [PATCH 21/41] gui/toolmenuheaderwidget: Show connection status in menu item. Using ledBorder property. Signed-off-by: andreidanila1 --- core/include/core/toolmenumanager.h | 10 +++-- core/src/scopymainwindow.cpp | 4 +- core/src/toolmenumanager.cpp | 42 ++++++++++--------- .../gui/widgets/toolmenuheaderwidget.h | 5 +++ gui/src/widgets/toolmenuheaderwidget.cpp | 11 +++++ 5 files changed, 47 insertions(+), 25 deletions(-) diff --git a/core/include/core/toolmenumanager.h b/core/include/core/toolmenumanager.h index 779fd19b15..dd1e5f070d 100644 --- a/core/include/core/toolmenumanager.h +++ b/core/include/core/toolmenumanager.h @@ -37,6 +37,7 @@ namespace scopy { typedef struct { + QString id; QString name; QString param; QPixmap icon; @@ -50,7 +51,7 @@ class SCOPY_CORE_EXPORT ToolMenuManager : public QObject ToolMenuManager(ToolStack *ts, DetachedToolWindowManager *dtm, ToolMenu *toolMenu, QObject *parent = nullptr); ~ToolMenuManager(); - void addMenuItem(QString deviceId, DeviceInfo dInfo, int itemIndex = -1); + void addMenuItem(DeviceInfo dInfo, int itemIndex = -1); void removeMenuItem(QString deviceId); void changeToolListContents(QString deviceId, QList tools); @@ -66,6 +67,7 @@ public Q_SLOTS: Q_SIGNALS: void requestToolSelect(QString id); void requestDevicePage(QString id); + void connState(QString id, bool isConnected); private Q_SLOTS: void updateTool(QWidget *old); @@ -79,12 +81,12 @@ private Q_SLOTS: void showTool(ToolMenuItem *toolMenuItem); void selectTool(ToolMenuItem *toolMenuItem, bool on); void setTmeAttached(ToolMenuEntry *tme); - MenuSectionCollapseWidget *createMenuSectionItem(const DeviceInfo &dInfo, const QString &deviceId); + MenuSectionCollapseWidget *createMenuSectionItem(const DeviceInfo &dInfo); ToolMenuItem *createToolMenuItem(ToolMenuEntry *tme, QWidget *parent = nullptr); MenuCollapseHeader *getCollapseSectionHeader(MenuSectionCollapseWidget *section); void initHeaderWidget(MenuCollapseSection::MenuHeaderWidgetType type, MenuCollapseHeader *header, - const DeviceInfo &dInfo, const QString &deviceId); - void initToolMenuHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo, const QString &deviceId); + const DeviceInfo &dInfo); + void initToolMenuHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo); void initCompositeHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo); QString m_prevItem; diff --git a/core/src/scopymainwindow.cpp b/core/src/scopymainwindow.cpp index ea2fedaac3..010aceb1a6 100644 --- a/core/src/scopymainwindow.cpp +++ b/core/src/scopymainwindow.cpp @@ -611,8 +611,8 @@ void ScopyMainWindow::initApi() void ScopyMainWindow::addDeviceToUi(QString id, Device *d) { - DeviceInfo dInfo = {d->displayName(), d->param(), d->iconPixmap(), d->toolList()}; - m_toolMenuManager->addMenuItem(id, dInfo); + DeviceInfo dInfo = {id, d->displayName(), d->param(), d->iconPixmap(), d->toolList()}; + m_toolMenuManager->addMenuItem(dInfo); hp->addDevice(id, d); } diff --git a/core/src/toolmenumanager.cpp b/core/src/toolmenumanager.cpp index 92402f5f71..216767e77c 100644 --- a/core/src/toolmenumanager.cpp +++ b/core/src/toolmenumanager.cpp @@ -44,9 +44,10 @@ ToolMenuManager::ToolMenuManager(ToolStack *ts, DetachedToolWindowManager *dtm, ToolMenuManager::~ToolMenuManager() {} -void ToolMenuManager::addMenuItem(QString deviceId, DeviceInfo dInfo, int itemIndex) +void ToolMenuManager::addMenuItem(DeviceInfo dInfo, int itemIndex) { - MenuSectionCollapseWidget *devSection = createMenuSectionItem(dInfo, deviceId); + QString id = dInfo.id; + MenuSectionCollapseWidget *devSection = createMenuSectionItem(dInfo); QButtonGroup *menuBtnGroup = m_toolMenu->btnGroup(); for(ToolMenuEntry *tme : qAsConst(dInfo.tools)) { ToolMenuItem *toolMenuItem = createToolMenuItem(tme, devSection); @@ -55,15 +56,14 @@ void ToolMenuManager::addMenuItem(QString deviceId, DeviceInfo dInfo, int itemIn connect(tme, &ToolMenuEntry::updateTool, this, &ToolMenuManager::updateTool); connect(tme, &ToolMenuEntry::updateToolAttached, this, [this, toolMenuItem](bool oldAttach) { updateToolAttached(oldAttach, toolMenuItem); }); - connect(tme, &ToolMenuEntry::iioEvent, this, [this, deviceId](int retCode, scopy::IIOCallType type) { - onIioEvent(deviceId, retCode, type); - }); + connect(tme, &ToolMenuEntry::iioEvent, this, + [this, id](int retCode, scopy::IIOCallType type) { onIioEvent(id, retCode, type); }); Q_EMIT tme->updateToolEntry(); } - m_toolMenu->add(itemIndex, deviceId, devSection); - m_itemMap[deviceId] = devSection; - m_dInfoMap[deviceId] = dInfo; - qDebug(CAT_TOOLMENUMANAGER) << "Menu item with id" << deviceId << "has been added"; + m_toolMenu->add(itemIndex, id, devSection); + m_itemMap[id] = devSection; + m_dInfoMap[id] = dInfo; + qDebug(CAT_TOOLMENUMANAGER) << "Menu item with id" << id << "has been added"; } void ToolMenuManager::removeMenuItem(QString deviceId) @@ -93,7 +93,7 @@ void ToolMenuManager::changeToolListContents(QString deviceId, QListindexOf(menuItem); removeMenuItem(deviceId); - addMenuItem(deviceId, m_dInfoMap[deviceId], itemIndex); + addMenuItem(m_dInfoMap[deviceId], itemIndex); showMenuItem(deviceId); } @@ -106,7 +106,6 @@ void ToolMenuManager::showMenuItem(QString id) Q_EMIT requestToolSelect(id); return; } - m_itemMap[id]->show(); m_prevItem = id; } @@ -122,6 +121,7 @@ void ToolMenuManager::deviceConnected(QString id) { m_connectedDev.append(id); showMenuItem(id); + Q_EMIT connState(id, true); } void ToolMenuManager::deviceDisconnected(QString id) @@ -130,6 +130,7 @@ void ToolMenuManager::deviceDisconnected(QString id) if(m_prevItem.compare(id) != 0) { hideMenuItem(id); } + Q_EMIT connState(id, false); } void ToolMenuManager::onDisplayNameChanged(QString id, QString devName) @@ -288,7 +289,7 @@ void ToolMenuManager::setTmeAttached(ToolMenuEntry *tme) tme->setAttached(!tme->attached()); } -MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(const DeviceInfo &dInfo, const QString &deviceId) +MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(const DeviceInfo &dInfo) { MenuCollapseSection::MenuHeaderWidgetType type = Preferences::get("device_menu_item").toBool() ? MenuCollapseSection::MHW_TOOLMENUWIDGET @@ -301,7 +302,7 @@ MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(const DeviceIn MenuCollapseHeader *collapseHeader = getCollapseSectionHeader(section); if(collapseHeader) { - initHeaderWidget(type, collapseHeader, dInfo, deviceId); + initHeaderWidget(type, collapseHeader, dInfo); Style::setStyle(collapseHeader, style::properties::widget::bottomBorder); } section->setCollapsed(false); @@ -310,11 +311,11 @@ MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(const DeviceIn } void ToolMenuManager::initHeaderWidget(MenuCollapseSection::MenuHeaderWidgetType type, MenuCollapseHeader *header, - const DeviceInfo &dInfo, const QString &deviceId) + const DeviceInfo &dInfo) { switch(type) { case MenuCollapseSection::MHW_TOOLMENUWIDGET: - initToolMenuHeaderWidget(header, dInfo, deviceId); + initToolMenuHeaderWidget(header, dInfo); break; case MenuCollapseSection::MHW_COMPOSITEWIDGET: initCompositeHeaderWidget(header, dInfo); @@ -324,18 +325,21 @@ void ToolMenuManager::initHeaderWidget(MenuCollapseSection::MenuHeaderWidgetType } } -void ToolMenuManager::initToolMenuHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo, - const QString &deviceId) +void ToolMenuManager::initToolMenuHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo) { + bool isConnected = m_connectedDev.contains(dInfo.id); ToolMenuHeaderWidget *thw = dynamic_cast(header->headerWidget()); if(!thw) { return; } + thw->setDeviceId(dInfo.id); thw->setUri(dInfo.param); thw->setDeviceIcon(dInfo.icon); thw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); - connect(thw->deviceBtn(), &QPushButton::pressed, this, - [this, deviceId]() { Q_EMIT requestDevicePage(deviceId); }); + Style::setStyle(header, style::properties::widget::ledBorder, isConnected); + + connect(thw->deviceBtn(), &QPushButton::pressed, this, [this, dInfo]() { Q_EMIT requestDevicePage(dInfo.id); }); + connect(this, &ToolMenuManager::connState, thw, &ToolMenuHeaderWidget::connState); } void ToolMenuManager::initCompositeHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo) diff --git a/gui/include/gui/widgets/toolmenuheaderwidget.h b/gui/include/gui/widgets/toolmenuheaderwidget.h index e5b9e2a765..4105e6872f 100644 --- a/gui/include/gui/widgets/toolmenuheaderwidget.h +++ b/gui/include/gui/widgets/toolmenuheaderwidget.h @@ -45,9 +45,13 @@ class SCOPY_GUI_EXPORT ToolMenuHeaderWidget : public QWidget, public BaseHeader QString title() override; void setDeviceIcon(QPixmap icon); void setUri(QString uri); + void setDeviceId(QString deviceId); QPushButton *deviceBtn() const; + void setState(QString id, bool state, QWidget *parent); + Q_SIGNALS: + void connState(QString id, bool isConnected); void blinkLed(int retCode, IIOCallType type); private Q_SLOTS: @@ -55,6 +59,7 @@ private Q_SLOTS: private: QTimer *m_timer; + QString m_id; LedButton *m_ledBtn; QPushButton *m_deviceBtn; QLineEdit *m_title; diff --git a/gui/src/widgets/toolmenuheaderwidget.cpp b/gui/src/widgets/toolmenuheaderwidget.cpp index c4a2e97fd0..ef805e8688 100644 --- a/gui/src/widgets/toolmenuheaderwidget.cpp +++ b/gui/src/widgets/toolmenuheaderwidget.cpp @@ -69,6 +69,8 @@ ToolMenuHeaderWidget::ToolMenuHeaderWidget(QString title, QWidget *parent) connect(m_timer, &QTimer::timeout, m_timer, &QTimer::stop); connect(this, &ToolMenuHeaderWidget::blinkLed, this, &ToolMenuHeaderWidget::onBlinkLed); + connect(this, &ToolMenuHeaderWidget::connState, this, + [this, parent](QString id, bool isConnected) { setState(id, isConnected, parent); }); } ToolMenuHeaderWidget::~ToolMenuHeaderWidget() {} @@ -92,6 +94,8 @@ void ToolMenuHeaderWidget::setUri(QString uri) m_uriLabel->setText(uri); } +void ToolMenuHeaderWidget::setDeviceId(QString deviceId) { m_id = deviceId; } + void ToolMenuHeaderWidget::onBlinkLed(int retCode, IIOCallType type) { switch(type) { @@ -112,4 +116,11 @@ void ToolMenuHeaderWidget::onBlinkLed(int retCode, IIOCallType type) QPushButton *ToolMenuHeaderWidget::deviceBtn() const { return m_deviceBtn; } +void ToolMenuHeaderWidget::setState(QString id, bool state, QWidget *parent) +{ + if(m_id == id) { + Style::setStyle(parent, style::properties::widget::ledBorder, state); + } +} + #include "moc_toolmenuheaderwidget.cpp" From b5eaab973352fa0202a20cfa3c1607e7fa40cd9f Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 28 Nov 2024 16:52:48 +0200 Subject: [PATCH 22/41] style/qss/properties/widget: Added deviceHeaderWidget style. Signed-off-by: andreidanila1 --- .../qss/properties/widget/deviceHeaderWidget.qss | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 gui/style/qss/properties/widget/deviceHeaderWidget.qss diff --git a/gui/style/qss/properties/widget/deviceHeaderWidget.qss b/gui/style/qss/properties/widget/deviceHeaderWidget.qss new file mode 100644 index 0000000000..da4ce75064 --- /dev/null +++ b/gui/style/qss/properties/widget/deviceHeaderWidget.qss @@ -0,0 +1,14 @@ +QWidget[&&property&&="idle"] { + background-color: transparent; + color: &content_default&; +} + +QWidget[&&property&&="idle"]:hover { + background-color: &content_silent&; + color: &content_default&; +} + +QWidget[&&property&&="selected"] { + background-color: &interactive_subtle_disabled&; + color: &content_default&; +} From 1d082576d05fa6bcc42a78a5d8c057a4e8b801ec Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 28 Nov 2024 14:24:32 +0200 Subject: [PATCH 23/41] core/toolmenumanager: Highlight device header on hover and selection. Signed-off-by: andreidanila1 --- core/src/toolmenumanager.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/src/toolmenumanager.cpp b/core/src/toolmenumanager.cpp index 216767e77c..40a743f193 100644 --- a/core/src/toolmenumanager.cpp +++ b/core/src/toolmenumanager.cpp @@ -304,6 +304,7 @@ MenuSectionCollapseWidget *ToolMenuManager::createMenuSectionItem(const DeviceIn if(collapseHeader) { initHeaderWidget(type, collapseHeader, dInfo); Style::setStyle(collapseHeader, style::properties::widget::bottomBorder); + Style::setStyle(collapseHeader, style::properties::widget::deviceHeaderWidget, "idle"); } section->setCollapsed(false); section->hide(); @@ -329,6 +330,7 @@ void ToolMenuManager::initToolMenuHeaderWidget(MenuCollapseHeader *header, const { bool isConnected = m_connectedDev.contains(dInfo.id); ToolMenuHeaderWidget *thw = dynamic_cast(header->headerWidget()); + QButtonGroup *menuBtnGroup = m_toolMenu->btnGroup(); if(!thw) { return; } @@ -338,7 +340,15 @@ void ToolMenuManager::initToolMenuHeaderWidget(MenuCollapseHeader *header, const thw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); Style::setStyle(header, style::properties::widget::ledBorder, isConnected); - connect(thw->deviceBtn(), &QPushButton::pressed, this, [this, dInfo]() { Q_EMIT requestDevicePage(dInfo.id); }); + menuBtnGroup->addButton(thw->deviceBtn()); + connect(thw->deviceBtn(), &QPushButton::toggled, this, [=](bool en) { + if(en) { + Style::setStyle(header, style::properties::widget::deviceHeaderWidget, "selected"); + Q_EMIT requestDevicePage(dInfo.id); + } else { + Style::setStyle(header, style::properties::widget::deviceHeaderWidget, "idle"); + } + }); connect(this, &ToolMenuManager::connState, thw, &ToolMenuHeaderWidget::connState); } From 93c8c9a5ef124fa3944b7816b4a200dcef0ad33a Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 28 Nov 2024 16:36:47 +0200 Subject: [PATCH 24/41] pluginbase: Added config page. Plugins can now override the loadConfigPage method to create a custom configuration widget. This widget, containing all necessary information, is represented by m_configPage from the PluginBase class. The widget can be accessed form outside the class using the configPage() getter. Signed-off-by: andreidanila1 --- pluginbase/include/pluginbase/plugin.h | 14 ++++++++++++++ pluginbase/include/pluginbase/pluginbase.h | 3 +++ pluginbase/src/pluginbase.cpp | 9 +++++++++ 3 files changed, 26 insertions(+) diff --git a/pluginbase/include/pluginbase/plugin.h b/pluginbase/include/pluginbase/plugin.h index a1140cf115..233dbd72c9 100644 --- a/pluginbase/include/pluginbase/plugin.h +++ b/pluginbase/include/pluginbase/plugin.h @@ -190,6 +190,13 @@ class SCOPY_PLUGINBASE_EXPORT Plugin * Default implementation in PluginBase - can be overriden */ virtual bool loadPage() = 0; + /** + * @brief loadConfigPage + * is called postcompatible. initialize m_configPage widget. This widget is added to the device configpage + * @return bool if page is loaded + * Default implementation in PluginBase - can be overriden + */ + virtual bool loadConfigPage() = 0; /** * @brief loadToolList * is called postcompatible. initialize m_toolList. m_toolList is used to populate tool menu @@ -289,6 +296,13 @@ class SCOPY_PLUGINBASE_EXPORT Plugin */ virtual QWidget *page() = 0; + /** + * @brief configPage + * @return plugin m_configPage getter - plugin configpage widget. used to create device configpage + * Default implementation in PluginBase - override not recommended + */ + virtual QWidget *configPage() = 0; + /** * @brief preferencesPage * @return plugin m_preferencesPage getter - preferences widget diff --git a/pluginbase/include/pluginbase/pluginbase.h b/pluginbase/include/pluginbase/pluginbase.h index e7149a4fc1..ee71e07299 100644 --- a/pluginbase/include/pluginbase/pluginbase.h +++ b/pluginbase/include/pluginbase/pluginbase.h @@ -51,6 +51,7 @@ class SCOPY_PLUGINBASE_EXPORT PluginBase : public Plugin virtual bool loadIcon() override; virtual bool loadPage() override; + virtual bool loadConfigPage() override; virtual void loadToolList() override; virtual bool loadPreferencesPage() override; virtual bool loadExtraButtons() override; @@ -67,6 +68,7 @@ class SCOPY_PLUGINBASE_EXPORT PluginBase : public Plugin virtual QString displayParam() override; virtual QWidget *icon() override; virtual QWidget *page() override; + virtual QWidget *configPage() override; virtual QWidget *preferencesPage() override; virtual QList extraButtons() override; virtual QList toolList() override; @@ -97,6 +99,7 @@ public Q_SLOTS: QString m_displayName; QString m_displayParam; QWidget *m_page; + QWidget *m_configPage; QWidget *m_preferencesPage; QWidget *m_icon; QList m_toolList; diff --git a/pluginbase/src/pluginbase.cpp b/pluginbase/src/pluginbase.cpp index bacdf0c29d..5d49e0dfb1 100644 --- a/pluginbase/src/pluginbase.cpp +++ b/pluginbase/src/pluginbase.cpp @@ -56,6 +56,12 @@ bool PluginBase::loadPage() return false; } +bool PluginBase::loadConfigPage() +{ + m_configPage = nullptr; + return false; +} + void PluginBase::loadToolList() {} bool PluginBase::loadPreferencesPage() @@ -94,8 +100,11 @@ QString PluginBase::displayName() { return m_displayName; } QString PluginBase::displayParam() { return m_displayParam; } QWidget *PluginBase::icon() { return m_icon; } + QWidget *PluginBase::page() { return m_page; } +QWidget *PluginBase::configPage() { return m_configPage; } + QWidget *PluginBase::preferencesPage() { return m_preferencesPage; } QList PluginBase::extraButtons() { return m_extraButtons; } From 1a96b705806b54588acd0e7c6603602483a2b352 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Thu, 28 Nov 2024 16:49:08 +0200 Subject: [PATCH 25/41] core: Create device config page. The device configuration page is a tab widget that contains configuration pages for all its compatible plugins, with each tab representing a plugin's configuration page. This device configuration page is added into the ScopyMainWindow tool stack and can be accessed by clicking the 'Device' button in the tool menu. Signed-off-by: andreidanila1 --- core/include/core/device.h | 1 + core/include/core/deviceimpl.h | 4 ++++ core/include/core/scopymainwindow.h | 1 - core/include/core/toolmenumanager.h | 1 - core/src/deviceimpl.cpp | 15 +++++++++++++++ core/src/scopymainwindow.cpp | 13 ++++--------- core/src/toolmenumanager.cpp | 2 +- 7 files changed, 25 insertions(+), 12 deletions(-) diff --git a/core/include/core/device.h b/core/include/core/device.h index 53a32956f5..3dac1b9bf7 100644 --- a/core/include/core/device.h +++ b/core/include/core/device.h @@ -51,6 +51,7 @@ class SCOPY_CORE_EXPORT Device virtual QPixmap iconPixmap() = 0; virtual QWidget *page() = 0; + virtual QWidget *configPage() = 0; virtual QList toolList() = 0; virtual void init() = 0; diff --git a/core/include/core/deviceimpl.h b/core/include/core/deviceimpl.h index 8209bdb86e..dba938ab07 100644 --- a/core/include/core/deviceimpl.h +++ b/core/include/core/deviceimpl.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace scopy { @@ -50,6 +51,7 @@ class SCOPY_CORE_EXPORT DeviceImpl : public QObject, public Device QWidget *icon() override; QPixmap iconPixmap() override; QWidget *page() override; + QWidget *configPage() override; QList toolList() override; virtual void init() override; virtual void preload() override; @@ -85,6 +87,7 @@ public Q_SLOTS: void loadName(); void loadIcons(); void loadPages(); + void loadConfigPage(); void loadToolList(); void loadBadges(); void setPingPlugin(Plugin *plugin); @@ -103,6 +106,7 @@ public Q_SLOTS: QString m_param; QWidget *m_icon; QWidget *m_page; + QTabWidget *m_configPage; QPushButton *connbtn, *discbtn; Plugin *m_pingPlugin = nullptr; }; diff --git a/core/include/core/scopymainwindow.h b/core/include/core/scopymainwindow.h index 027b3e2b4d..5e4263e017 100644 --- a/core/include/core/scopymainwindow.h +++ b/core/include/core/scopymainwindow.h @@ -108,7 +108,6 @@ public Q_SLOTS: void handleScanner(); void enableScanner(); void deviceAutoconnect(); - void showDevicePage(QString id, ToolStack *ts); protected: void closeEvent(QCloseEvent *event) override; diff --git a/core/include/core/toolmenumanager.h b/core/include/core/toolmenumanager.h index dd1e5f070d..0c2d5a9f15 100644 --- a/core/include/core/toolmenumanager.h +++ b/core/include/core/toolmenumanager.h @@ -66,7 +66,6 @@ public Q_SLOTS: Q_SIGNALS: void requestToolSelect(QString id); - void requestDevicePage(QString id); void connState(QString id, bool isConnected); private Q_SLOTS: diff --git a/core/src/deviceimpl.cpp b/core/src/deviceimpl.cpp index 8b07c6a097..356e098934 100644 --- a/core/src/deviceimpl.cpp +++ b/core/src/deviceimpl.cpp @@ -89,6 +89,7 @@ void DeviceImpl::loadPlugins() loadIcons(); loadBadges(); loadPages(); + loadConfigPage(); loadToolList(); if(m_plugins.isEmpty()) { connbtn->hide(); @@ -215,6 +216,18 @@ void DeviceImpl::loadPages() } } +void DeviceImpl::loadConfigPage() +{ + m_configPage = new QTabWidget(); + m_configPage->setTabPosition(QTabWidget::South); + + for(auto &&p : plugins()) { + if(p->loadConfigPage()) { + m_configPage->addTab(p->configPage(), p->name()); + } + } +} + void DeviceImpl::loadToolList() { for(auto &&p : m_plugins) { @@ -449,6 +462,8 @@ QPixmap DeviceImpl::iconPixmap() return pixmap; } +QWidget *DeviceImpl::configPage() { return m_configPage; } + QWidget *DeviceImpl::page() { return m_page; } QList DeviceImpl::toolList() diff --git a/core/src/scopymainwindow.cpp b/core/src/scopymainwindow.cpp index 010aceb1a6..8d7f2f8e55 100644 --- a/core/src/scopymainwindow.cpp +++ b/core/src/scopymainwindow.cpp @@ -181,8 +181,6 @@ ScopyMainWindow::ScopyMainWindow(QWidget *parent) connect(dm, &DeviceManager::requestTool, m_toolMenuManager, &ToolMenuManager::showMenuItem); connect(m_toolMenuManager, &ToolMenuManager::requestToolSelect, ts, &ToolStack::show); connect(m_toolMenuManager, &ToolMenuManager::requestToolSelect, dtm, &DetachedToolWindowManager::show); - connect(m_toolMenuManager, &ToolMenuManager::requestDevicePage, this, - [this, ts](QString id) { showDevicePage(id, ts); }); connect(hp, &ScopyHomePage::displayNameChanged, m_toolMenuManager, &ToolMenuManager::onDisplayNameChanged); connect(hp, &ScopyHomePage::newDeviceAvailable, dm, &DeviceManager::addDevice); @@ -255,13 +253,6 @@ void ScopyMainWindow::deviceAutoconnect() } } -void ScopyMainWindow::showDevicePage(QString id, ToolStack *ts) -{ - QString hpKey = ts->getKey(hp); - ts->show(hpKey); - hp->viewDevice(id); -} - void ScopyMainWindow::save() { QString selectedFilter; @@ -614,12 +605,16 @@ void ScopyMainWindow::addDeviceToUi(QString id, Device *d) DeviceInfo dInfo = {id, d->displayName(), d->param(), d->iconPixmap(), d->toolList()}; m_toolMenuManager->addMenuItem(dInfo); hp->addDevice(id, d); + auto ts = ui->wsToolStack; + ts->add(id, d->configPage()); } void ScopyMainWindow::removeDeviceFromUi(QString id) { m_toolMenuManager->removeMenuItem(id); hp->removeDevice(id); + auto ts = ui->wsToolStack; + ts->remove(id); } void ScopyMainWindow::receiveVersionDocument(QJsonDocument document) diff --git a/core/src/toolmenumanager.cpp b/core/src/toolmenumanager.cpp index 40a743f193..2728682326 100644 --- a/core/src/toolmenumanager.cpp +++ b/core/src/toolmenumanager.cpp @@ -344,7 +344,7 @@ void ToolMenuManager::initToolMenuHeaderWidget(MenuCollapseHeader *header, const connect(thw->deviceBtn(), &QPushButton::toggled, this, [=](bool en) { if(en) { Style::setStyle(header, style::properties::widget::deviceHeaderWidget, "selected"); - Q_EMIT requestDevicePage(dInfo.id); + Q_EMIT requestToolSelect(dInfo.id); } else { Style::setStyle(header, style::properties::widget::deviceHeaderWidget, "idle"); } From 393b9e6665d7929335a9d5cb286c518ba0be34b4 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Mon, 2 Dec 2024 12:40:31 +0200 Subject: [PATCH 26/41] core/scopymainwindow: Added collapseToolMenu method. Signed-off-by: andreidanila1 --- core/include/core/scopymainwindow.h | 1 + core/src/scopymainwindow.cpp | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/core/include/core/scopymainwindow.h b/core/include/core/scopymainwindow.h index 5e4263e017..552a44420d 100644 --- a/core/include/core/scopymainwindow.h +++ b/core/include/core/scopymainwindow.h @@ -108,6 +108,7 @@ public Q_SLOTS: void handleScanner(); void enableScanner(); void deviceAutoconnect(); + void collapseToolMenu(bool collapse); protected: void closeEvent(QCloseEvent *event) override; diff --git a/core/src/scopymainwindow.cpp b/core/src/scopymainwindow.cpp index 8d7f2f8e55..6de05ad689 100644 --- a/core/src/scopymainwindow.cpp +++ b/core/src/scopymainwindow.cpp @@ -96,22 +96,13 @@ ScopyMainWindow::ScopyMainWindow(QWidget *parent) auto ts = ui->wsToolStack; - //////// BrowseMenu *browseMenu = new BrowseMenu(ui->wToolBrowser); ui->wToolBrowser->layout()->addWidget(browseMenu); - connect(browseMenu, &BrowseMenu::requestTool, ts, &ToolStack::show, Qt::QueuedConnection); connect(browseMenu, SIGNAL(requestLoad()), this, SLOT(load())); connect(browseMenu, SIGNAL(requestSave()), this, SLOT(save())); - connect(browseMenu, &BrowseMenu::collapsed, this, [this](bool coll) { - if(coll) { - ui->animHolder->setAnimMin(Style::getDimension(json::global::unit_4)); - } else { - ui->animHolder->setAnimMax(230); - } - ui->animHolder->toggleMenu(!coll); - }); - //////// + connect(browseMenu, &BrowseMenu::collapsed, this, &ScopyMainWindow::collapseToolMenu); + Style::setBackgroundColor(ui->centralwidget, json::theme::background_primary); scanTask = new IIOScanTask(this); @@ -253,6 +244,16 @@ void ScopyMainWindow::deviceAutoconnect() } } +void ScopyMainWindow::collapseToolMenu(bool collapse) +{ + if(collapse) { + ui->animHolder->setAnimMin(Style::getDimension(json::global::unit_4)); + } else { + ui->animHolder->setAnimMax(230); + } + ui->animHolder->toggleMenu(!collapse); +} + void ScopyMainWindow::save() { QString selectedFilter; From fd827c523de35f9d0c54849f1ab5f75075943524 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Mon, 2 Dec 2024 12:44:46 +0200 Subject: [PATCH 27/41] core/toolmenu: Show icons when collapsed. Signed-off-by: andreidanila1 --- core/include/core/browsemenu.h | 1 + core/include/core/toolmenuitem.h | 2 +- core/include/core/toolmenumanager.h | 3 +++ core/src/browsemenu.cpp | 21 ++++++++++++++++++--- core/src/scopymainwindow.cpp | 3 ++- core/src/toolmenuitem.cpp | 10 ++++++++++ core/src/toolmenumanager.cpp | 7 ++++++- gui/style/json/global.json | 1 + 8 files changed, 42 insertions(+), 6 deletions(-) diff --git a/core/include/core/browsemenu.h b/core/include/core/browsemenu.h index 03da7910e2..1c4eba42c3 100644 --- a/core/include/core/browsemenu.h +++ b/core/include/core/browsemenu.h @@ -55,6 +55,7 @@ class SCOPY_CORE_EXPORT BrowseMenu : public QWidget private: void add(QWidget *w, QString name, MenuAlignment position); void toggleCollapsed(); + void hideBtnText(QPushButton *btn, QString name, bool hide); QPushButton *createBtn(QString name, QString iconPath, QWidget *parent = nullptr); QFrame *createHLine(QWidget *parent = nullptr); QWidget *createHeader(QWidget *parent = nullptr); diff --git a/core/include/core/toolmenuitem.h b/core/include/core/toolmenuitem.h index 2dc1a7f8ca..3930b6c5b0 100644 --- a/core/include/core/toolmenuitem.h +++ b/core/include/core/toolmenuitem.h @@ -49,13 +49,13 @@ class ToolMenuItem : public QPushButton public Q_SLOTS: void setDisabled(bool disabled); void updateItem(); + void onCollapsed(bool collapsed); protected: void enterEvent(QEvent *event); void leaveEvent(QEvent *event); private: - // QPushButton *m_toolBtn; CustomPushButton *m_toolRunBtn; QString m_uuid; diff --git a/core/include/core/toolmenumanager.h b/core/include/core/toolmenumanager.h index 0c2d5a9f15..66cf2d98e5 100644 --- a/core/include/core/toolmenumanager.h +++ b/core/include/core/toolmenumanager.h @@ -67,10 +67,12 @@ public Q_SLOTS: Q_SIGNALS: void requestToolSelect(QString id); void connState(QString id, bool isConnected); + void menuCollapsed(bool collapsed); private Q_SLOTS: void updateTool(QWidget *old); void updateToolAttached(bool oldAttach, ToolMenuItem *toolMenuItem); + void setCollapsed(bool collapse); private: void loadToolAttachedState(ToolMenuEntry *tme); @@ -88,6 +90,7 @@ private Q_SLOTS: void initToolMenuHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo); void initCompositeHeaderWidget(MenuCollapseHeader *header, const DeviceInfo &dInfo); + bool m_collapsed; QString m_prevItem; QStringList m_connectedDev; ToolStack *m_ts; diff --git a/core/src/browsemenu.cpp b/core/src/browsemenu.cpp index 576496570b..95f680e2e8 100644 --- a/core/src/browsemenu.cpp +++ b/core/src/browsemenu.cpp @@ -63,6 +63,8 @@ BrowseMenu::BrowseMenu(QWidget *parent) homeBtn->setIconSize(QSize(32, 32)); homeBtn->setStyleSheet("text-align: left"); connect(homeBtn, &QPushButton::clicked, this, [=]() { Q_EMIT requestTool("home"); }); + connect(this, &BrowseMenu::collapsed, homeBtn, + [this, homeBtn](bool collapsed) { hideBtnText(homeBtn, tr("Home"), collapsed); }); QWidget *saveLoadWidget = new QWidget(m_content); saveLoadWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); @@ -93,6 +95,8 @@ BrowseMenu::BrowseMenu(QWidget *parent) QPushButton *aboutBtn = createBtn( "About", ":/gui/icons/" + Style::getAttribute(json::theme::icon_theme_folder) + "/icons/info.svg", m_content); + aboutBtn->setIconSize( + QSize(Style::getDimension(json::global::unit_2), Style::getDimension(json::global::unit_2))); connect(aboutBtn, &QPushButton::clicked, this, [=]() { Q_EMIT requestTool("about"); }); aboutBtn->setCheckable(true); @@ -139,16 +143,26 @@ void BrowseMenu::toggleCollapsed() { m_collapsed = !m_collapsed; m_btnCollapse->setHidden(m_collapsed); - m_content->setHidden(m_collapsed); Q_EMIT collapsed(m_collapsed); } +void BrowseMenu::hideBtnText(QPushButton *btn, QString name, bool hide) +{ + if(hide) { + btn->setText(""); + } else { + btn->setText(name); + } +} + QPushButton *BrowseMenu::createBtn(QString name, QString iconPath, QWidget *parent) { QPushButton *btn = new QPushButton(parent); btn->setIcon(QIcon(iconPath)); btn->setText(tr(name.toStdString().c_str())); - Style::setStyle(btn, style::properties::button::toolButton); + Style::setStyle(btn, style::properties::button::toolButton, true); + connect(this, &BrowseMenu::collapsed, btn, + [this, btn, name](bool collapsed) { hideBtnText(btn, tr(name.toStdString().c_str()), collapsed); }); return btn; } @@ -172,7 +186,7 @@ QWidget *BrowseMenu::createHeader(QWidget *parent) Style::setStyle(btnCollapseMini, style::properties::widget::toolMenu); Style::setStyle(btnCollapseMini, style::properties::button::toolButton); btnCollapseMini->setCheckable(true); - btnCollapseMini->setFixedSize(Style::getDimension(json::global::unit_4), + btnCollapseMini->setFixedSize(Style::getDimension(json::global::unit_4_5), Style::getDimension(json::global::unit_4)); headerLay->addWidget(btnCollapseMini); @@ -190,6 +204,7 @@ QLabel *BrowseMenu::createScopyLogo(QWidget *parent) { QLabel *logo = new QLabel(m_content); Style::setStyle(logo, style::properties::widget::logo); + connect(this, &BrowseMenu::collapsed, logo, &QWidget::setHidden); return logo; } diff --git a/core/src/scopymainwindow.cpp b/core/src/scopymainwindow.cpp index 6de05ad689..891e7263f5 100644 --- a/core/src/scopymainwindow.cpp +++ b/core/src/scopymainwindow.cpp @@ -173,6 +173,7 @@ ScopyMainWindow::ScopyMainWindow(QWidget *parent) connect(m_toolMenuManager, &ToolMenuManager::requestToolSelect, ts, &ToolStack::show); connect(m_toolMenuManager, &ToolMenuManager::requestToolSelect, dtm, &DetachedToolWindowManager::show); connect(hp, &ScopyHomePage::displayNameChanged, m_toolMenuManager, &ToolMenuManager::onDisplayNameChanged); + connect(browseMenu, &BrowseMenu::collapsed, m_toolMenuManager, &ToolMenuManager::menuCollapsed); connect(hp, &ScopyHomePage::newDeviceAvailable, dm, &DeviceManager::addDevice); @@ -247,7 +248,7 @@ void ScopyMainWindow::deviceAutoconnect() void ScopyMainWindow::collapseToolMenu(bool collapse) { if(collapse) { - ui->animHolder->setAnimMin(Style::getDimension(json::global::unit_4)); + ui->animHolder->setAnimMin(Style::getDimension(json::global::unit_4_5)); } else { ui->animHolder->setAnimMax(230); } diff --git a/core/src/toolmenuitem.cpp b/core/src/toolmenuitem.cpp index 9c46a243d1..a60222315b 100644 --- a/core/src/toolmenuitem.cpp +++ b/core/src/toolmenuitem.cpp @@ -144,6 +144,16 @@ void ToolMenuItem::updateItem() qDebug(CAT_TOOLMENUITEM) << "updating toolmenuentry for " << tme->name() << " - " << tme->uuid(); } +void ToolMenuItem::onCollapsed(bool collapsed) +{ + m_toolRunBtn->setHidden(collapsed); + if(collapsed) { + setText(""); + } else { + setText(m_name); + } +} + void ToolMenuItem::enterEvent(QEvent *event) { #ifndef __ANDROID__ diff --git a/core/src/toolmenumanager.cpp b/core/src/toolmenumanager.cpp index 2728682326..63ec5ebafc 100644 --- a/core/src/toolmenumanager.cpp +++ b/core/src/toolmenumanager.cpp @@ -156,7 +156,6 @@ void ToolMenuManager::onIioEvent(QString id, int retCode, IIOCallType type) void ToolMenuManager::updateTool(QWidget *old) { - ToolMenuEntry *tme = dynamic_cast(QObject::sender()); Q_ASSERT(tme); QString id = tme->uuid(); @@ -224,6 +223,8 @@ void ToolMenuManager::updateToolAttached(bool oldAttach, ToolMenuItem *toolMenuI } } +void ToolMenuManager::setCollapsed(bool collapse) { m_collapsed = collapse; } + void ToolMenuManager::loadToolAttachedState(ToolMenuEntry *tme) { Preferences *p = Preferences::GetInstance(); @@ -360,11 +361,14 @@ void ToolMenuManager::initCompositeHeaderWidget(MenuCollapseHeader *header, cons } chw->add(new QLabel(dInfo.param)); chw->layout()->setContentsMargins(Style::getDimension(json::global::unit_1), 0, 0, 0); + chw->setHidden(m_collapsed); + connect(this, &ToolMenuManager::menuCollapsed, chw, &QWidget::setHidden); } ToolMenuItem *ToolMenuManager::createToolMenuItem(ToolMenuEntry *tme, QWidget *parent) { ToolMenuItem *toolMenuItem = new ToolMenuItem(tme->uuid(), tme->name(), tme->icon(), parent); + toolMenuItem->onCollapsed(m_collapsed); connect(toolMenuItem->getToolRunBtn(), &QPushButton::toggled, tme, &ToolMenuEntry::runToggled); connect(toolMenuItem->getToolRunBtn(), &QPushButton::clicked, tme, &ToolMenuEntry::runClicked); connect(toolMenuItem, &QPushButton::clicked, this, [=]() { Q_EMIT requestToolSelect(toolMenuItem->getId()); }); @@ -372,6 +376,7 @@ ToolMenuItem *ToolMenuManager::createToolMenuItem(ToolMenuEntry *tme, QWidget *p [this, toolMenuItem](bool on) { selectTool(toolMenuItem, on); }); connect(toolMenuItem, &ToolMenuItem::doubleclick, this, [this, tme]() { setTmeAttached(tme); }); connect(tme, &ToolMenuEntry::updateToolEntry, toolMenuItem, &ToolMenuItem::updateItem); + connect(this, &ToolMenuManager::menuCollapsed, toolMenuItem, &ToolMenuItem::onCollapsed); return toolMenuItem; } diff --git a/gui/style/json/global.json b/gui/style/json/global.json index 45a2e23835..43df67f038 100644 --- a/gui/style/json/global.json +++ b/gui/style/json/global.json @@ -11,6 +11,7 @@ "unit_2_5": "32", "unit_3": "36", "unit_4": "48", +"unit_4_5": "54", "unit_5": "80", "unit_6": "128", "radius_interactive": "4", From 806f8c93149b82fb96be6916818e25c76f84220b Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Tue, 10 Dec 2024 17:01:14 +0200 Subject: [PATCH 28/41] gui/toolmenuheaderwidget: Changed blinking model. The LED button no longer includes a timer, while the ToolMenuHeaderWidget now manages two timers. Signed-off-by: andreidanila1 --- gui/include/gui/widgets/ledbutton.h | 3 +- .../gui/widgets/toolmenuheaderwidget.h | 17 ++++- gui/src/widgets/ledbutton.cpp | 20 ++--- gui/src/widgets/toolmenuheaderwidget.cpp | 76 +++++++++++++++++-- 4 files changed, 91 insertions(+), 25 deletions(-) diff --git a/gui/include/gui/widgets/ledbutton.h b/gui/include/gui/widgets/ledbutton.h index 4f5a474341..74bd07695d 100644 --- a/gui/include/gui/widgets/ledbutton.h +++ b/gui/include/gui/widgets/ledbutton.h @@ -33,7 +33,8 @@ class LedButton : public QPushButton LedButton(QWidget *parent = nullptr); ~LedButton(); - void ledOn(bool ledState, int runningTimeMsec = 100); + void setLedState(bool ledState); + void ledOn(); void ledOff(); private: diff --git a/gui/include/gui/widgets/toolmenuheaderwidget.h b/gui/include/gui/widgets/toolmenuheaderwidget.h index 4105e6872f..ec5a7b4ad6 100644 --- a/gui/include/gui/widgets/toolmenuheaderwidget.h +++ b/gui/include/gui/widgets/toolmenuheaderwidget.h @@ -32,12 +32,20 @@ #include #include #include +#include namespace scopy { class SCOPY_GUI_EXPORT ToolMenuHeaderWidget : public QWidget, public BaseHeader { Q_OBJECT public: + typedef enum + { + SINGLE_INTERRUPT, + STREAM_RUNNING, + SINGLE_RUNNING, + IDLE + } LedState; ToolMenuHeaderWidget(QString title, QWidget *parent); ~ToolMenuHeaderWidget(); @@ -56,16 +64,23 @@ class SCOPY_GUI_EXPORT ToolMenuHeaderWidget : public QWidget, public BaseHeader private Q_SLOTS: void onBlinkLed(int retCode, IIOCallType type); + void refresh(); + void onTimeout(); private: + void handleSingle(bool isSuccess); + void handleStream(bool isSuccess); + + QTimer *m_refreshTimer; QTimer *m_timer; QString m_id; LedButton *m_ledBtn; QPushButton *m_deviceBtn; QLineEdit *m_title; QLabel *m_uriLabel; + LedState m_ledState; - const int LED_ON_MSEC = 200; + const int LED_ON_MSEC = 100; const int WAITING_FACTOR = 10; }; } // namespace scopy diff --git a/gui/src/widgets/ledbutton.cpp b/gui/src/widgets/ledbutton.cpp index c69ce5562c..e5ebbdde9f 100644 --- a/gui/src/widgets/ledbutton.cpp +++ b/gui/src/widgets/ledbutton.cpp @@ -41,25 +41,15 @@ LedButton::LedButton(QWidget *parent) setFixedSize(size); m_timer = new QTimer(this); - connect(m_timer, &QTimer::timeout, this, &LedButton::ledOff); + connect(m_timer, &QTimer::timeout, m_timer, &QTimer::stop); } LedButton::~LedButton() {} -void LedButton::ledOn(bool ledState, int runningTimeMsec) -{ - if(m_timer->isActive()) { - return; - } - setChecked(ledState); - setVisible(true); - m_timer->start(runningTimeMsec); -} +void LedButton::setLedState(bool ledState) { setChecked(ledState); } -void LedButton::ledOff() -{ - m_timer->stop(); - setVisible(false); -} +void LedButton::ledOn() { setVisible(true); } + +void LedButton::ledOff() { setVisible(false); } #include "moc_ledbutton.cpp" diff --git a/gui/src/widgets/toolmenuheaderwidget.cpp b/gui/src/widgets/toolmenuheaderwidget.cpp index ef805e8688..ea2b27d777 100644 --- a/gui/src/widgets/toolmenuheaderwidget.cpp +++ b/gui/src/widgets/toolmenuheaderwidget.cpp @@ -27,6 +27,8 @@ using namespace scopy; ToolMenuHeaderWidget::ToolMenuHeaderWidget(QString title, QWidget *parent) + : QWidget(parent) + , m_ledState(IDLE) { QHBoxLayout *hLay = new QHBoxLayout(this); hLay->setMargin(0); @@ -64,9 +66,13 @@ ToolMenuHeaderWidget::ToolMenuHeaderWidget(QString title, QWidget *parent) hLay->addWidget(titleWidget); hLay->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + m_refreshTimer = new QTimer(this); + m_refreshTimer->setInterval(LED_ON_MSEC * WAITING_FACTOR); + connect(m_refreshTimer, &QTimer::timeout, this, &ToolMenuHeaderWidget::refresh); + m_timer = new QTimer(this); - m_timer->setInterval(LED_ON_MSEC * WAITING_FACTOR); - connect(m_timer, &QTimer::timeout, m_timer, &QTimer::stop); + m_timer->setInterval(LED_ON_MSEC); + connect(m_timer, &QTimer::timeout, this, &ToolMenuHeaderWidget::onTimeout); connect(this, &ToolMenuHeaderWidget::blinkLed, this, &ToolMenuHeaderWidget::onBlinkLed); connect(this, &ToolMenuHeaderWidget::connState, this, @@ -98,20 +104,74 @@ void ToolMenuHeaderWidget::setDeviceId(QString deviceId) { m_id = deviceId; } void ToolMenuHeaderWidget::onBlinkLed(int retCode, IIOCallType type) { + bool isSuccess = (retCode >= 0); + if(m_ledState == IDLE) { + m_refreshTimer->start(); + } + if(!m_refreshTimer->isActive()) { + return; + } switch(type) { case IIOCallType::SINGLE: - m_timer->stop(); + handleSingle(isSuccess); break; case IIOCallType::STREAM: - if(m_timer->isActive()) { - return; - } - m_timer->start(); + handleStream(isSuccess); break; default: break; } - m_ledBtn->ledOn(retCode >= 0, LED_ON_MSEC); +} + +void ToolMenuHeaderWidget::handleSingle(bool isSuccess) +{ + if(m_ledState != IDLE && m_ledState != STREAM_RUNNING) { + return; + } + if(m_ledState == IDLE) { + m_ledBtn->ledOn(); + m_ledState = SINGLE_RUNNING; + } else { + m_ledBtn->ledOff(); + m_ledState = SINGLE_INTERRUPT; + } + m_ledBtn->setLedState(isSuccess); + m_timer->start(); +} + +void ToolMenuHeaderWidget::handleStream(bool isSuccess) +{ + if(m_ledState != STREAM_RUNNING && m_ledState != IDLE) { + return; + } + m_ledState = STREAM_RUNNING; + m_ledBtn->setLedState(isSuccess); + m_ledBtn->ledOn(); + m_timer->start(); +} + +void ToolMenuHeaderWidget::onTimeout() +{ + switch(m_ledState) { + case SINGLE_INTERRUPT: + m_ledBtn->ledOn(); + m_ledState = SINGLE_RUNNING; + break; + case IDLE: + m_ledBtn->ledOff(); + m_timer->stop(); + break; + default: + m_ledState = IDLE; + break; + } +} + +void ToolMenuHeaderWidget::refresh() +{ + m_refreshTimer->stop(); + m_ledBtn->ledOff(); + m_timer->start(); } QPushButton *ToolMenuHeaderWidget::deviceBtn() const { return m_deviceBtn; } From 0e2682fced69b8189fe50854649df6e7d323ed7b Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 14:41:09 +0200 Subject: [PATCH 29/41] gui/utils: Changes to SVG handling. Created a structure that contains all the information needed to be able to change an attribute in an SVG file. Added ChangeSVGAttr method. Signed-off-by: andreidanila1 --- gui/include/gui/utils.h | 11 ++++++++++- gui/src/utils.cpp | 33 +++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/gui/include/gui/utils.h b/gui/include/gui/utils.h index f5fd5fadd1..967cec37c8 100644 --- a/gui/include/gui/utils.h +++ b/gui/include/gui/utils.h @@ -42,14 +42,23 @@ class SCOPY_GUI_EXPORT Util { public: + typedef struct + { + QString tag; + QString id; + QString attrName; + QString attrVal; + } SVGSpec; + static void retainWidgetSizeWhenHidden(QWidget *w, bool retain = true); static void setWidgetNrOfChars(QWidget *w, int minNrOfChars, int maxNrOfChars = 0); static QString loadStylesheetFromFile(const QString &path); static bool compareNatural(const std::string &a, const std::string &b); static QString doubleToQString(double value); static QWidget *findContainingWindow(QWidget *w); - static void SetAttrRecur(QDomElement &elem, QString strtagname, QString strattr, QString strattrval); + static void SetAttrRecur(QDomElement &elem, SVGSpec s); static QPixmap ChangeSVGColor(QString iconPath, QString color, float opacity); + static QPixmap ChangeSVGAttr(QString iconPath, QList list); }; #define PLOT_MENU_BAR_ENABLED diff --git a/gui/src/utils.cpp b/gui/src/utils.cpp index 1aa3c63f1a..ec45afdf3c 100644 --- a/gui/src/utils.cpp +++ b/gui/src/utils.cpp @@ -168,25 +168,38 @@ void DockerUtils::configureTopBar(QDockWidget *docker) }); } -void Util::SetAttrRecur(QDomElement &elem, QString strtagname, QString strattr, QString strattrval) +void Util::SetAttrRecur(QDomElement &elem, SVGSpec s) { // if it has the tagname then overwritte desired attribute - if(elem.tagName().compare(strtagname) == 0) { - elem.setAttribute(strattr, strattrval); + if(elem.tagName().compare(s.tag) == 0) { + if(s.id.isEmpty()) { + elem.setAttribute(s.attrName, s.attrVal); + } else if(elem.attribute("id").compare(s.id) == 0) { + elem.setAttribute(s.attrName, s.attrVal); + } } + // loop all children for(int i = 0; i < elem.childNodes().count(); i++) { if(!elem.childNodes().at(i).isElement()) { continue; } QDomElement docElem = elem.childNodes().at(i).toElement(); //<-- make const "variable" - SetAttrRecur(docElem, strtagname, strattr, strattrval); + SetAttrRecur(docElem, s); } } /*QIcon*/ QPixmap Util::ChangeSVGColor(QString iconPath, QString color, float opacity) { - // open svg resource load contents to qbytearray + SVGSpec pathFill{"path", "", "fill", color}; + SVGSpec pathOpacity{"path", "", "opacity", QString::number(opacity, 'g', 2)}; + SVGSpec polygonFill{"polygon", "", "fill", color}; + QPixmap pix = ChangeSVGAttr(iconPath, {pathFill, pathOpacity, polygonFill}); + return pix; +} + +QPixmap Util::ChangeSVGAttr(QString iconPath, QList list) +{ QFile file(iconPath); if(!file.open(QIODevice::ReadOnly)) return {}; @@ -196,11 +209,9 @@ void Util::SetAttrRecur(QDomElement &elem, QString strtagname, QString strattr, doc.setContent(baData); // recurivelly change color QDomElement docElem = doc.documentElement(); //<-- make const "variable" - SetAttrRecur(docElem, "path", "fill", color); - // SetAttrRecur(docElem, "rect", "fill", color); - SetAttrRecur(docElem, "polygon", "fill", color); - SetAttrRecur(docElem, "path", "opacity", QString::number(opacity, 'g', 2)); - // create svg renderer with edited contents + for(const SVGSpec &s : list) { + SetAttrRecur(docElem, s); + } QSvgRenderer svgRenderer(doc.toByteArray()); // create pixmap target (could be a QImage) QPixmap pix(svgRenderer.defaultSize()); @@ -210,6 +221,4 @@ void Util::SetAttrRecur(QDomElement &elem, QString strtagname, QString strattr, // use renderer to render over painter which paints on pixmap svgRenderer.render(&pixPainter); return pix; - // QIcon myicon(pix); - // return myicon; } From ec50dae5102f33ea5ce87a36c4e13b1e9a4390fd Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 14:45:50 +0200 Subject: [PATCH 30/41] gui/res/icons: Added device shapes for DeviceIconBuilder. Signed-off-by: andreidanila1 --- .../icons/device-shapes/rounded_square.svg | 22 +++++++++++++++++++ gui/res/icons/device-shapes/square.svg | 7 ++++++ gui/res/resources.qrc | 2 ++ 3 files changed, 31 insertions(+) create mode 100644 gui/res/icons/device-shapes/rounded_square.svg create mode 100644 gui/res/icons/device-shapes/square.svg diff --git a/gui/res/icons/device-shapes/rounded_square.svg b/gui/res/icons/device-shapes/rounded_square.svg new file mode 100644 index 0000000000..d780d65c86 --- /dev/null +++ b/gui/res/icons/device-shapes/rounded_square.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/res/icons/device-shapes/square.svg b/gui/res/icons/device-shapes/square.svg new file mode 100644 index 0000000000..a766c381ff --- /dev/null +++ b/gui/res/icons/device-shapes/square.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/gui/res/resources.qrc b/gui/res/resources.qrc index 425a3a8358..89a0c7247f 100644 --- a/gui/res/resources.qrc +++ b/gui/res/resources.qrc @@ -170,6 +170,8 @@ Arial.ttf icons/notification_bell.svg icons/circle_led.svg + icons/device-shapes/square.svg + icons/device-shapes/rounded_square.svg icons/scopy-default/icons/search.svg From d9c0d1bc2e69395a97065b888859f169130b046c Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:03:56 +0200 Subject: [PATCH 31/41] gui: Created DeviceIconBuilder class. The class is responsible for creating device icons in a customizable way, at runtime. Signed-off-by: andreidanila1 --- gui/include/gui/deviceiconbuilder.h | 95 ++++++++++++++++++++++ gui/src/deviceiconbuilder.cpp | 119 ++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 gui/include/gui/deviceiconbuilder.h create mode 100644 gui/src/deviceiconbuilder.cpp diff --git a/gui/include/gui/deviceiconbuilder.h b/gui/include/gui/deviceiconbuilder.h new file mode 100644 index 0000000000..6cca005487 --- /dev/null +++ b/gui/include/gui/deviceiconbuilder.h @@ -0,0 +1,95 @@ +/* + * 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 DEVICEICONBUILDER_H +#define DEVICEICONBUILDER_H + +#include "hoverwidget.h" +#include "scopy-gui_export.h" +#include +#include +#include + +namespace scopy { +class SCOPY_GUI_EXPORT DeviceIconBuilder : public QObject +{ + Q_OBJECT +public: + typedef enum + { + SQUARE, + ROUNDED_SQUARE + + } IconShape; + + DeviceIconBuilder(QObject *parent = nullptr); + ~DeviceIconBuilder(); + + /** + * @brief Builds the device icon. + * @return QWidget* + */ + QWidget *build(); + + /** + * @brief Sets the IconShape. + * @param s - Related to this shape, the corresponding svg icon will be selected. + */ + DeviceIconBuilder &shape(IconShape s); + + /** + * @brief Sets the icon bgColor. + * @param bgColor - A QString with the desired color code. + */ + DeviceIconBuilder &color(QString bgColor); + + /** + * @brief Sets the header widget and the header hover widget offset. + * @param w - Header widget. + * @param offset - The offset related to the top-center position of the icon. By default is set in the middle of + * the header section. + */ + DeviceIconBuilder &headerWidget(QWidget *w, QPoint offset = {0, 24}); + + /** + * @brief Sets the footer widget and the footer hover widget offset. + * @param w - Footer widget. + * @param offset - The offset related to the bottom-center position of the icon. By default is set in the middle + * of the footer section. + */ + DeviceIconBuilder &footerWidget(QWidget *w, QPoint offset = {0, -10}); + +private: + void createHover(QWidget *icon, QWidget *w, HoverPosition anchor, HoverPosition content, QPoint offset); + void setIconShape(QLabel *icon, QString shapePath, QList specs); + + IconShape m_shape; + QString m_bgColor; + QWidget *m_headerWidget; + QPoint m_headerOffset; + QWidget *m_footerWidget; + QPoint m_footerOffset; + + const int DEVICE_BTN_HEIGHT = 80; +}; +} // namespace scopy + +#endif // DEVICEICONBUILDER_H diff --git a/gui/src/deviceiconbuilder.cpp b/gui/src/deviceiconbuilder.cpp new file mode 100644 index 0000000000..b6a0332f53 --- /dev/null +++ b/gui/src/deviceiconbuilder.cpp @@ -0,0 +1,119 @@ +/* + * 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 "deviceiconbuilder.h" + +#include +#include +#include +#include +#include + +using namespace scopy; + +DeviceIconBuilder::DeviceIconBuilder(QObject *parent) + : QObject(parent) + , m_shape(SQUARE) + , m_bgColor("") + , m_headerWidget(nullptr) + , m_footerWidget(nullptr) + , m_headerOffset({0, 0}) + , m_footerOffset({0, 0}) +{} + +DeviceIconBuilder::~DeviceIconBuilder() {} + +QWidget *DeviceIconBuilder::build() +{ + QLabel *icon = new QLabel(); + QList specs; + QString shapePath = ""; + switch(m_shape) { + case SQUARE: + specs.append({"rect", "icon-rect", "fill", m_bgColor}); + shapePath = ":/gui/icons/device-shapes/square.svg"; + break; + case ROUNDED_SQUARE: + specs.append({"use", "icon-path-color", "fill", m_bgColor}); + specs.append({"polygon", "", "fill", m_bgColor}); + shapePath = ":/gui/icons/device-shapes/rounded_square.svg"; + break; + default: + break; + } + createHover(icon, m_headerWidget, HP_TOP, HP_BOTTOM, m_headerOffset); + createHover(icon, m_footerWidget, HP_BOTTOM, HP_TOP, m_footerOffset); + setIconShape(icon, shapePath, specs); + return icon; +} + +DeviceIconBuilder &DeviceIconBuilder::shape(IconShape s) +{ + m_shape = s; + return *this; +} + +DeviceIconBuilder &DeviceIconBuilder::color(QString bgColor) +{ + m_bgColor = bgColor; + return *this; +} + +DeviceIconBuilder &DeviceIconBuilder::headerWidget(QWidget *w, QPoint offset) +{ + m_headerWidget = w; + m_headerOffset = offset; + return *this; +} + +DeviceIconBuilder &DeviceIconBuilder::footerWidget(QWidget *w, QPoint offset) +{ + m_footerWidget = w; + m_footerOffset = offset; + return *this; +} + +void DeviceIconBuilder::createHover(QWidget *icon, QWidget *w, HoverPosition anchor, HoverPosition content, + QPoint offset) +{ + if(!w) { + return; + } + HoverWidget *hover = new HoverWidget(w, icon, icon); + hover->setStyleSheet("background-color: transparent; border: 0px;"); + hover->setAnchorPos(anchor); + hover->setContentPos(content); + hover->setVisible(true); + hover->setAnchorOffset(offset); + hover->raise(); +} + +void DeviceIconBuilder::setIconShape(QLabel *icon, QString shapePath, QList specs) +{ + QPixmap pixmap(shapePath); + if(!m_bgColor.isEmpty()) { + pixmap = Util::ChangeSVGAttr(shapePath, specs); + } + pixmap = pixmap.scaledToHeight(DEVICE_BTN_HEIGHT, Qt::SmoothTransformation); + icon->setPixmap(pixmap); +} + +#include "moc_deviceiconbuilder.cpp" From 7d769e564ac18e01d76344d9d068c318ab8e96d0 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:06:33 +0200 Subject: [PATCH 32/41] style/qss/properties/label: Add qss styling for DeviceIcon-specific labels. Signed-off-by: andreidanila1 --- gui/style/qss/properties/label/deviceIcon.qss | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 gui/style/qss/properties/label/deviceIcon.qss diff --git a/gui/style/qss/properties/label/deviceIcon.qss b/gui/style/qss/properties/label/deviceIcon.qss new file mode 100644 index 0000000000..8bd6b76e2d --- /dev/null +++ b/gui/style/qss/properties/label/deviceIcon.qss @@ -0,0 +1,8 @@ +QLabel[&&property&&=true] { + color: white; + font-weight: bold; + font-size: &font_size_0_5&; +} +QLabel[&&property&&=true]:disabled { + color: grey; +} From aca776f458439e2333748666eeefe869cace4bbc Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:12:48 +0200 Subject: [PATCH 33/41] plugins/adc: Create icon using DeviceIconBuilder. Signed-off-by: andreidanila1 --- plugins/adc/src/adcplugin.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/adc/src/adcplugin.cpp b/plugins/adc/src/adcplugin.cpp index c6ae0b4ba7..7c074dc897 100644 --- a/plugins/adc/src/adcplugin.cpp +++ b/plugins/adc/src/adcplugin.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include "adctimeinstrumentcontroller.h" #include "adcfftinstrumentcontroller.h" @@ -145,8 +146,16 @@ bool ADCPlugin::loadPreferencesPage() bool ADCPlugin::loadIcon() { - SCOPY_PLUGIN_ICON(":/gui/icons/" + Style::getAttribute(json::theme::icon_theme_folder) + - "/icons/tool_oscilloscope.svg"); + QLabel *logo = new QLabel(); + QPixmap pixmap(":/gui/icons/scopy-default/icons/logo_analog.svg"); + int pixmapHeight = 14; + pixmap = pixmap.scaledToHeight(pixmapHeight, Qt::SmoothTransformation); + logo->setPixmap(pixmap); + + QLabel *footer = new QLabel("ADC"); + Style::setStyle(footer, style::properties::label::deviceIcon, true); + + m_icon = DeviceIconBuilder().shape(DeviceIconBuilder::SQUARE).headerWidget(logo).footerWidget(footer).build(); return true; } From fc7bec44c57a30cef2da480b27e375eb9d09c1f3 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:13:21 +0200 Subject: [PATCH 34/41] plugins/dac: Create icon using DeviceIconBuilder. Signed-off-by: andreidanila1 --- plugins/dac/src/dacplugin.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/dac/src/dacplugin.cpp b/plugins/dac/src/dacplugin.cpp index dc2a377fb1..a178520c46 100644 --- a/plugins/dac/src/dacplugin.cpp +++ b/plugins/dac/src/dacplugin.cpp @@ -25,6 +25,7 @@ #include "dacutils.h" #include +#include #include #include @@ -79,8 +80,16 @@ bool DACPlugin::loadPage() bool DACPlugin::loadIcon() { - SCOPY_PLUGIN_ICON(":/gui/icons/" + Style::getAttribute(json::theme::icon_theme_folder) + - "/icons/tool_oscilloscope.svg"); + QLabel *logo = new QLabel(); + QPixmap pixmap(":/gui/icons/scopy-default/icons/logo_analog.svg"); + int pixmapHeight = 14; + pixmap = pixmap.scaledToHeight(pixmapHeight, Qt::SmoothTransformation); + logo->setPixmap(pixmap); + + QLabel *footer = new QLabel("DAC"); + Style::setStyle(footer, style::properties::label::deviceIcon, true); + + m_icon = DeviceIconBuilder().shape(DeviceIconBuilder::SQUARE).headerWidget(logo).footerWidget(footer).build(); return true; } From 0d583e457355ea662d4d2e7ed4d92cd9c8788336 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:13:52 +0200 Subject: [PATCH 35/41] plugins/datalogger: Create icon using DeviceIconBuilder. Signed-off-by: andreidanila1 --- plugins/datalogger/src/dataloggerplugin.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/datalogger/src/dataloggerplugin.cpp b/plugins/datalogger/src/dataloggerplugin.cpp index 484a35ad10..8f8be8ea07 100644 --- a/plugins/datalogger/src/dataloggerplugin.cpp +++ b/plugins/datalogger/src/dataloggerplugin.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -65,8 +66,16 @@ bool DataLoggerPlugin::loadPage() { return false; } bool DataLoggerPlugin::loadIcon() { - SCOPY_PLUGIN_ICON(":/gui/icons/" + Style::getAttribute(json::theme::icon_theme_folder) + - "/icons/tool_datalogger.svg"); + QLabel *logo = new QLabel(); + QPixmap pixmap(":/gui/icons/scopy-default/icons/logo_analog.svg"); + int pixmapHeight = 14; + pixmap = pixmap.scaledToHeight(pixmapHeight, Qt::SmoothTransformation); + logo->setPixmap(pixmap); + + QLabel *footer = new QLabel("DLOG"); + Style::setStyle(footer, style::properties::label::deviceIcon, true); + + m_icon = DeviceIconBuilder().shape(DeviceIconBuilder::SQUARE).headerWidget(logo).footerWidget(footer).build(); return true; } From 72b6d02cc69c2c45d35604a4761cac49bca8a6e6 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:14:16 +0200 Subject: [PATCH 36/41] plugins/debugger: Create icon using DeviceIconBuilder. Signed-off-by: andreidanila1 --- plugins/debugger/src/debuggerplugin.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/debugger/src/debuggerplugin.cpp b/plugins/debugger/src/debuggerplugin.cpp index 02bbaba933..1e9d09eb7f 100644 --- a/plugins/debugger/src/debuggerplugin.cpp +++ b/plugins/debugger/src/debuggerplugin.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -174,7 +175,16 @@ bool DebuggerPlugin::loadPage() bool DebuggerPlugin::loadIcon() { - SCOPY_PLUGIN_ICON(":/gui/icons/adalm.svg"); + QLabel *logo = new QLabel(); + QPixmap pixmap(":/gui/icons/scopy-default/icons/logo_analog.svg"); + int pixmapHeight = 14; + pixmap = pixmap.scaledToHeight(pixmapHeight, Qt::SmoothTransformation); + logo->setPixmap(pixmap); + + QLabel *footer = new QLabel("DEBUG"); + Style::setStyle(footer, style::properties::label::deviceIcon, true); + + m_icon = DeviceIconBuilder().shape(DeviceIconBuilder::SQUARE).headerWidget(logo).footerWidget(footer).build(); return true; } From 1d16e988ac113dbd0602c546aae3d9c2a51e9c8c Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:14:39 +0200 Subject: [PATCH 37/41] plugins/pqm: Create icon using DeviceIconBuilder. Signed-off-by: andreidanila1 --- plugins/pqm/src/pqmplugin.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/pqm/src/pqmplugin.cpp b/plugins/pqm/src/pqmplugin.cpp index 918ae7e1bb..00b6d74331 100644 --- a/plugins/pqm/src/pqmplugin.cpp +++ b/plugins/pqm/src/pqmplugin.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -96,7 +97,16 @@ bool PQMPlugin::loadPage() bool PQMPlugin::loadIcon() { - SCOPY_PLUGIN_ICON(":/pqm/pqm_icon.svg"); + QLabel *logo = new QLabel(); + QPixmap pixmap(":/gui/icons/scopy-default/icons/logo_analog.svg"); + int pixmapHeight = 14; + pixmap = pixmap.scaledToHeight(pixmapHeight, Qt::SmoothTransformation); + logo->setPixmap(pixmap); + + QLabel *footer = new QLabel("PQMON"); + Style::setStyle(footer, style::properties::label::deviceIcon, true); + + m_icon = DeviceIconBuilder().shape(DeviceIconBuilder::SQUARE).headerWidget(logo).footerWidget(footer).build(); return true; } From 1470616212ba87e3fefefa382e5adc1bf6997414 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:15:01 +0200 Subject: [PATCH 38/41] plugins/regmap: Create icon using DeviceIconBuilder. Signed-off-by: andreidanila1 --- plugins/regmap/src/regmapplugin.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/regmap/src/regmapplugin.cpp b/plugins/regmap/src/regmapplugin.cpp index 40788cd1aa..819600aa19 100644 --- a/plugins/regmap/src/regmapplugin.cpp +++ b/plugins/regmap/src/regmapplugin.cpp @@ -52,6 +52,7 @@ #include #include "logging_categories.h" #include +#include #include "iioutil/connectionprovider.h" #include "jsonformatedelement.hpp" @@ -83,9 +84,16 @@ bool RegmapPlugin::loadPage() bool RegmapPlugin::loadIcon() { - m_icon = new QLabel(""); - m_icon->setStyleSheet("border-image: url(:/gui/icons/" + Style::getAttribute(json::theme::icon_theme_folder) + - "/icons/RegMap.svg);"); + QLabel *logo = new QLabel(); + QPixmap pixmap(":/gui/icons/scopy-default/icons/logo_analog.svg"); + int pixmapHeight = 14; + pixmap = pixmap.scaledToHeight(pixmapHeight, Qt::SmoothTransformation); + logo->setPixmap(pixmap); + + QLabel *footer = new QLabel("REGMAP"); + Style::setStyle(footer, style::properties::label::deviceIcon, true); + + m_icon = DeviceIconBuilder().shape(DeviceIconBuilder::SQUARE).headerWidget(logo).footerWidget(footer).build(); return true; } From 4e6ea1acbe81c142d90a26cac5ea651c124d8847 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:15:16 +0200 Subject: [PATCH 39/41] plugins/swiot: Create icon using DeviceIconBuilder. Signed-off-by: andreidanila1 --- plugins/swiot/src/swiotplugin.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/swiot/src/swiotplugin.cpp b/plugins/swiot/src/swiotplugin.cpp index 15525d2811..ac26ab5ecb 100644 --- a/plugins/swiot/src/swiotplugin.cpp +++ b/plugins/swiot/src/swiotplugin.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "swiot_logging_categories.h" @@ -129,8 +130,16 @@ bool SWIOTPlugin::loadExtraButtons() bool SWIOTPlugin::loadIcon() { - m_icon = new QLabel(""); - m_icon->setStyleSheet("border-image: url(:/swiot/swiot_icon.svg);"); + QLabel *logo = new QLabel(); + QPixmap pixmap(":/gui/icons/scopy-default/icons/logo_analog.svg"); + int pixmapHeight = 14; + pixmap = pixmap.scaledToHeight(pixmapHeight, Qt::SmoothTransformation); + logo->setPixmap(pixmap); + + QLabel *footer = new QLabel("SWIOT1L"); + Style::setStyle(footer, style::properties::label::deviceIcon, true); + + m_icon = DeviceIconBuilder().shape(DeviceIconBuilder::SQUARE).headerWidget(logo).footerWidget(footer).build(); return true; } From 27340221544eb9ffed9b1442f99fe87b5c1b6eee Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:16:03 +0200 Subject: [PATCH 40/41] core/deviceimpl: Create NO_PLUGIN icon using DeviceIconBuilder. Signed-off-by: andreidanila1 --- core/src/deviceimpl.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/core/src/deviceimpl.cpp b/core/src/deviceimpl.cpp index 356e098934..91ae688654 100644 --- a/core/src/deviceimpl.cpp +++ b/core/src/deviceimpl.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ Q_LOGGING_CATEGORY(CAT_DEVICEIMPL, "Device") namespace scopy { + DeviceImpl::DeviceImpl(QString param, PluginManager *p, QString category, QObject *parent) : QObject{parent} , m_param(param) @@ -157,17 +159,22 @@ void DeviceImpl::loadName() void DeviceImpl::loadIcons() { m_icon = new QWidget(); + QHBoxLayout *lay = new QHBoxLayout(m_icon); m_icon->setFixedHeight(100); m_icon->setFixedWidth(100); - new QHBoxLayout(m_icon); for(auto &p : m_plugins) { if(p->loadIcon()) { - m_icon->layout()->addWidget(p->icon()); + lay->addWidget(p->icon()); return; } } - new QLabel("No PLUGIN", m_icon); + QLabel *header = new QLabel("No Plugin"); + Style::setStyle(header, style::properties::label::deviceIcon, true); + + QWidget *noPluginIcon = + DeviceIconBuilder().shape(DeviceIconBuilder::SQUARE).color("gray").headerWidget(header).build(); + lay->addWidget(noPluginIcon); } void DeviceImpl::loadPages() From 22617de0ea9db49de2e2e35c0af277607eaebf29 Mon Sep 17 00:00:00 2001 From: andreidanila1 Date: Fri, 13 Dec 2024 15:17:36 +0200 Subject: [PATCH 41/41] core/devicebrowser: Added horizontal scroll bar. Signed-off-by: andreidanila1 --- core/include/core/devicebrowser.h | 2 + core/src/devicebrowser.cpp | 32 +- core/ui/devicebrowser.ui | 466 +++++++++++++++++------------- 3 files changed, 298 insertions(+), 202 deletions(-) diff --git a/core/include/core/devicebrowser.h b/core/include/core/devicebrowser.h index beac1ecc46..5a943bd615 100644 --- a/core/include/core/devicebrowser.h +++ b/core/include/core/devicebrowser.h @@ -64,6 +64,8 @@ private Q_SLOTS: void updateSelectedDeviceIdx(QString); void forwardRequestDeviceWithDirection(); + void onScrollRangeChanged(int min, int max); + private: void initBtns(); DeviceIcon *buildDeviceIcon(Device *d, QWidget *parent = nullptr); diff --git a/core/src/devicebrowser.cpp b/core/src/devicebrowser.cpp index 5ae442c989..55a8791d17 100644 --- a/core/src/devicebrowser.cpp +++ b/core/src/devicebrowser.cpp @@ -31,6 +31,7 @@ #include #include +#include #include Q_LOGGING_CATEGORY(CAT_DEVBROWSER, "DeviceBrowser") @@ -45,13 +46,19 @@ DeviceBrowser::DeviceBrowser(QWidget *parent) this->setFixedHeight(185); auto dbm = ui->wDeviceBrowserMenu; - layout = new QHBoxLayout(dbm); + layout = dynamic_cast(dbm->layout()); + + auto scrollArea = ui->scrollArea; + scrollArea->horizontalScrollBar()->setVisible(false); initBtns(); connect(ui->btnHome, SIGNAL(clicked()), this, SLOT(forwardRequestDeviceWithDirection())); connect(ui->btnAdd, SIGNAL(clicked()), this, SLOT(forwardRequestDeviceWithDirection())); connect(this, SIGNAL(requestDevice(QString, int)), this, SLOT(updateSelectedDeviceIdx(QString))); + + connect(scrollArea->horizontalScrollBar(), &QScrollBar::rangeChanged, this, + &DeviceBrowser::onScrollRangeChanged); } DeviceBrowser::~DeviceBrowser() @@ -96,13 +103,16 @@ void DeviceBrowser::addDevice(QString id, Device *d, int position) { qInfo(CAT_DEVBROWSER) << "adding device " << id; auto w = dynamic_cast(buildDeviceIcon(d, this)); + int spacerIndex = layout->indexOf(ui->hSpacer); w->setProperty(devBrowserId, id); - layout->insertWidget(position, w); bg->addButton(w); - if(position == -1) + if(position == -1) { + layout->insertWidget(spacerIndex, w); list.append(w); - else + } else { + layout->insertWidget(position, w); list.insert(position, w); + } connect(w, &QAbstractButton::clicked, this, &DeviceBrowser::forwardRequestDeviceWithDirection); } @@ -230,6 +240,20 @@ DeviceIcon *DeviceBrowser::buildDeviceIcon(Device *d, QWidget *parent) return devIcon; } +// Used to display the scrollbar when needed and to maintain its size in the scroll area when not needed. +// We chose this approach because for the Qt::ScrollBarAsNeeded policy the size of the scrollball cannot be retained +// with Util::retainWidgetSizeWhenHidden because the resizing of the scrollbar is done dynamically (withoud using the +// show/hide default functions). +void DeviceBrowser::onScrollRangeChanged(int min, int max) +{ + auto scrollArea = ui->scrollArea; + if(max > min) { + scrollArea->horizontalScrollBar()->setVisible(true); + } else { + scrollArea->horizontalScrollBar()->setVisible(false); + } +} + /* auto &&is = ui->wInfoPageStack; auto &&hc = is->getHomepageControls(); diff --git a/core/ui/devicebrowser.ui b/core/ui/devicebrowser.ui index d4de72d3dc..fa61640efb 100644 --- a/core/ui/devicebrowser.ui +++ b/core/ui/devicebrowser.ui @@ -7,11 +7,11 @@ 0 0 464 - 108 + 140 - + 0 0 @@ -42,218 +42,288 @@ 0 - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 9 + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Orientation::Vertical - - 9 + + + 0 + 0 + - - - - - 0 - 0 - - - - - 40 - 40 - - - - - 40 - 40 - - - - - - - - :/gui/icons/home.svg - - - - - 40 - 40 - - - - true - - - false - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 9 + + + + + + + 0 + 0 + - - 9 + + + 0 + 0 + - - - - - 0 - 0 - - - - - 40 - 40 - - - - - 40 - 40 - - - - - - - - :/gui/icons/add.svg - - - - - 40 - 40 - - - - true - - - - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + 40 + 40 + + + + + 40 + 40 + + + + + + + + :/gui/icons/home.svg + + + + + 40 + 40 + + + + true + + + false + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + 40 + 40 + + + + + 40 + 40 + + + + + + + + :/gui/icons/add.svg + + + + + 40 + 40 + + + + true + + + + + + + + + + Qt::Orientation::Vertical + + + + 0 + 0 + + + + + + - + - + 0 0 - - - - - - Qt::Orientation::Horizontal + + Qt::ScrollBarPolicy::ScrollBarAlwaysOff + + + Qt::ScrollBarPolicy::ScrollBarAlwaysOn + + + QAbstractScrollArea::SizeAdjustPolicy::AdjustToContents - - - 40 - 20 - + + true - + + + + 0 + 0 + 392 + 124 + + + + + 0 + 0 + + + + + 0 + + + + + Qt::Orientation::Horizontal + + + + 0 + 0 + + + + + + + - - - 0 + + + + 0 + 0 + - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Orientation::Vertical + + + + 0 + 40 + + + + + +