Compound device edit dialog

This commit is contained in:
Jan Käberich 2022-08-05 18:29:31 +02:00
parent 90ac9c57e1
commit 74e6a439af
27 changed files with 4439 additions and 8 deletions

View file

@ -0,0 +1,77 @@
#include "compounddevice.h"
CompoundDevice::CompoundDevice()
{
name = "";
sync = Synchronization::USB;
}
nlohmann::json CompoundDevice::toJSON()
{
nlohmann::json j;
j["name"] = name.toStdString();
j["synchronization"] = SyncToString(sync).toStdString();
nlohmann::json jserials;
for(auto d : deviceSerials) {
jserials.push_back(d.toStdString());
}
j["devices"] = jserials;
nlohmann::json jmappings;
for(auto m : portMapping) {
nlohmann::json jmapping;
jmapping["device"] = m.device;
jmapping["port"] = m.port;
jmappings.push_back(jmapping);
}
j["mapping"] = jmappings;
return j;
}
void CompoundDevice::fromJSON(nlohmann::json j)
{
name = QString::fromStdString(j.value("name", "CompoundDevice"));
sync = SyncFromString(QString::fromStdString(j.value("synchronization", "USB")));
deviceSerials.clear();
if(j.contains("devices")) {
for(auto js : j["devices"]) {
deviceSerials.push_back(QString::fromStdString(js));
}
}
portMapping.clear();
if(j.contains("mapping")) {
for(auto jm : j["mapping"]) {
PortMapping mapping;
mapping.device = jm.value("device", 0);
mapping.port = jm.value("port", 0);
portMapping.push_back(mapping);
}
}
}
QString CompoundDevice::SyncToString(CompoundDevice::Synchronization sync)
{
switch(sync) {
case Synchronization::USB: return "USB";
case Synchronization::ExtRef: return "Ext. Ref.";
case Synchronization::Trigger: return "Trigger";
default:
case Synchronization::Last: return "Invalid";
}
}
CompoundDevice::Synchronization CompoundDevice::SyncFromString(QString s)
{
for(int i=0;i<(int) Synchronization::Last;i++) {
if(SyncToString((Synchronization)i) == s) {
return (Synchronization) i;
}
}
// default to USB
return Synchronization::USB;
}
QString CompoundDevice::getDesription()
{
return name + ", "+QString::number(deviceSerials.size())+" devices, "+QString::number(portMapping.size())+" ports in total";
}

View file

@ -0,0 +1,43 @@
#ifndef COMPOUNDDEVICE_H
#define COMPOUNDDEVICE_H
#include "savable.h"
#include <vector>
#include <QString>
class CompoundDevice : public Savable
{
friend class CompoundDeviceEditDialog;
public:
CompoundDevice();
virtual nlohmann::json toJSON();
virtual void fromJSON(nlohmann::json j);
class PortMapping {
public:
unsigned int device;
unsigned int port;
};
enum class Synchronization {
USB,
ExtRef,
Trigger,
Last
};
static QString SyncToString(Synchronization sync);
static Synchronization SyncFromString(QString s);
QString getDesription();
QString name;
Synchronization sync;
std::vector<QString> deviceSerials;
std::vector<PortMapping> portMapping;
};
#endif // COMPOUNDDEVICE_H

View file

@ -0,0 +1,548 @@
#include "compounddeviceeditdialog.h"
#include "ui_compounddeviceeditdialog.h"
#include "device.h"
#include <QPushButton>
#include <QDrag>
#include <QMimeData>
#include <QMouseEvent>
#include <QStandardItemModel>
using namespace std;
CompoundDeviceEditDialog::CompoundDeviceEditDialog(CompoundDevice *cdev, QWidget *parent) :
QDialog(parent),
ui(new Ui::CompoundDeviceEditDialog)
{
ldev = *cdev;
ui->setupUi(this);
connect(ui->name, &QLineEdit::editingFinished, [=](){
ldev.name = ui->name->text();
checkIfOkay();
});
for(int i=0;i<(int)CompoundDevice::Synchronization::Last;i++) {
ui->sync->addItem(CompoundDevice::SyncToString((CompoundDevice::Synchronization) i));
if((CompoundDevice::Synchronization) i == CompoundDevice::Synchronization::Trigger) {
// Disable for now
auto *model = qobject_cast<QStandardItemModel *>(ui->sync->model());
Q_ASSERT(model != nullptr);
bool disabled = true;
auto *item = model->item(i);
item->setFlags(disabled ? item->flags() & ~Qt::ItemIsEnabled
: item->flags() | Qt::ItemIsEnabled);
}
}
connect(ui->sync, &QComboBox::currentTextChanged, [=](){
ldev.sync = CompoundDevice::SyncFromString(ui->sync->currentText());
updateDeviceFrames();
});
connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, [=](){
*cdev = ldev;
accept();
});
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &QDialog::reject);
connect(ui->buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, [=](){
ldev.saveToFileDialog("Save compound device", "Compound device file (*.cdev)", ".cdev");
});
connect(ui->buttonBox->button(QDialogButtonBox::Open), &QPushButton::clicked, [=](){
if(ldev.openFromFileDialog("Load compound device", "Compound device file (*.cdev)")) {
setInitialGUI();
}
});
ui->status->setStyleSheet("QLabel { color : red; }");
graph = new QWidget();
ui->scrollArea->setWidget(graph);
auto layout = new QHBoxLayout();
graph->setLayout(layout);
graph->setAcceptDrops(true);
graph->setObjectName("Graph");
graph->installEventFilter(this);
ui->lLibreVNA1->installEventFilter(this);
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(0);
setInitialGUI();
}
CompoundDeviceEditDialog::~CompoundDeviceEditDialog()
{
delete ui;
}
void CompoundDeviceEditDialog::checkIfOkay()
{
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
if(deviceFrames.size() != ldev.deviceSerials.size()) {
// probably still populating the GUI, skip check
return;
}
if(ldev.name.isEmpty()) {
ui->status->setText("Name must not be empty");
return;
}
if(ldev.deviceSerials.size() < 2) {
ui->status->setText("At least two devices are required");
return;
}
if(ldev.deviceSerials.size() > 4) {
ui->status->setText("Only up to four devices supported");
return;
}
// Check serials
for(int i=0;i<ldev.deviceSerials.size();i++) {
ldev.deviceSerials[i] = deviceFrames[i]->getSerial();
if(ldev.deviceSerials[i].isEmpty()) {
ui->status->setText("Device "+QString::number(i+1)+" has no serial number");
return;
}
}
// Check serials for duplicates
for(int i=0;i<ldev.deviceSerials.size();i++) {
for(int j=i+1;j<ldev.deviceSerials.size();j++) {
if(ldev.deviceSerials[i] == ldev.deviceSerials[j]) {
ui->status->setText("Duplicate serial number ("+ldev.deviceSerials[i]+") in devices "+QString::number(i+1)+" and "+QString::number(j+1));
return;
}
}
}
// Check port mapping
// Looking for duplicate and missing ports
bool highestPortFound = false;
int highestPort;
for(int port=0;port<2*ldev.deviceSerials.size();port++) {
int num = 0;
for(int i=0;i<deviceFrames.size();i++) {
if(deviceFrames[i]->getPort1() == port) {
num++;
}
if(deviceFrames[i]->getPort2() == port) {
num++;
}
}
if(num > 1) {
ui->status->setText("Duplicate port "+QString::number(port+1));
return;
} else if(num == 0) {
if(port == 0) {
ui->status->setText("Port 1 must be present");
return;
}
if(!highestPortFound) {
highestPort = port;
}
highestPortFound = true;
} else if(highestPortFound) {
// port is present, but earlier port was missing
ui->status->setText("Missing port: "+QString::number(port+1)+" is selected, but port "+QString::number(port)+" is not present.");
return;
}
}
if(!highestPortFound) {
highestPort = 2*ldev.deviceSerials.size();
}
// All good, actually create the port mapping
ldev.portMapping.clear();
for(int port=0;port<highestPort;port++) {
CompoundDevice::PortMapping map;
bool found = false;
for(int i=0;i<deviceFrames.size();i++) {
if(deviceFrames[i]->getPort1() == port) {
found = true;
map.device = i;
map.port = 0;
break;
}
if(deviceFrames[i]->getPort2() == port) {
found = true;
map.device = i;
map.port = 1;
break;
}
}
if(!found) {
ui->status->setText("Failed to find port "+QString::number(port+1)+" (likely a bug)");
return;
}
ldev.portMapping.push_back(map);
}
ui->status->clear();
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(true);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
}
void CompoundDeviceEditDialog::setInitialGUI()
{
ui->name->setText(ldev.name);
ui->sync->setCurrentText(CompoundDevice::SyncToString(ldev.sync));
// Removing the old frames actually modifies the state of ldev as well. Block signals to prevent this from happening
for(auto f : deviceFrames) {
f->blockSignals(true);
}
QHBoxLayout* layout = (QHBoxLayout*) graph->layout();
// remove all widgets from the layout
if (layout != NULL ) {
QLayoutItem* item;
while ((item = layout->takeAt(0)) != NULL ) {
delete item->widget();
delete item;
}
}
deviceFrames.clear();
layout->addStretch(1);
for(int i=0;i<ldev.deviceSerials.size();i++) {
auto frame = new DeviceFrame(&ldev, i);
connect(frame, &DeviceFrame::settingChanged, this, &CompoundDeviceEditDialog::checkIfOkay);
addFrame(i, frame);
}
layout->addStretch(1);
checkIfOkay();
}
DeviceFrame *CompoundDeviceEditDialog::frameAtPosition(int pos)
{
pos -= graph->layout()->itemAt(0)->geometry().width();
if(pos > 0 && pos <= (int) deviceFrames.size() * frameSize) {
return deviceFrames[pos / frameSize];
}
return nullptr;
}
unsigned int CompoundDeviceEditDialog::findInsertPosition(int xcoord)
{
xcoord -= graph->layout()->itemAt(0)->geometry().width();
// added in port 1 network
int index = (xcoord + frameSize / 2) / frameSize;
if(index < 0) {
index = 0;
} else if(index > (int) deviceFrames.size()) {
index = deviceFrames.size();
}
// add 1 (first widget is always the stretch)
return index + 1;
}
void CompoundDeviceEditDialog::addFrameAtPosition(int pos, DeviceFrame *c)
{
auto index = findInsertPosition(pos);
// add component to the deviceFrame vector
index -= 1; // first widget is fixed
if(index <= deviceFrames.size()) {
addFrame(index, c);
}
}
void CompoundDeviceEditDialog::addFrame(int index, DeviceFrame *c)
{
if(deviceFrames.size() == ldev.deviceSerials.size()) {
ldev.deviceSerials.insert(ldev.deviceSerials.begin() + index, "");
}
deviceFrames.insert(deviceFrames.begin() + index, c);
deviceFrames[index]->setPosition(index);
// remove from list when the component deletes itself
connect(c, &DeviceFrame::deleted, [=](){
removeDeviceFrame(c);
});
QHBoxLayout *l = static_cast<QHBoxLayout*>(graph->layout());
l->insertWidget(index + 1, c);
c->show();
updateDeviceFrames();
}
void CompoundDeviceEditDialog::createDragFrame(DeviceFrame *c)
{
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
QByteArray encodedPointer;
QDataStream stream(&encodedPointer, QIODevice::WriteOnly);
stream << quintptr(c);
mimeData->setData("compoundDeviceFrame/pointer", encodedPointer);
drag->setMimeData(mimeData);
drag->exec(Qt::MoveAction);
}
void CompoundDeviceEditDialog::updateInsertIndicator(int xcoord)
{
auto index = findInsertPosition(xcoord);
QHBoxLayout *l = static_cast<QHBoxLayout*>(graph->layout());
l->removeWidget(insertIndicator);
l->insertWidget(index, insertIndicator);
}
bool CompoundDeviceEditDialog::eventFilter(QObject *object, QEvent *event)
{
if(object->objectName() == "Graph") {
if(event->type() == QEvent::MouseButtonPress) {
auto mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton) {
dragFrame = frameAtPosition(mouseEvent->pos().x());
if(dragFrame) {
dragStartPosition = mouseEvent->pos();
return true;
}
}
return false;
} else if(event->type() == QEvent::MouseMove) {
auto mouseEvent = static_cast<QMouseEvent*>(event);
if (!(mouseEvent->buttons() & Qt::LeftButton)) {
return false;
}
if (!dragFrame) {
return false;
}
if ((mouseEvent->pos() - dragStartPosition).manhattanLength()
< QApplication::startDragDistance()) {
return false;
}
// remove and hide component while it is being dragged
graph->layout()->removeWidget(dragFrame);
dragFrame->hide();
removeDeviceFrame(dragFrame);
graph->update();
createDragFrame(dragFrame);
return true;
} else if(event->type() == QEvent::DragEnter) {
auto dragEvent = static_cast<QDragEnterEvent*>(event);
if(dragEvent->mimeData()->hasFormat("compoundDeviceFrame/pointer")) {
dropPending = true;
auto data = dragEvent->mimeData()->data("compoundDeviceFrame/pointer");
QDataStream stream(&data, QIODevice::ReadOnly);
quintptr dropPtr;
stream >> dropPtr;
dropFrame = (DeviceFrame*) dropPtr;
dragEvent->acceptProposedAction();
insertIndicator = new QWidget();
insertIndicator->setMinimumSize(2, frameSize);
insertIndicator->setMaximumSize(2, frameSize);
insertIndicator->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
insertIndicator->setStyleSheet("background-color:red;");
updateInsertIndicator(dragEvent->pos().x());
return true;
}
} else if(event->type() == QEvent::DragMove) {
auto dragEvent = static_cast<QDragMoveEvent*>(event);
updateInsertIndicator(dragEvent->pos().x());
return true;
} else if(event->type() == QEvent::Drop) {
auto dragEvent = static_cast<QDropEvent*>(event);
delete insertIndicator;
addFrameAtPosition(dragEvent->pos().x(), dropFrame);
return true;
} else if(event->type() == QEvent::DragLeave) {
dropPending = false;
dropFrame = nullptr;
delete insertIndicator;
}
} else {
// clicked/dragged one of the components outside of the graph
if(event->type() == QEvent::MouseButtonPress) {
auto mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton) {
dragStartPosition = mouseEvent->pos();
if(object->objectName() == "lLibreVNA1") {
dragFrame = new DeviceFrame(&ldev, 0);
connect(dragFrame, &DeviceFrame::settingChanged, this, &CompoundDeviceEditDialog::checkIfOkay);
} else {
dragFrame = nullptr;
}
return true;
}
return false;
} else if(event->type() == QEvent::MouseMove) {
auto mouseEvent = static_cast<QMouseEvent*>(event);
if (!(mouseEvent->buttons() & Qt::LeftButton)) {
return false;
}
if (!dragFrame) {
return false;
}
if ((mouseEvent->pos() - dragStartPosition).manhattanLength()
< QApplication::startDragDistance()) {
return false;
}
createDragFrame(dragFrame);
return true;
}
}
return false;
}
void CompoundDeviceEditDialog::removeDeviceFrame(DeviceFrame *dev)
{
auto it = std::find(deviceFrames.begin(), deviceFrames.end(), dev);
if(it == deviceFrames.end()) {
// not found, shouldn't happen
return;
}
auto pos = it - deviceFrames.begin();
deviceFrames.erase(it);
ldev.deviceSerials.erase(ldev.deviceSerials.begin() + pos);
// remove all port mappings from the removed device
bool mappingFound;
do {
mappingFound = false;
for(int i=0;i<ldev.portMapping.size();i++) {
if(ldev.portMapping[i].device == pos) {
mappingFound = true;
ldev.portMapping.erase(ldev.portMapping.begin() + i);
break;
}
}
} while(mappingFound);
updateDeviceFrames();
}
void CompoundDeviceEditDialog::updateDeviceFrames()
{
int i=0;
for(auto df : deviceFrames) {
df->setPosition(i++);
}
}
DeviceFrame::DeviceFrame(CompoundDevice *dev, int position) :
dev(dev),
position(position)
{
setMinimumSize(frameSize, frameSize);
setMaximumSize(frameSize, frameSize);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setFocusPolicy(Qt::FocusPolicy::ClickFocus);
serial = new QComboBox();
serial->setEditable(true);
port1 = new QComboBox();
port2 = new QComboBox();
connect(serial, &QComboBox::currentTextChanged, this, &DeviceFrame::settingChanged);
connect(port1, &QComboBox::currentTextChanged, this, &DeviceFrame::settingChanged);
connect(port2, &QComboBox::currentTextChanged, this, &DeviceFrame::settingChanged);
auto layout = new QVBoxLayout;
layout->addStretch(1);
auto l1 = new QHBoxLayout;
l1->addStretch(1);
l1->addWidget(serial);
l1->addStretch(1);
layout->addLayout(l1);
layout->addStretch(1);
auto l2 = new QHBoxLayout;
l2->addWidget(port1);
l2->addStretch(1);
l2->addWidget(port2);
layout->addLayout(l2);
setLayout(layout);
update();
// Set initial state
if(position < dev->deviceSerials.size()) {
serial->setCurrentText(dev->deviceSerials[position]);
for(int i=0;i<dev->portMapping.size();i++) {
if(dev->portMapping[i].device == position) {
if(dev->portMapping[i].port == 0) {
port1->setCurrentIndex(i + 1);
} else if(dev->portMapping[i].port == 1) {
port2->setCurrentIndex(i + 1);
}
}
}
}
}
DeviceFrame::~DeviceFrame()
{
emit deleted();
}
void DeviceFrame::setPosition(int pos)
{
position = pos;
update();
}
void DeviceFrame::update()
{
auto p1 = port1->currentText();
auto p2 = port2->currentText();
auto s = serial->currentText();
port1->clear();
port2->clear();
serial->clear();
port1->addItem("Unused");
port2->addItem("Unused");
for(int i=0;i<dev->deviceSerials.size();i++) {
port1->addItem("Port "+QString::number(i*2+1));
port2->addItem("Port "+QString::number(i*2+1));
port1->addItem("Port "+QString::number(i*2+2));
port2->addItem("Port "+QString::number(i*2+2));
}
if(port1->findText(p1) >= 0) {
port1->setCurrentText(p1);
} else {
port1->setCurrentIndex(0);
}
if(port2->findText(p2) >= 0) {
port2->setCurrentText(p2);
} else {
port2->setCurrentIndex(0);
}
auto devices = Device::GetDevices();
for(auto d : devices) {
serial->addItem(d);
}
// if(!serial->findText(s) >= 0) {
// serial->addItem(s);
// }
serial->setCurrentText(s);
if(dev->sync == CompoundDevice::Synchronization::USB) {
setStyleSheet("image: url(:/icons/compound_V1_USB.png);");
} else if(dev->sync == CompoundDevice::Synchronization::ExtRef) {
if(position == 0) {
setStyleSheet("image: url(:/icons/compound_V1_Ref_Left.png);");
} else if(position == dev->deviceSerials.size() - 1) {
setStyleSheet("image: url(:/icons/compound_V1_Ref_Right.png);");
} else {
setStyleSheet("image: url(:/icons/compound_V1_Ref_Middle.png);");
}
}
}
QString DeviceFrame::getSerial()
{
return serial->currentText();
}
int DeviceFrame::getPort1()
{
return port1->currentIndex() - 1;
}
int DeviceFrame::getPort2()
{
return port2->currentIndex() - 1;
}

View file

@ -0,0 +1,74 @@
#ifndef COMPOUNDDEVICEEDITDIALOG_H
#define COMPOUNDDEVICEEDITDIALOG_H
#include "compounddevice.h"
#include <QDialog>
#include <QLabel>
#include <QComboBox>
namespace Ui {
class CompoundDeviceEditDialog;
}
class DeviceFrame : public QFrame {
Q_OBJECT
public:
DeviceFrame(CompoundDevice *dev, int position);
~DeviceFrame();
void setPosition(int pos);
void update();
QString getSerial();
int getPort1();
int getPort2();
signals:
void deleted();
void settingChanged();
private:
static constexpr int frameSize = 350;
QComboBox *serial;
QComboBox *port1, *port2;
QLabel *image;
int position;
CompoundDevice *dev;
};
class CompoundDeviceEditDialog : public QDialog
{
Q_OBJECT
public:
explicit CompoundDeviceEditDialog(CompoundDevice *cdev, QWidget *parent = nullptr);
~CompoundDeviceEditDialog();
private slots:
void checkIfOkay();
private:
static constexpr int frameSize = 350;
void setInitialGUI();
DeviceFrame *frameAtPosition(int pos);
unsigned int findInsertPosition(int xcoord);
void addFrameAtPosition(int pos, DeviceFrame *c);
void addFrame(int index, DeviceFrame *c);
void createDragFrame(DeviceFrame *c);
void updateInsertIndicator(int xcoord);
bool eventFilter(QObject *object, QEvent *event) override;
void removeDeviceFrame(DeviceFrame *dev);
void updateDeviceFrames();
Ui::CompoundDeviceEditDialog *ui;
CompoundDevice ldev;
QWidget *graph, *insertIndicator;
QPoint dragStartPosition;
bool dropPending;
DeviceFrame *dragFrame;
DeviceFrame *dropFrame;
std::vector<DeviceFrame*> deviceFrames;
};
#endif // COMPOUNDDEVICEEDITDIALOG_H

View file

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CompoundDeviceEditDialog</class>
<widget class="QDialog" name="CompoundDeviceEditDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1097</width>
<height>598</height>
</rect>
</property>
<property name="windowTitle">
<string>Compound Device Edit</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="name"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Synchronization:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="sync"/>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Standalone Devices</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>Drag/drop into compound device</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>80</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="lLibreVNA1">
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">border-image: url(:/icons/LibreVNAV1.svg);</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="text">
<string>LibreVNA V1</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1077</width>
<height>372</height>
</rect>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="status">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Open|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -136,6 +136,7 @@ VirtualDevice::VirtualDevice(QString serial)
info{},
status{}
{
cdev = nullptr;
isCompound = false;
zerospan = false;
auto dev = new Device(serial);
@ -243,6 +244,11 @@ Device *VirtualDevice::getDevice()
}
}
CompoundDevice *VirtualDevice::getCompoundDevice()
{
return cdev;
}
std::vector<Device *> VirtualDevice::getDevices()
{
return devices;

View file

@ -3,6 +3,7 @@
#include "device.h"
#include "Tools/parameters.h"
#include "compounddevice.h"
#include <set>
#include <complex>
@ -52,6 +53,7 @@ public:
bool isCompoundDevice() const;
Device *getDevice();
CompoundDevice *getCompoundDevice();
std::vector<Device*> getDevices();
const Info& getInfo() const;
static const VirtualDevice::Info &getInfo(VirtualDevice *vdev);
@ -179,6 +181,8 @@ private:
bool zerospan;
std::map<Device*, Device::TransmissionResult> results;
CompoundDevice *cdev;
};
Q_DECLARE_METATYPE(VirtualDevice::Status)