mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-06 23:13:43 +00:00
Merge branch 'master' into prototype_testing
This commit is contained in:
commit
f76e3a209d
189 changed files with 979384 additions and 264 deletions
|
|
@ -237,7 +237,7 @@ void LibreCALDialog::updateCalibrationStartStatus()
|
|||
ui->start->setEnabled(canStart);
|
||||
if(canStart) {
|
||||
ui->lCalibrationStatus->setText("Ready to start");
|
||||
ui->lCalibrationStatus->setStyleSheet("QLabel { color : black; }");
|
||||
ui->lCalibrationStatus->setStyleSheet("");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +254,7 @@ void LibreCALDialog::updateDeviceStatus()
|
|||
}
|
||||
if(device->stabilized()) {
|
||||
ui->lDeviceStatus->setText("LibreCAL ready for calibration");
|
||||
ui->lDeviceStatus->setStyleSheet("QLabel { color : black; }");
|
||||
ui->lDeviceStatus->setStyleSheet("");
|
||||
} else {
|
||||
ui->lDeviceStatus->setText("Heating up, please wait with calibration");
|
||||
ui->lDeviceStatus->setStyleSheet("QLabel { color : orange; }");
|
||||
|
|
@ -263,6 +263,7 @@ void LibreCALDialog::updateDeviceStatus()
|
|||
|
||||
void LibreCALDialog::determineAutoPorts()
|
||||
{
|
||||
disableUI();
|
||||
ui->progressCal->setValue(0);
|
||||
ui->lCalibrationStatus->setText("Autodetecting port connections...");
|
||||
ui->lCalibrationStatus->setStyleSheet("QLabel { color : green; }");
|
||||
|
|
@ -422,7 +423,7 @@ void LibreCALDialog::startCalibration()
|
|||
|
||||
ui->progressCal->setValue(0);
|
||||
ui->lCalibrationStatus->setText("Creating calibration kit from coefficients...");
|
||||
ui->lCalibrationStatus->setStyleSheet("QLabel { color : black; }");
|
||||
ui->lCalibrationStatus->setStyleSheet("");
|
||||
auto& kit = cal->getKit();
|
||||
kit.clearStandards();
|
||||
kit.manufacturer = "LibreCAL ("+coeffSet.name+")";
|
||||
|
|
@ -606,7 +607,9 @@ void LibreCALDialog::startCalibration()
|
|||
disconnect(cal, &Calibration::measurementsUpdated, this, nullptr);
|
||||
connect(cal, &Calibration::measurementsUpdated, this, startNextCalibrationStep, Qt::QueuedConnection);
|
||||
connect(cal, &Calibration::measurementsAborted, this, [=](){
|
||||
setTerminationOnAllUsedPorts(CalDevice::Standard(CalDevice::Standard::Type::None));
|
||||
enableUI();
|
||||
ui->lCalibrationStatus->setText("Ready to start");
|
||||
});
|
||||
|
||||
startNextCalibrationStep();
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public:
|
|||
double getLowerFreq() const;
|
||||
double getUpperFreq() const;
|
||||
double getReferenceImpedance() const;
|
||||
TraceModel* getModel() const {return model;}
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
CompoundDriver::CompoundDriver()
|
||||
{
|
||||
connected = false;
|
||||
isIdle = true;
|
||||
triggerForwarding = false;
|
||||
SApoints = 0;
|
||||
|
||||
drivers.push_back(new LibreVNAUSBDriver);
|
||||
drivers.push_back(new LibreVNATCPDriver);
|
||||
|
|
@ -295,6 +298,11 @@ bool CompoundDriver::setVNA(const DeviceDriver::VNASettings &s, std::function<vo
|
|||
return setIdle(cb);
|
||||
}
|
||||
|
||||
setIdle([this](bool){
|
||||
enableTriggerForwarding();
|
||||
qDebug() << "Start trigger forwarding";
|
||||
});
|
||||
|
||||
// create port->stage mapping
|
||||
portStageMapping.clear();
|
||||
for(unsigned int i=0;i<s.excitedPorts.size();i++) {
|
||||
|
|
@ -333,6 +341,11 @@ bool CompoundDriver::setVNA(const DeviceDriver::VNASettings &s, std::function<vo
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
lastNonIdleSettings.type = Types::VNA;
|
||||
lastNonIdleSettings.vna = s;
|
||||
isIdle = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -352,6 +365,11 @@ bool CompoundDriver::setSA(const DeviceDriver::SASettings &s, std::function<void
|
|||
}
|
||||
zerospan = s.freqStart == s.freqStop;
|
||||
|
||||
setIdle([this](bool){
|
||||
enableTriggerForwarding();
|
||||
qDebug() << "Start trigger forwarding";
|
||||
});
|
||||
|
||||
// Configure the devices
|
||||
results.clear();
|
||||
bool success = true;
|
||||
|
|
@ -384,6 +402,11 @@ bool CompoundDriver::setSA(const DeviceDriver::SASettings &s, std::function<void
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lastNonIdleSettings.type = Types::SA;
|
||||
lastNonIdleSettings.sa = s;
|
||||
isIdle = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -414,14 +437,22 @@ bool CompoundDriver::setSG(const DeviceDriver::SGSettings &s)
|
|||
}
|
||||
success &= devices[i]->setSG(devSettings);
|
||||
}
|
||||
|
||||
lastNonIdleSettings.type = Types::SG;
|
||||
lastNonIdleSettings.sg = s;
|
||||
isIdle = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool CompoundDriver::setIdle(std::function<void (bool)> cb)
|
||||
{
|
||||
disableTriggerForwarding();
|
||||
qDebug() << "Stop trigger forwarding";
|
||||
auto success = true;
|
||||
results.clear();
|
||||
for(auto dev : devices) {
|
||||
dev->sendWithoutPayload(Protocol::PacketType::ClearTrigger);
|
||||
success &= dev->setIdle([=](bool success){
|
||||
if(cb) {
|
||||
results[dev] = success;
|
||||
|
|
@ -429,6 +460,9 @@ bool CompoundDriver::setIdle(std::function<void (bool)> cb)
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
isIdle = true;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -463,9 +497,36 @@ QStringList CompoundDriver::availableExtRefOutSettings()
|
|||
bool CompoundDriver::setExtRef(QString option_in, QString option_out)
|
||||
{
|
||||
auto success = true;
|
||||
for(auto dev : devices) {
|
||||
success &= dev->setExtRef(option_in, option_out);
|
||||
|
||||
qDebug() << "Ref change start";
|
||||
if(isIdle) {
|
||||
// can immediately switch reference settings
|
||||
for(auto dev : devices) {
|
||||
success &= dev->setExtRef(option_in, option_out);
|
||||
}
|
||||
} else {
|
||||
// can not switch during a sweep
|
||||
// set to idle first
|
||||
setIdle();
|
||||
// change reference
|
||||
for(auto dev : devices) {
|
||||
success &= dev->setExtRef(option_in, option_out);
|
||||
}
|
||||
// restore last non idle state
|
||||
switch(lastNonIdleSettings.type) {
|
||||
case Types::VNA:
|
||||
setVNA(lastNonIdleSettings.vna);
|
||||
break;
|
||||
case Types::SA:
|
||||
setSA(lastNonIdleSettings.sa);
|
||||
break;
|
||||
case Types::SG:
|
||||
setSG(lastNonIdleSettings.sg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
qDebug() << "Ref change stop";
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -484,6 +545,27 @@ std::set<QString> CompoundDriver::getIndividualDeviceSerials()
|
|||
return ret;
|
||||
}
|
||||
|
||||
void CompoundDriver::triggerReceived(LibreVNADriver *device, bool set)
|
||||
{
|
||||
triggerMutex.lock();
|
||||
if(activeDevice.sync == LibreVNADriver::Synchronization::GUI && triggerForwarding) {
|
||||
for(unsigned int i=0;i<devices.size();i++) {
|
||||
if(devices[i] == device) {
|
||||
// pass on to the next device
|
||||
if(i < devices.size() - 1) {
|
||||
qDebug() << "Passing on trigger" << set << "from" << device->getSerial() << "to" << devices[i+1]->getSerial();
|
||||
devices[i+1]->sendWithoutPayload(set ? Protocol::PacketType::SetTrigger : Protocol::PacketType::ClearTrigger);
|
||||
} else {
|
||||
qDebug() << "Passing on trigger" << set << "from" << device->getSerial() << "to" << devices[0]->getSerial();
|
||||
devices[0]->sendWithoutPayload(set ? Protocol::PacketType::SetTrigger : Protocol::PacketType::ClearTrigger);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
triggerMutex.unlock();
|
||||
}
|
||||
|
||||
void CompoundDriver::parseCompoundJSON()
|
||||
{
|
||||
try {
|
||||
|
|
@ -528,36 +610,6 @@ void CompoundDriver::incomingPacket(LibreVNADriver *device, const Protocol::Pack
|
|||
case Protocol::PacketType::SpectrumAnalyzerResult:
|
||||
spectrumResultReceived(device, p.spectrumResult);
|
||||
break;
|
||||
case Protocol::PacketType::SetTrigger:
|
||||
if(activeDevice.sync == LibreVNADriver::Synchronization::GUI) {
|
||||
for(unsigned int i=0;i<devices.size();i++) {
|
||||
if(devices[i] == device) {
|
||||
// pass on to the next device
|
||||
if(i < devices.size() - 1) {
|
||||
devices[i+1]->sendWithoutPayload(Protocol::PacketType::SetTrigger);
|
||||
} else {
|
||||
devices[0]->sendWithoutPayload(Protocol::PacketType::SetTrigger);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Protocol::PacketType::ClearTrigger:
|
||||
if(activeDevice.sync == LibreVNADriver::Synchronization::GUI) {
|
||||
for(unsigned int i=0;i<devices.size();i++) {
|
||||
if(devices[i] == device) {
|
||||
// pass on to the next device
|
||||
if(i < devices.size() - 1) {
|
||||
devices[i+1]->sendWithoutPayload(Protocol::PacketType::ClearTrigger);
|
||||
} else {
|
||||
devices[0]->sendWithoutPayload(Protocol::PacketType::ClearTrigger);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// nothing to do for other packet types
|
||||
break;
|
||||
|
|
@ -651,6 +703,26 @@ void CompoundDriver::spectrumResultReceived(LibreVNADriver *dev, Protocol::Spect
|
|||
}
|
||||
}
|
||||
|
||||
void CompoundDriver::enableTriggerForwarding()
|
||||
{
|
||||
triggerMutex.lock();
|
||||
for(auto d : devices) {
|
||||
connect(d, &LibreVNADriver::receivedTrigger, this, &CompoundDriver::triggerReceived, Qt::UniqueConnection);
|
||||
}
|
||||
triggerForwarding = true;
|
||||
triggerMutex.unlock();
|
||||
}
|
||||
|
||||
void CompoundDriver::disableTriggerForwarding()
|
||||
{
|
||||
triggerMutex.lock();
|
||||
triggerForwarding = false;
|
||||
for(auto d : devices) {
|
||||
QObject::disconnect(d, &LibreVNADriver::receivedTrigger, this, &CompoundDriver::triggerReceived);
|
||||
}
|
||||
triggerMutex.unlock();
|
||||
}
|
||||
|
||||
void CompoundDriver::datapointReceivecd(LibreVNADriver *dev, Protocol::VNADatapoint<32> *data)
|
||||
{
|
||||
if(!compoundVNABuffer.count(data->pointNum)) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include "../../devicedriver.h"
|
||||
#include "compounddevice.h"
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
class CompoundDriver : public DeviceDriver
|
||||
{
|
||||
public:
|
||||
|
|
@ -169,6 +171,8 @@ public:
|
|||
|
||||
static std::set<QString> getIndividualDeviceSerials();
|
||||
|
||||
private slots:
|
||||
void triggerReceived(LibreVNADriver *device, bool set);
|
||||
private:
|
||||
void parseCompoundJSON();
|
||||
void createCompoundJSON();
|
||||
|
|
@ -177,6 +181,8 @@ private:
|
|||
void updatedStatus(LibreVNADriver *device, const Protocol::DeviceStatus &status);
|
||||
void datapointReceivecd(LibreVNADriver *dev, Protocol::VNADatapoint<32> *data);
|
||||
void spectrumResultReceived(LibreVNADriver *dev, Protocol::SpectrumAnalyzerResult res);
|
||||
void enableTriggerForwarding();
|
||||
void disableTriggerForwarding();
|
||||
|
||||
Info info;
|
||||
std::map<LibreVNADriver*, Info> deviceInfos;
|
||||
|
|
@ -196,8 +202,18 @@ private:
|
|||
// Configuration of the device we are connected to
|
||||
CompoundDevice activeDevice;
|
||||
bool connected;
|
||||
bool triggerForwarding;
|
||||
QMutex triggerMutex;
|
||||
std::vector<LibreVNADriver*> devices;
|
||||
bool zerospan;
|
||||
bool isIdle;
|
||||
enum class Types{VNA, SA, SG};
|
||||
struct {
|
||||
VNASettings vna;
|
||||
SASettings sa;
|
||||
SGSettings sg;
|
||||
Types type;
|
||||
} lastNonIdleSettings;
|
||||
unsigned int VNApoints;
|
||||
unsigned int SApoints;
|
||||
|
||||
|
|
|
|||
|
|
@ -191,6 +191,8 @@ signals:
|
|||
void receivedAnswer(const LibreVNADriver::TransmissionResult &result);
|
||||
void receivedPacket(const Protocol::PacketInfo& packet);
|
||||
|
||||
void receivedTrigger(LibreVNADriver *driver, bool set);
|
||||
|
||||
protected slots:
|
||||
void handleReceivedPacket(const Protocol::PacketInfo& packet);
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -242,6 +242,12 @@ void LibreVNATCPDriver::ReceivedData()
|
|||
case Protocol::PacketType::Nack:
|
||||
emit receivedAnswer(TransmissionResult::Nack);
|
||||
break;
|
||||
case Protocol::PacketType::SetTrigger:
|
||||
emit receivedTrigger(this, true);
|
||||
break;
|
||||
case Protocol::PacketType::ClearTrigger:
|
||||
emit receivedTrigger(this, false);
|
||||
break;
|
||||
default:
|
||||
// pass on to LibreVNADriver class
|
||||
emit receivedPacket(packet);
|
||||
|
|
|
|||
|
|
@ -179,6 +179,12 @@ void LibreVNAUSBDriver::ReceivedData()
|
|||
}
|
||||
}
|
||||
dataBuffer->removeBytes(handled_len);
|
||||
if(packet.type == Protocol::PacketType::SetTrigger) {
|
||||
qDebug() << "Incoming set trigger from " << serial;
|
||||
}
|
||||
if(packet.type == Protocol::PacketType::ClearTrigger) {
|
||||
qDebug() << "Incoming clear trigger from " << serial;
|
||||
}
|
||||
switch(packet.type) {
|
||||
case Protocol::PacketType::Ack:
|
||||
emit receivedAnswer(TransmissionResult::Ack);
|
||||
|
|
@ -186,6 +192,12 @@ void LibreVNAUSBDriver::ReceivedData()
|
|||
case Protocol::PacketType::Nack:
|
||||
emit receivedAnswer(TransmissionResult::Nack);
|
||||
break;
|
||||
case Protocol::PacketType::SetTrigger:
|
||||
emit receivedTrigger(this, true);
|
||||
break;
|
||||
case Protocol::PacketType::ClearTrigger:
|
||||
emit receivedTrigger(this, false);
|
||||
break;
|
||||
case Protocol::PacketType::None:
|
||||
break;
|
||||
default:
|
||||
|
|
@ -377,6 +389,6 @@ bool LibreVNAUSBDriver::startNextTransmission()
|
|||
return false;
|
||||
}
|
||||
transmissionTimer.start(t.timeout);
|
||||
qDebug() << "Transmission started (packet type" << (int) t.packet.type << "), queue at " << transmissionQueue.size();
|
||||
// qDebug() << "Transmission started (packet type" << (int) t.packet.type << "), queue at " << transmissionQueue.size();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,10 @@ DeviceLog::~DeviceLog()
|
|||
|
||||
void DeviceLog::addLine(QString line)
|
||||
{
|
||||
// Set color depending on log level
|
||||
QColor color = Qt::black;
|
||||
// Set color depending on log level.
|
||||
// Use theme dependent color for info messages
|
||||
QColor color = QApplication::palette().text().color();
|
||||
// Use fixed colors for other log levels
|
||||
if(line.contains(",CRT]")) {
|
||||
color = Qt::red;
|
||||
} else if(line.contains(",ERR]")) {
|
||||
|
|
|
|||
|
|
@ -412,11 +412,12 @@ RESOURCES += \
|
|||
resources/librevna.qrc
|
||||
|
||||
win32:RC_ICONS = resources/librevna.ico
|
||||
mac:ICON = resources/librevna.icns
|
||||
|
||||
QMAKE_CXXFLAGS += -Wno-deprecated -Wno-deprecated-declarations -Wno-deprecated-copy
|
||||
|
||||
CONFIG += c++17
|
||||
REVISION = $$system(git rev-parse HEAD)
|
||||
DEFINES += GITHASH=\\"\"$$REVISION\\"\"
|
||||
DEFINES += FW_MAJOR=1 FW_MINOR=6 FW_PATCH=2 FW_SUFFIX=""
|
||||
DEFINES += FW_MAJOR=1 FW_MINOR=6 FW_PATCH=3 FW_SUFFIX=""
|
||||
DEFINES -= _UNICODE UNICODE
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
|
|||
}
|
||||
}
|
||||
|
||||
window->addStreamingData(m_avg, AppWindow::SADataType::Raw);
|
||||
window->addStreamingData(m_avg, AppWindow::SADataType::Raw, settings.freqStart == settings.freqStop);
|
||||
|
||||
if(normalize.measuring) {
|
||||
if(average.currentSweep() == averages) {
|
||||
|
|
@ -569,7 +569,7 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
|
|||
m.second /= normalize.portCorrection[m.first][m_avg.pointNum];
|
||||
m.second *= corr;
|
||||
}
|
||||
window->addStreamingData(m_avg, AppWindow::SADataType::Normalized);
|
||||
window->addStreamingData(m_avg, AppWindow::SADataType::Normalized, settings.freqStart == settings.freqStop);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ Marker::Marker(MarkerModel *model, int number, Marker *parent, QString descr)
|
|||
connect(this, &Marker::traceChanged, this, &Marker::updateContextmenu);
|
||||
connect(this, &Marker::typeChanged, this, &Marker::updateContextmenu);
|
||||
updateContextmenu();
|
||||
|
||||
connect(&Preferences::getInstance(), &Preferences::updated, this, &Marker::updateSymbol);
|
||||
}
|
||||
|
||||
Marker::~Marker()
|
||||
|
|
@ -815,7 +817,7 @@ void Marker::traceDataChanged(unsigned int begin, unsigned int end)
|
|||
|
||||
void Marker::updateSymbol()
|
||||
{
|
||||
if(isDisplayedMarker()) {
|
||||
if(isDisplayedMarker() && parentTrace) {
|
||||
auto style = Preferences::getInstance().Marker.symbolStyle;
|
||||
switch(style) {
|
||||
case MarkerSymbolStyle::FilledNumberInside: {
|
||||
|
|
|
|||
|
|
@ -91,6 +91,14 @@ void Math::Expression::inputSamplesChanged(unsigned int begin, unsigned int end)
|
|||
}
|
||||
dataMutex.lock();
|
||||
data.resize(in.size());
|
||||
// sanity check input values
|
||||
if(end > 0 && end > in.size()) {
|
||||
end = in.size() - 1;
|
||||
}
|
||||
if(end <= begin) {
|
||||
dataMutex.unlock();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
for(unsigned int i=begin;i<end;i++) {
|
||||
t = in[i].x;
|
||||
|
|
|
|||
|
|
@ -427,6 +427,9 @@ QString Trace::getMathFormulaError() const
|
|||
break;
|
||||
}
|
||||
}
|
||||
if(varName == "x") {
|
||||
found = true;
|
||||
}
|
||||
if(!found) {
|
||||
return "Unknown variable: "+varName;
|
||||
}
|
||||
|
|
@ -465,7 +468,21 @@ void Trace::updateMathTracePoints()
|
|||
double startX = std::numeric_limits<double>::lowest();
|
||||
double stopX = std::numeric_limits<double>::max();
|
||||
double stepSize = std::numeric_limits<double>::max();
|
||||
auto domain = DataType::Invalid;
|
||||
for(auto t : mathSourceTraces) {
|
||||
if(domain == DataType::Invalid) {
|
||||
domain = t.first->outputType();
|
||||
} else {
|
||||
if(domain != t.first->outputType()) {
|
||||
// not all traces have the same domain, clear output and do not calculate
|
||||
data.resize(0);
|
||||
mathUpdateBegin = 0;
|
||||
mathUpdateEnd = 0;
|
||||
dataType = DataType::Invalid;
|
||||
emit outputTypeChanged(dataType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(t.first->minX() > startX) {
|
||||
startX = t.first->minX();
|
||||
}
|
||||
|
|
@ -480,7 +497,14 @@ void Trace::updateMathTracePoints()
|
|||
stepSize = traceStepSize;
|
||||
}
|
||||
}
|
||||
unsigned int samples = round((stopX - startX) / stepSize + 1);
|
||||
if(domain != this->domain) {
|
||||
this->domain = domain;
|
||||
emit typeChanged(this);
|
||||
}
|
||||
unsigned int samples = 0;
|
||||
if(stopX > startX) {
|
||||
samples = round((stopX - startX) / stepSize + 1);
|
||||
}
|
||||
// qDebug() << "Updated trace points, now"<<samples<<"points from"<<startX<<"to"<<stopX;
|
||||
if(samples != data.size()) {
|
||||
auto oldSize = data.size();
|
||||
|
|
@ -530,6 +554,10 @@ void Trace::scheduleMathCalculation(unsigned int begin, unsigned int end)
|
|||
void Trace::calculateMath()
|
||||
{
|
||||
lastMathUpdate = QTime::currentTime();
|
||||
if(mathUpdateEnd <= mathUpdateBegin) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
if(mathUpdateBegin >= data.size() || mathUpdateEnd >= data.size() + 1) {
|
||||
qWarning() << "Not calculating math trace, out of limits. Requested from" << mathUpdateBegin << "to" << mathUpdateEnd <<" but data is of size" << data.size();
|
||||
return;
|
||||
|
|
@ -639,6 +667,11 @@ bool Trace::canAddAsMathSource(Trace *t)
|
|||
|
||||
bool Trace::addMathSource(Trace *t, QString variableName)
|
||||
{
|
||||
if(mathSourceTraces.count(t)) {
|
||||
// this trace is already used as a math source
|
||||
mathSourceTraces[t] = variableName;
|
||||
return true;
|
||||
}
|
||||
// qDebug() << "Adding trace" << t << "as a math source to" << this << "as variable" << variableName;
|
||||
if(!canAddAsMathSource(t)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class TraceModel;
|
|||
class Trace : public TraceMath
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class TraceEditDialog;
|
||||
public:
|
||||
|
||||
using Data = TraceMath::Data;
|
||||
|
|
|
|||
|
|
@ -393,6 +393,26 @@ std::complex<double> YAxis::reconstructValueFromYAxisType(std::map<YAxis::Type,
|
|||
return ret;
|
||||
}
|
||||
|
||||
double YAxis::getDefaultLimitMax(Type type)
|
||||
{
|
||||
return Preferences::getInstance().Graphs.defaultAxisLimits.max[(int) type];
|
||||
}
|
||||
|
||||
double YAxis::getDefaultLimitMin(Type type)
|
||||
{
|
||||
return Preferences::getInstance().Graphs.defaultAxisLimits.min[(int) type];
|
||||
}
|
||||
|
||||
double YAxis::getDefaultLimitMax()
|
||||
{
|
||||
return getDefaultLimitMax(type);
|
||||
}
|
||||
|
||||
double YAxis::getDefaultLimitMin()
|
||||
{
|
||||
return getDefaultLimitMin(type);
|
||||
}
|
||||
|
||||
void YAxis::updateTicks()
|
||||
{
|
||||
Axis::updateTicks();
|
||||
|
|
|
|||
|
|
@ -108,6 +108,10 @@ public:
|
|||
bool isSupported(XAxis::Type type, TraceModel::DataSource source);
|
||||
static std::set<YAxis::Type> getSupported(XAxis::Type type, TraceModel::DataSource source);
|
||||
static std::complex<double> reconstructValueFromYAxisType(std::map<Type, double> yaxistypes);
|
||||
static double getDefaultLimitMax(YAxis::Type type);
|
||||
static double getDefaultLimitMin(YAxis::Type type);
|
||||
double getDefaultLimitMax();
|
||||
double getDefaultLimitMin();
|
||||
|
||||
protected:
|
||||
virtual void updateTicks() override;
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
|
|||
if(t.mathDependsOn(ts, true)) {
|
||||
traceItem->setCheckState(Qt::Checked);
|
||||
variableItem->setFlags(variableItem->flags() | Qt::ItemIsEnabled | Qt::ItemIsEditable);
|
||||
ui->mathTraceTable->blockSignals(false);
|
||||
} else {
|
||||
traceItem->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
|
|
@ -181,7 +182,7 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
|
|||
connect(ui->mathTraceTable, &QTableWidget::itemChanged, [&](QTableWidgetItem *item){
|
||||
auto row = ui->mathTraceTable->row(item);
|
||||
auto column = ui->mathTraceTable->column(item);
|
||||
qDebug() << "Item changed at row"<<row<<"column"<<column;
|
||||
// qDebug() << "Item changed at row"<<row<<"column"<<column;
|
||||
ui->mathTraceTable->blockSignals(true);
|
||||
auto trace = t.getModel()->trace(row);
|
||||
if(column == 0) {
|
||||
|
|
@ -198,16 +199,7 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
|
|||
variableItem->setText("");
|
||||
variableItem->setFlags(variableItem->flags() & ~(Qt::ItemIsEnabled | Qt::ItemIsEditable));
|
||||
}
|
||||
// available trace selections may have changed, disable/enable other rows
|
||||
for(unsigned int i=0;i<t.getModel()->getTraces().size();i++) {
|
||||
auto traceItem = ui->mathTraceTable->item(i, 0);
|
||||
auto flags = traceItem->flags();
|
||||
if(t.canAddAsMathSource(t.getModel()->trace(i))) {
|
||||
traceItem->setFlags(flags | Qt::ItemIsEnabled);
|
||||
} else {
|
||||
traceItem->setFlags(flags & ~Qt::ItemIsEnabled);
|
||||
}
|
||||
}
|
||||
updateMathFormulaSelectableRows();
|
||||
} else {
|
||||
// changed the variable name text
|
||||
t.addMathSource(trace, item->text());
|
||||
|
|
@ -216,6 +208,8 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
|
|||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(updateMathFormulaStatus());
|
||||
});
|
||||
}
|
||||
updateMathFormulaSelectableRows();
|
||||
updateMathFormulaStatus();
|
||||
|
||||
switch(t.getSource()) {
|
||||
case Trace::Source::Live: ui->bLive->click(); break;
|
||||
|
|
@ -384,6 +378,21 @@ void TraceEditDialog::okClicked()
|
|||
|
||||
bool TraceEditDialog::updateMathFormulaStatus()
|
||||
{
|
||||
// check output domains first (there could be a problem if a trace changed its output domain
|
||||
// after the math trace was created)
|
||||
auto domain = TraceMath::DataType::Invalid;
|
||||
for(auto t : trace.mathSourceTraces) {
|
||||
if(domain == TraceMath::DataType::Invalid) {
|
||||
domain = t.first->outputType();
|
||||
} else {
|
||||
if(domain != t.first->outputType()) {
|
||||
// not all traces have the same domain
|
||||
ui->lMathFormulaStatus->setText("Different output domains of selected source traces");
|
||||
ui->lMathFormulaStatus->setStyleSheet("QLabel { color : red; }");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto error = trace.getMathFormulaError();
|
||||
if(error.isEmpty()) {
|
||||
// all good
|
||||
|
|
@ -397,6 +406,25 @@ bool TraceEditDialog::updateMathFormulaStatus()
|
|||
}
|
||||
}
|
||||
|
||||
void TraceEditDialog::updateMathFormulaSelectableRows()
|
||||
{
|
||||
// available trace selections may have changed, disable/enable other rows
|
||||
|
||||
// block signals, otherwise the trace names will be reset
|
||||
ui->mathTraceTable->blockSignals(true);
|
||||
for(unsigned int i=0;i<trace.getModel()->getTraces().size();i++) {
|
||||
auto traceItem = ui->mathTraceTable->item(i, 0);
|
||||
auto flags = traceItem->flags();
|
||||
if(trace.canAddAsMathSource(trace.getModel()->trace(i)) || traceItem->checkState()) {
|
||||
// Item can always be deselected but only selected if it is compatible
|
||||
traceItem->setFlags(flags | Qt::ItemIsEnabled);
|
||||
} else {
|
||||
traceItem->setFlags(flags & ~Qt::ItemIsEnabled);
|
||||
}
|
||||
}
|
||||
ui->mathTraceTable->blockSignals(false);
|
||||
}
|
||||
|
||||
MathModel::MathModel(Trace &t, QObject *parent)
|
||||
: QAbstractTableModel(parent),
|
||||
t(t)
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ private slots:
|
|||
|
||||
private:
|
||||
bool updateMathFormulaStatus();
|
||||
void updateMathFormulaSelectableRows();
|
||||
Ui::TraceEditDialog *ui;
|
||||
Trace &trace;
|
||||
bool VNAtrace;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <QMimeData>
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
#include <QInputDialog>
|
||||
|
||||
std::set<TracePlot*> TracePlot::plots;
|
||||
|
||||
|
|
@ -233,13 +234,24 @@ void TracePlot::paintEvent(QPaintEvent *event)
|
|||
p.setBackground(QBrush(pref.Graphs.Color.background));
|
||||
p.fillRect(0, 0, width(), height(), QBrush(pref.Graphs.Color.background));
|
||||
|
||||
marginTop = 0;
|
||||
// draw title
|
||||
if(!title.isEmpty()) {
|
||||
QFont font = p.font();
|
||||
font.setPixelSize(pref.Graphs.fontSizeTitle);
|
||||
p.setFont(font);
|
||||
p.setPen(Util::getFontColorFromBackground(pref.Graphs.Color.background));
|
||||
p.drawText(QRect(0, 0, width(), pref.Graphs.fontSizeTitle), Qt::AlignCenter, title);
|
||||
marginTop += pref.Graphs.fontSizeTitle;
|
||||
}
|
||||
|
||||
// show names of active traces and marker data (if enabled)
|
||||
bool hasMarkerData = false;
|
||||
auto marginMarkerData = pref.Graphs.fontSizeMarkerData * 12.5;
|
||||
marginTop = pref.Graphs.fontSizeTraceNames + 8;
|
||||
auto traceNameTop = marginTop + 5;
|
||||
marginTop += pref.Graphs.fontSizeTraceNames + 8;
|
||||
int x = 1; // xcoordinate for the next trace name
|
||||
int y = marginTop; // ycoordinate for the next marker data
|
||||
auto areaTextTop = 5;
|
||||
auto labelMarginRight = 4;
|
||||
auto borderRadius = 5;
|
||||
for(auto t : traces) {
|
||||
|
|
@ -248,7 +260,7 @@ void TracePlot::paintEvent(QPaintEvent *event)
|
|||
}
|
||||
|
||||
// Trace name
|
||||
auto textArea = QRect(x, areaTextTop, width() - x, marginTop);
|
||||
auto textArea = QRect(x, traceNameTop, width() - x, pref.Graphs.fontSizeTraceNames + 8);
|
||||
QFont font = p.font();
|
||||
font.setPixelSize(pref.Graphs.fontSizeTraceNames);
|
||||
p.setFont(font);
|
||||
|
|
@ -384,6 +396,13 @@ void TracePlot::paintEvent(QPaintEvent *event)
|
|||
void TracePlot::finishContextMenu()
|
||||
{
|
||||
contextmenu->addSeparator();
|
||||
auto setTitle = new QAction("Set Title", contextmenu);
|
||||
contextmenu->addAction(setTitle);
|
||||
connect(setTitle, &QAction::triggered, [=](){
|
||||
title = QInputDialog::getText(contextmenu, "Set new graph title", "Enter new title:", QLineEdit::Normal, title);
|
||||
});
|
||||
contextmenu->addSeparator();
|
||||
|
||||
if(parentTile) {
|
||||
auto add = new QMenu("Add tile...", contextmenu);
|
||||
auto left = new QAction("to the left", contextmenu);
|
||||
|
|
@ -723,6 +742,18 @@ QRect TracePlot::getDropRect()
|
|||
return QRect(QPoint(w*dropBorders, h*dropBorders), QSize(w*(1.0-2*dropBorders), h*(1.0-2*dropBorders)));
|
||||
}
|
||||
|
||||
nlohmann::json TracePlot::getBaseJSON()
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["title"] = title.toStdString();
|
||||
return j;
|
||||
}
|
||||
|
||||
void TracePlot::parseBaseJSON(nlohmann::json j)
|
||||
{
|
||||
title = QString::fromStdString(j.value("title", ""));
|
||||
}
|
||||
|
||||
std::set<TracePlot *> TracePlot::getPlots()
|
||||
{
|
||||
return plots;
|
||||
|
|
|
|||
|
|
@ -103,6 +103,10 @@ protected:
|
|||
virtual QString mouseText(QPoint pos) {Q_UNUSED(pos) return QString();}
|
||||
QRect getDropRect();
|
||||
|
||||
// save/load base class members. Should be called by derived classes in the toJSON/fromJSON functions
|
||||
nlohmann::json getBaseJSON();
|
||||
void parseBaseJSON(nlohmann::json j);
|
||||
|
||||
protected slots:
|
||||
void newTraceAvailable(Trace *t);
|
||||
void traceDeleted(Trace *t);
|
||||
|
|
@ -150,6 +154,9 @@ protected:
|
|||
unsigned int marginTop;
|
||||
|
||||
bool limitPassing;
|
||||
|
||||
private:
|
||||
QString title;
|
||||
};
|
||||
|
||||
#endif // TRACEPLOT_H
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ TracePolar::TracePolar(TraceModel &model, QWidget *parent)
|
|||
|
||||
nlohmann::json TracePolar::toJSON()
|
||||
{
|
||||
nlohmann::json j;
|
||||
nlohmann::json j = getBaseJSON();
|
||||
j["limit_to_span"] = limitToSpan;
|
||||
j["limit_to_edge"] = limitToEdge;
|
||||
j["edge_reflection"] = edgeReflection;
|
||||
|
|
@ -44,6 +44,7 @@ nlohmann::json TracePolar::toJSON()
|
|||
|
||||
void TracePolar::fromJSON(nlohmann::json j)
|
||||
{
|
||||
parseBaseJSON(j);
|
||||
limitToSpan = j.value("limit_to_span", true);
|
||||
limitToEdge = j.value("limit_to_edge", false);
|
||||
edgeReflection = j.value("edge_reflection", 1.0);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,23 @@ TraceTouchstoneExport::TraceTouchstoneExport(TraceModel &model, QWidget *parent)
|
|||
ui->selector->setModel(&model);
|
||||
ui->selector->setPartialSelectionAllowed(true);
|
||||
connect(ui->selector, qOverload<>(&TraceSetSelector::selectionChanged), this, &TraceTouchstoneExport::selectionChanged);
|
||||
on_sbPorts_valueChanged(ui->sbPorts->value());
|
||||
connect(ui->sbPorts, &QSpinBox::valueChanged, this, &TraceTouchstoneExport::setPortNum);
|
||||
// figure out how many ports the user most likely needs
|
||||
unsigned int p;
|
||||
for(p=4;p>=1;p--) {
|
||||
// do we have a trace name which could indicate such a number of ports?
|
||||
for(unsigned int i=1;i<=p;i++) {
|
||||
auto n1 = "S"+QString::number(p)+QString::number(i);
|
||||
auto n2 = "S"+QString::number(i)+QString::number(p);
|
||||
for(auto t : model.getTraces()) {
|
||||
if(t->name().contains(n1) || t->name().contains(n2)) {
|
||||
goto traceFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
traceFound:
|
||||
setPortNum(p);
|
||||
}
|
||||
|
||||
TraceTouchstoneExport::~TraceTouchstoneExport()
|
||||
|
|
@ -30,13 +46,32 @@ bool TraceTouchstoneExport::setTrace(int portFrom, int portTo, Trace *t)
|
|||
return ui->selector->setTrace(portTo, portFrom, t);
|
||||
}
|
||||
|
||||
bool TraceTouchstoneExport::setPortNum(int ports)
|
||||
bool TraceTouchstoneExport::setPortNum(unsigned int ports)
|
||||
{
|
||||
if(ports < 1 || ports > 4) {
|
||||
return false;
|
||||
}
|
||||
if((unsigned int) ui->sbPorts->value() == ports && ui->selector->getPorts() == ports) {
|
||||
// already set correctly, nothing to do
|
||||
return true;
|
||||
}
|
||||
ui->sbPorts->setValue(ports);
|
||||
ui->selector->setPorts(ports);
|
||||
// Attempt to set default traces (this will result in correctly populated
|
||||
// 2 port export if the initial 4 traces have not been modified)
|
||||
auto traces = ui->selector->getModel()->getTraces();
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
for(unsigned int j=1;j<=ports;j++) {
|
||||
auto name = "S"+QString::number(i)+QString::number(j);
|
||||
for(auto t : traces) {
|
||||
if(t->name().contains(name)) {
|
||||
// this could be the correct trace
|
||||
setTrace(j, i, t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -86,11 +121,6 @@ void TraceTouchstoneExport::on_buttonBox_accepted()
|
|||
}
|
||||
}
|
||||
|
||||
void TraceTouchstoneExport::on_sbPorts_valueChanged(int ports)
|
||||
{
|
||||
ui->selector->setPorts(ports);
|
||||
}
|
||||
|
||||
void TraceTouchstoneExport::selectionChanged()
|
||||
{
|
||||
auto valid = ui->selector->selectionValid();
|
||||
|
|
|
|||
|
|
@ -19,11 +19,10 @@ public:
|
|||
explicit TraceTouchstoneExport(TraceModel &model, QWidget *parent = nullptr);
|
||||
~TraceTouchstoneExport();
|
||||
bool setTrace(int portFrom, int portTo, Trace *t);
|
||||
bool setPortNum(int ports);
|
||||
bool setPortNum(unsigned int ports);
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
void on_sbPorts_valueChanged(int ports);
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ TraceWaterfall::TraceWaterfall(TraceModel &model, QWidget *parent)
|
|||
plotAreaBottom = 0;
|
||||
|
||||
xAxis.set(XAxis::Type::Frequency, false, true, 0, 6000000000, 10, false);
|
||||
yAxis.set(YAxis::Type::Magnitude, false, true, -1, 1, 10, false);
|
||||
yAxis.set(YAxis::Type::Magnitude, false, true, YAxis::getDefaultLimitMin(YAxis::Type::Magnitude), YAxis::getDefaultLimitMax(YAxis::Type::Magnitude), 10, false);
|
||||
initializeTraceInfo();
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +95,7 @@ void TraceWaterfall::replot()
|
|||
|
||||
void TraceWaterfall::fromJSON(nlohmann::json j)
|
||||
{
|
||||
parseBaseJSON(j);
|
||||
resetWaterfall();
|
||||
pixelsPerLine = j.value("pixelsPerLine", pixelsPerLine);
|
||||
maxDataSweeps = j.value("maxLines", maxDataSweeps);
|
||||
|
|
@ -127,7 +128,7 @@ void TraceWaterfall::fromJSON(nlohmann::json j)
|
|||
|
||||
nlohmann::json TraceWaterfall::toJSON()
|
||||
{
|
||||
nlohmann::json j;
|
||||
nlohmann::json j = getBaseJSON();
|
||||
j["pixelsPerLine"] = pixelsPerLine;
|
||||
j["direction"] = dir == Direction::TopToBottom ? "TopToBottom" : "BottomToTop";
|
||||
j["keepDataBeyondPlot"] = keepDataBeyondPlotSize;
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ TraceXYPlot::TraceXYPlot(TraceModel &model, QWidget *parent)
|
|||
yAxis[1].setTickMaster(yAxis[0]);
|
||||
|
||||
// Setup default axis
|
||||
setYAxis(0, YAxis::Type::Magnitude, false, false, -120, 20, 14, true);
|
||||
setYAxis(1, YAxis::Type::Phase, false, false, -180, 180, 12, true);
|
||||
setYAxis(0, YAxis::Type::Magnitude, false, false, YAxis::getDefaultLimitMin(YAxis::Type::Magnitude), YAxis::getDefaultLimitMax(YAxis::Type::Magnitude), 14, true);
|
||||
setYAxis(1, YAxis::Type::Phase, false, false, YAxis::getDefaultLimitMin(YAxis::Type::Phase), YAxis::getDefaultLimitMax(YAxis::Type::Phase), 12, true);
|
||||
// enable autoscaling and set for full span (no information about actual span available yet)
|
||||
updateSpan(0, 6000000000);
|
||||
setXAxis(XAxis::Type::Frequency, XAxisMode::UseSpan, false, 0, 6000000000, 10, true);
|
||||
|
|
@ -157,7 +157,7 @@ void TraceXYPlot::setAuto(bool horizontally, bool vertically)
|
|||
|
||||
nlohmann::json TraceXYPlot::toJSON()
|
||||
{
|
||||
nlohmann::json j;
|
||||
nlohmann::json j = getBaseJSON();
|
||||
nlohmann::json jX;
|
||||
jX["type"] = xAxis.TypeToName().toStdString();
|
||||
jX["mode"] = AxisModeToName(xAxisMode).toStdString();
|
||||
|
|
@ -198,6 +198,7 @@ nlohmann::json TraceXYPlot::toJSON()
|
|||
|
||||
void TraceXYPlot::fromJSON(nlohmann::json j)
|
||||
{
|
||||
parseBaseJSON(j);
|
||||
auto jX = j["XAxis"];
|
||||
// old format used enum value for type and mode, new format uses string encoding (more robust when additional enum values are added).
|
||||
// Check which format is used and parse accordingly
|
||||
|
|
@ -329,10 +330,10 @@ bool TraceXYPlot::configureForTrace(Trace *t)
|
|||
return false;
|
||||
}
|
||||
if(!yAxis[0].isSupported(xAxis.getType(), getModel().getSource())) {
|
||||
setYAxis(0, yLeftDefault, false, true, 0, 1, 10, false);
|
||||
setYAxis(0, yLeftDefault, false, false, YAxis::getDefaultLimitMin(yLeftDefault), YAxis::getDefaultLimitMax(yLeftDefault), 10, true);
|
||||
}
|
||||
if(!yAxis[1].isSupported(xAxis.getType(), getModel().getSource())) {
|
||||
setYAxis(1, yRightDefault, false, true, 0, 1, 10, false);
|
||||
setYAxis(1, yRightDefault, false, false, YAxis::getDefaultLimitMin(yRightDefault), YAxis::getDefaultLimitMax(yRightDefault), 10, true);
|
||||
}
|
||||
traceRemovalPending = true;
|
||||
return true;
|
||||
|
|
@ -638,13 +639,25 @@ void TraceXYPlot::draw(QPainter &p)
|
|||
p.drawLine(p1, p2);
|
||||
}
|
||||
|
||||
if(pref.Marker.clipToYAxis) {
|
||||
// clip Y coordinate of markers to visible area (always show markers, even when out of range)
|
||||
if(point.y() < plotRect.top()) {
|
||||
point.ry() = plotRect.top();
|
||||
} else if(point.y() > plotRect.bottom()) {
|
||||
point.ry() = plotRect.bottom();
|
||||
}
|
||||
}
|
||||
|
||||
if(!plotRect.contains(point)) {
|
||||
// out of screen
|
||||
continue;
|
||||
}
|
||||
auto symbol = m->getSymbol();
|
||||
point += QPoint(-symbol.width()/2, -symbol.height());
|
||||
// ignore clipRect for markers
|
||||
p.setClipping(false);
|
||||
p.drawPixmap(point, symbol);
|
||||
p.setClipping(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1027,8 +1040,14 @@ void TraceXYPlot::enableTraceAxis(Trace *t, int axis, bool enabled)
|
|||
// unable to add trace to the requested axis
|
||||
return;
|
||||
}
|
||||
if(axis == 0) {
|
||||
TracePlot::enableTrace(t, enabled);
|
||||
if(enabled) {
|
||||
TracePlot::enableTrace(t, true);
|
||||
} else {
|
||||
// only disable trace on parent trace list if disabled for both axes
|
||||
int otherAxis = axis ? 0 : 1;
|
||||
if(tracesAxis[otherAxis].find(t) == tracesAxis[otherAxis].end()) {
|
||||
TracePlot::enableTrace(t, false);
|
||||
}
|
||||
}
|
||||
bool alreadyEnabled = tracesAxis[axis].find(t) != tracesAxis[axis].end();
|
||||
if(alreadyEnabled != enabled) {
|
||||
|
|
@ -1089,11 +1108,6 @@ bool TraceXYPlot::supported(Trace *t, YAxis::Type type)
|
|||
return false;
|
||||
}
|
||||
break;
|
||||
case YAxis::Type::GroupDelay:
|
||||
if(t->isReflection()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ WaterfallAxisDialog::WaterfallAxisDialog(TraceWaterfall *plot) :
|
|||
ui->Wmin->setPrefixes(prefixes);
|
||||
ui->Wmax->setUnit(unit);
|
||||
ui->Wmax->setPrefixes(prefixes);
|
||||
ui->Wmin->setValue(YAxis::getDefaultLimitMin(type));
|
||||
ui->Wmax->setValue(YAxis::getDefaultLimitMax(type));
|
||||
});
|
||||
connect(ui->Wauto, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Wmin->setEnabled(!checked);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
log->setEnabled(false);
|
||||
linear->setEnabled(false);
|
||||
CBauto->setEnabled(false);
|
||||
min->setEnabled(false);
|
||||
max->setEnabled(false);
|
||||
divs->setEnabled(false);
|
||||
autoDivs->setEnabled(false);
|
||||
} else {
|
||||
// axis enabled
|
||||
log->setEnabled(true);
|
||||
|
|
@ -88,31 +92,29 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
max->setPrefixes(prefixes);
|
||||
};
|
||||
|
||||
connect(ui->Y1type, qOverload<int>(&QComboBox::currentIndexChanged), [this, updateYenableState](int) {
|
||||
updateYenableState(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
});
|
||||
connect(ui->Y1auto, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
});
|
||||
connect(ui->Y1log, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
});
|
||||
connect(ui->Y1autoDivs, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
});
|
||||
auto setupYAxisConnetions = [this, updateYenableState](QComboBox *type, QRadioButton *linear, QRadioButton *log, QCheckBox *CBauto, SIUnitEdit *min, SIUnitEdit *max, QSpinBox *divs, QCheckBox *autoDivs) {
|
||||
connect(type, qOverload<int>(&QComboBox::currentIndexChanged), this, [=](int) {
|
||||
updateYenableState(type, linear, log, CBauto, min, max, divs, autoDivs);
|
||||
// update min/max settings when axis has changed
|
||||
if(type->currentIndex() != 0) {
|
||||
auto axisType = (YAxis::Type) type->currentIndex();
|
||||
min->setValue(YAxis::getDefaultLimitMin(axisType));
|
||||
max->setValue(YAxis::getDefaultLimitMax(axisType));
|
||||
}
|
||||
});
|
||||
connect(CBauto, &QCheckBox::toggled, this, [=](bool) {
|
||||
updateYenableState(type, linear, log, CBauto, min, max, divs, autoDivs);
|
||||
});
|
||||
connect(log, &QCheckBox::toggled, this, [=](bool) {
|
||||
updateYenableState(type, linear, log, CBauto, min, max, divs, autoDivs);
|
||||
});
|
||||
connect(autoDivs, &QCheckBox::toggled, this, [=](bool) {
|
||||
updateYenableState(type, linear, log, CBauto, min, max, divs, autoDivs);
|
||||
});
|
||||
};
|
||||
|
||||
connect(ui->Y2type, qOverload<int>(&QComboBox::currentIndexChanged), [this, updateYenableState](int) {
|
||||
updateYenableState(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
});
|
||||
connect(ui->Y2auto, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
});
|
||||
connect(ui->Y2log, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
});
|
||||
connect(ui->Y2autoDivs, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
});
|
||||
setupYAxisConnetions(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
setupYAxisConnetions(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
|
||||
auto updateXenableState = [](QRadioButton *linear, QRadioButton *log, QCheckBox *CBauto, SIUnitEdit *min, SIUnitEdit *max, QSpinBox *divs, QCheckBox *autoDivs) {
|
||||
log->setEnabled(true);
|
||||
|
|
|
|||
|
|
@ -35,16 +35,6 @@ void TraceWidgetVNA::exportCSV()
|
|||
void TraceWidgetVNA::exportTouchstone()
|
||||
{
|
||||
auto e = new TraceTouchstoneExport(model);
|
||||
// Attempt to set default traces (this will result in correctly populated
|
||||
// 2 port export if the initial 4 traces have not been modified)
|
||||
e->setPortNum(2);
|
||||
auto traces = model.getTraces();
|
||||
for(unsigned int i=0;i<4;i++) {
|
||||
if(i >= traces.size()) {
|
||||
break;
|
||||
}
|
||||
e->setTrace(i%2+1, i/2+1, traces[i]);
|
||||
}
|
||||
if(AppWindow::showGUI()) {
|
||||
e->show();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,11 @@ VNA::VNA(AppWindow *window, QString name)
|
|||
|
||||
// A modal QProgressDialog calls processEvents() in setValue(). Needs to use a queued connection to update the progress
|
||||
// value from within the NewDatapoint slot to prevent possible re-entrancy.
|
||||
connect(this, &VNA::calibrationMeasurementPercentage, calDialog, &QProgressDialog::setValue, Qt::QueuedConnection);
|
||||
connect(this, &VNA::calibrationMeasurementPercentage, calDialog, [=](int percent) {
|
||||
if(calMeasuring || percent == 100) {
|
||||
calDialog->setValue(percent);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
connect(calDialog, &QProgressDialog::canceled, this, [=]() {
|
||||
// the user aborted the calibration measurement
|
||||
|
|
@ -184,8 +188,9 @@ VNA::VNA(AppWindow *window, QString name)
|
|||
auto menuDeembed = new QMenu("De-embedding", window);
|
||||
window->menuBar()->insertMenu(window->getUi()->menuWindow->menuAction(), menuDeembed);
|
||||
actions.insert(menuDeembed->menuAction());
|
||||
auto confDeembed = menuDeembed->addAction("Setup...");
|
||||
auto confDeembed = new QAction("Setup...", menuDeembed);
|
||||
confDeembed->setMenuRole(QAction::NoRole);
|
||||
menuDeembed->addAction(confDeembed);
|
||||
connect(confDeembed, &QAction::triggered, &deembedding, &Deembedding::configure);
|
||||
|
||||
enableDeembeddingAction = menuDeembed->addAction("De-embed VNA samples");
|
||||
|
|
@ -976,7 +981,30 @@ void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
|
|||
|
||||
m_avg = average.process(m_avg);
|
||||
|
||||
window->addStreamingData(m_avg, AppWindow::VNADataType::Raw);
|
||||
TraceMath::DataType type = TraceMath::DataType::Frequency;
|
||||
if(settings.zerospan) {
|
||||
type = TraceMath::DataType::TimeZeroSpan;
|
||||
|
||||
// keep track of first point time
|
||||
if(m_avg.pointNum == 0) {
|
||||
settings.firstPointTime = m_avg.us;
|
||||
m_avg.us = 0;
|
||||
} else {
|
||||
m_avg.us -= settings.firstPointTime;
|
||||
}
|
||||
} else {
|
||||
switch(settings.sweepType) {
|
||||
case SweepType::Last:
|
||||
case SweepType::Frequency:
|
||||
type = TraceMath::DataType::Frequency;
|
||||
break;
|
||||
case SweepType::Power:
|
||||
type = TraceMath::DataType::Power;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window->addStreamingData(m_avg, AppWindow::VNADataType::Raw, settings.zerospan);
|
||||
|
||||
if(average.settled()) {
|
||||
setOperationPending(false);
|
||||
|
|
@ -1001,36 +1029,13 @@ void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
|
|||
cal.correctMeasurement(m_avg);
|
||||
|
||||
if(cal.getCaltype().type != Calibration::Type::None) {
|
||||
window->addStreamingData(m_avg, AppWindow::VNADataType::Calibrated);
|
||||
}
|
||||
|
||||
TraceMath::DataType type = TraceMath::DataType::Frequency;
|
||||
if(settings.zerospan) {
|
||||
type = TraceMath::DataType::TimeZeroSpan;
|
||||
|
||||
// keep track of first point time
|
||||
if(m_avg.pointNum == 0) {
|
||||
settings.firstPointTime = m_avg.us;
|
||||
m_avg.us = 0;
|
||||
} else {
|
||||
m_avg.us -= settings.firstPointTime;
|
||||
}
|
||||
} else {
|
||||
switch(settings.sweepType) {
|
||||
case SweepType::Last:
|
||||
case SweepType::Frequency:
|
||||
type = TraceMath::DataType::Frequency;
|
||||
break;
|
||||
case SweepType::Power:
|
||||
type = TraceMath::DataType::Power;
|
||||
break;
|
||||
}
|
||||
window->addStreamingData(m_avg, AppWindow::VNADataType::Calibrated, settings.zerospan);
|
||||
}
|
||||
|
||||
traceModel.addVNAData(m_avg, type, false);
|
||||
if(deembedding_active) {
|
||||
deembedding.Deembed(m_avg);
|
||||
window->addStreamingData(m_avg, AppWindow::VNADataType::Deembedded);
|
||||
window->addStreamingData(m_avg, AppWindow::VNADataType::Deembedded, settings.zerospan);
|
||||
traceModel.addVNAData(m_avg, type, true);
|
||||
}
|
||||
|
||||
|
|
@ -1222,6 +1227,7 @@ bool VNA::SpanMatchCal()
|
|||
SetStartFreq(cal.getMinFreq());
|
||||
SetStopFreq(cal.getMaxFreq());
|
||||
SetPoints(cal.getNumPoints());
|
||||
UpdateCalWidget();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -507,16 +507,26 @@ void AppWindow::CreateToolbars()
|
|||
tb_reference->addWidget(new QLabel("Ref out:"));
|
||||
toolbars.reference.outFreq = new QComboBox();
|
||||
tb_reference->addWidget(toolbars.reference.outFreq);
|
||||
connect(toolbars.reference.type, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppWindow::UpdateReference);
|
||||
connect(toolbars.reference.outFreq, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppWindow::UpdateReference);
|
||||
connect(toolbars.reference.type, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppWindow::ReferenceChanged);
|
||||
connect(toolbars.reference.outFreq, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppWindow::ReferenceChanged);
|
||||
addToolBar(tb_reference);
|
||||
tb_reference->setObjectName("Reference Toolbar");
|
||||
|
||||
referenceTimer.setSingleShot(true);
|
||||
connect(&referenceTimer, &QTimer::timeout, this, &AppWindow::UpdateReference);
|
||||
}
|
||||
|
||||
void AppWindow::SetupSCPI()
|
||||
{
|
||||
scpi.add(new SCPICommand("*IDN", nullptr, [=](QStringList){
|
||||
return "LibreVNA,LibreVNA-GUI,dummy_serial,"+appVersion;
|
||||
QString ret = "LibreVNA,LibreVNA-GUI,";
|
||||
if(device) {
|
||||
ret += device->getSerial();
|
||||
} else {
|
||||
ret += "Not connected";
|
||||
}
|
||||
ret += ","+appVersion;
|
||||
return ret;
|
||||
}));
|
||||
scpi.add(new SCPICommand("*RST", [=](QStringList){
|
||||
SetResetState();
|
||||
|
|
@ -859,7 +869,7 @@ SCPI* AppWindow::getSCPI()
|
|||
return &scpi;
|
||||
}
|
||||
|
||||
void AppWindow::addStreamingData(const DeviceDriver::VNAMeasurement &m, VNADataType type)
|
||||
void AppWindow::addStreamingData(const DeviceDriver::VNAMeasurement &m, VNADataType type, bool is_zerospan)
|
||||
{
|
||||
StreamingServer *server = nullptr;
|
||||
switch(type) {
|
||||
|
|
@ -869,11 +879,11 @@ void AppWindow::addStreamingData(const DeviceDriver::VNAMeasurement &m, VNADataT
|
|||
}
|
||||
|
||||
if(server) {
|
||||
server->addData(m);
|
||||
server->addData(m, is_zerospan);
|
||||
}
|
||||
}
|
||||
|
||||
void AppWindow::addStreamingData(const DeviceDriver::SAMeasurement &m, SADataType type)
|
||||
void AppWindow::addStreamingData(const DeviceDriver::SAMeasurement &m, SADataType type, bool is_zerospan)
|
||||
{
|
||||
StreamingServer *server = nullptr;
|
||||
switch(type) {
|
||||
|
|
@ -882,7 +892,7 @@ void AppWindow::addStreamingData(const DeviceDriver::SAMeasurement &m, SADataTyp
|
|||
}
|
||||
|
||||
if(server) {
|
||||
server->addData(m);
|
||||
server->addData(m, is_zerospan);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -945,7 +955,7 @@ void AppWindow::ResetReference()
|
|||
toolbars.reference.outFreq->setCurrentIndex(0);
|
||||
toolbars.reference.type->blockSignals(false);
|
||||
toolbars.reference.outFreq->blockSignals(false);
|
||||
UpdateReference();
|
||||
ReferenceChanged();
|
||||
}
|
||||
|
||||
//void AppWindow::StartManualControl()
|
||||
|
|
@ -1001,7 +1011,16 @@ void AppWindow::UpdateReferenceToolbar()
|
|||
}
|
||||
toolbars.reference.type->blockSignals(false);
|
||||
toolbars.reference.outFreq->blockSignals(false);
|
||||
UpdateReference();
|
||||
ReferenceChanged();
|
||||
}
|
||||
|
||||
void AppWindow::ReferenceChanged()
|
||||
{
|
||||
if(!device) {
|
||||
// can't update without a device connected
|
||||
return;
|
||||
}
|
||||
referenceTimer.start(100);
|
||||
}
|
||||
|
||||
void AppWindow::UpdateReference()
|
||||
|
|
|
|||
|
|
@ -59,14 +59,14 @@ public:
|
|||
Deembedded = 2,
|
||||
};
|
||||
|
||||
void addStreamingData(const DeviceDriver::VNAMeasurement &m, VNADataType type);
|
||||
void addStreamingData(const DeviceDriver::VNAMeasurement &m, VNADataType type, bool is_zerospan);
|
||||
|
||||
enum class SADataType {
|
||||
Raw = 0,
|
||||
Normalized = 1,
|
||||
};
|
||||
|
||||
void addStreamingData(const DeviceDriver::SAMeasurement &m, SADataType type);
|
||||
void addStreamingData(const DeviceDriver::SAMeasurement &m, SADataType type, bool is_zerospan);
|
||||
|
||||
public slots:
|
||||
void setModeStatus(QString msg);
|
||||
|
|
@ -82,6 +82,7 @@ private slots:
|
|||
// void StartManualControl();
|
||||
void ResetReference();
|
||||
void UpdateReferenceToolbar();
|
||||
void ReferenceChanged();
|
||||
void UpdateReference();
|
||||
void DeviceStatusUpdated();
|
||||
void DeviceFlagsUpdated();
|
||||
|
|
@ -144,6 +145,9 @@ private:
|
|||
QString deviceSerial;
|
||||
QActionGroup *deviceActionGroup;
|
||||
|
||||
// Reference change timer
|
||||
QTimer referenceTimer;
|
||||
|
||||
// Status bar widgets
|
||||
QLabel lConnectionStatus;
|
||||
QLabel lDeviceInfo;
|
||||
|
|
|
|||
|
|
@ -179,10 +179,14 @@ void ModeHandler::setStatusBarMessageChanged(const QString &msg)
|
|||
}
|
||||
}
|
||||
|
||||
bool ModeHandler::nameAllowed(const QString &name)
|
||||
bool ModeHandler::nameAllowed(const QString &name, unsigned int ignoreIndex)
|
||||
{
|
||||
for(auto m : modes) {
|
||||
if(m->getName() == name) {
|
||||
for(unsigned int i=0;i<modes.size();i++) {
|
||||
if(i == ignoreIndex) {
|
||||
// ignore possible collision at this index
|
||||
continue;
|
||||
}
|
||||
if(modes[i]->getName() == name) {
|
||||
/* name already taken, no duplicates allowed
|
||||
* when importing, name is used as value
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public:
|
|||
Mode* getMode(int index);
|
||||
std::vector<Mode*> getModes();
|
||||
|
||||
bool nameAllowed(const QString &name);
|
||||
bool nameAllowed(const QString &name, unsigned int ignoreIndex=-1);
|
||||
int findIndex(Mode *targetMode);
|
||||
Mode* findFirstOfType(Mode::Type t);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ void ModeWindow::SetupUi()
|
|||
tabBar->setStyleSheet("QTabBar::tab { height: " + QString::number(aw->menuBar()->height()) + "px;}");
|
||||
tabBar->setTabsClosable(true);
|
||||
cornerWidget->layout()->addWidget(tabBar);
|
||||
connect(tabBar, &QTabBar::tabBarDoubleClicked, this, [=](int index) {
|
||||
renameMode(index);
|
||||
});
|
||||
|
||||
auto bAdd = new QPushButton();
|
||||
QIcon icon;
|
||||
|
|
@ -94,6 +97,11 @@ void ModeWindow::SetupUi()
|
|||
menu->addSeparator();
|
||||
auto submenuAdd = new QMenu("Create new");
|
||||
menu->addMenu(submenuAdd);
|
||||
auto rename = new QAction("Rename active mode");
|
||||
connect(rename, &QAction::triggered, this, [=](){
|
||||
renameMode(handler->getCurrentIndex());
|
||||
});
|
||||
menu->addAction(rename);
|
||||
|
||||
auto mAdd = new QMenu();
|
||||
for(unsigned int i=0;i<(int) Mode::Type::Last;i++) {
|
||||
|
|
@ -180,3 +188,19 @@ void ModeWindow::CurrentModeChanged(int modeIndex)
|
|||
}
|
||||
menuActions[modeIndex]->setChecked(true);
|
||||
}
|
||||
|
||||
void ModeWindow::renameMode(int modeIndex)
|
||||
{
|
||||
auto mode = handler->getMode(modeIndex);
|
||||
auto newName = QInputDialog::getText(this, "Rename", "Enter new name for mode \""+mode->getName()+"\":");
|
||||
if(newName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if(handler->nameAllowed(newName, modeIndex)) {
|
||||
mode->setName(newName);
|
||||
tabBar->setTabText(modeIndex, newName);
|
||||
menu->actions()[modeIndex]->setText(newName);
|
||||
} else {
|
||||
InformationBox::ShowError("Error", "Unable to set name. Mode names must be unique.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ private slots:
|
|||
void ModeCreated(int modeIndex);
|
||||
void ModeClosed(int modeIndex);
|
||||
void CurrentModeChanged(int modeIndex);
|
||||
void renameMode(int modeIndex);
|
||||
};
|
||||
|
||||
#endif // MODEWINDOW_H
|
||||
|
|
|
|||
|
|
@ -110,6 +110,18 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||
ui->GraphsSweepHidePercent->setPrecision(3);
|
||||
ui->GraphsSweepHidePercent->setUnit("%");
|
||||
|
||||
auto layout = static_cast<QGridLayout*>(ui->GraphAxisLimitGroup->layout());
|
||||
for(unsigned int i=(int) YAxis::Type::Disabled + 1;i<(int) YAxis::Type::Last;i++) {
|
||||
auto type = (YAxis::Type) i;
|
||||
layout->addWidget(new QLabel(YAxis::TypeToName(type)), i, 0);
|
||||
auto minEntry = new SIUnitEdit(YAxis::Unit(type), YAxis::Prefixes(type), 5);
|
||||
layout->addWidget(minEntry, i, 1);
|
||||
graphAxisLimitsMinEntries[type] = minEntry;
|
||||
auto maxEntry = new SIUnitEdit(YAxis::Unit(type), YAxis::Prefixes(type), 5);
|
||||
layout->addWidget(maxEntry, i, 2);
|
||||
graphAxisLimitsMaxEntries[type] = maxEntry;
|
||||
}
|
||||
|
||||
// General page
|
||||
if(p->TCPoverride) {
|
||||
ui->SCPIServerPort->setEnabled(false);
|
||||
|
|
@ -183,10 +195,12 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||
// apply GUI state to settings
|
||||
updateFromGUI();
|
||||
accept();
|
||||
emit p->updated();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, [=](){
|
||||
// apply GUI state to settings
|
||||
updateFromGUI();
|
||||
emit p->updated();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, [=](){
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Save preferences", "", "LibreVNA preferences files (*.vnapref)", nullptr, Preferences::QFileDialogOptions());
|
||||
|
|
@ -211,6 +225,7 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||
file.close();
|
||||
p->fromJSON(j);
|
||||
setInitialGUIState();
|
||||
emit p->updated();
|
||||
}
|
||||
});
|
||||
connect(ui->AcquisitionLimitTDRCheckbox, &QCheckBox::toggled, [=](bool enabled){
|
||||
|
|
@ -280,6 +295,7 @@ void PreferencesDialog::setInitialGUIState()
|
|||
ui->GraphsLimitIndication->setCurrentIndex((int) p->Graphs.limitIndication);
|
||||
ui->GraphsLimitNaNpasses->setCurrentIndex(p->Graphs.limitNaNpasses ? 1 : 0);
|
||||
ui->GraphsLineWidth->setValue(p->Graphs.lineWidth);
|
||||
ui->GraphsFontSizeTitle->setValue(p->Graphs.fontSizeTitle);
|
||||
ui->GraphsFontSizeAxis->setValue(p->Graphs.fontSizeAxis);
|
||||
ui->GraphsFontSizeCursorOverlay->setValue(p->Graphs.fontSizeCursorOverlay);
|
||||
ui->GraphsFontSizeMarkerData->setValue(p->Graphs.fontSizeMarkerData);
|
||||
|
|
@ -292,9 +308,13 @@ void PreferencesDialog::setInitialGUIState()
|
|||
ui->GraphsSweepHide->setChecked(p->Graphs.SweepIndicator.hide);
|
||||
ui->GraphsSweepHidePercent->setValue(p->Graphs.SweepIndicator.hidePercent);
|
||||
ui->graphsEnableMasterTicksForYAxis->setChecked(p->Graphs.enableMasterTicksForYAxis);
|
||||
for(unsigned int i=(int) YAxis::Type::Disabled + 1;i<(int) YAxis::Type::Last;i++) {
|
||||
auto type = (YAxis::Type) i;
|
||||
graphAxisLimitsMinEntries[type]->setValue(p->Graphs.defaultAxisLimits.min[i]);
|
||||
graphAxisLimitsMaxEntries[type]->setValue(p->Graphs.defaultAxisLimits.max[i]);
|
||||
}
|
||||
|
||||
ui->MarkerShowMarkerData->setChecked(p->Marker.defaultBehavior.showDataOnGraphs);
|
||||
|
||||
ui->MarkerShowdB->setChecked(p->Marker.defaultBehavior.showdB);
|
||||
ui->MarkerShowdBm->setChecked(p->Marker.defaultBehavior.showdBm);
|
||||
ui->MarkerShowdBUv->setChecked(p->Marker.defaultBehavior.showdBuV);
|
||||
|
|
@ -322,6 +342,7 @@ void PreferencesDialog::setInitialGUIState()
|
|||
ui->MarkerInterpolate->setCurrentIndex(p->Marker.interpolatePoints ? 1 : 0);
|
||||
ui->MarkerSortOrder->setCurrentIndex((int) p->Marker.sortOrder);
|
||||
ui->MarkerSymbolStyle->setCurrentIndex((int) p->Marker.symbolStyle);
|
||||
ui->MarkerClipToYAxis->setChecked(p->Marker.clipToYAxis);
|
||||
|
||||
ui->SCPIServerEnabled->setChecked(p->SCPIServer.enabled);
|
||||
ui->SCPIServerPort->setValue(p->SCPIServer.port);
|
||||
|
|
@ -396,6 +417,7 @@ void PreferencesDialog::updateFromGUI()
|
|||
p->Graphs.limitIndication = (GraphLimitIndication) ui->GraphsLimitIndication->currentIndex();
|
||||
p->Graphs.limitNaNpasses = ui->GraphsLimitNaNpasses->currentIndex() == 1;
|
||||
p->Graphs.lineWidth = ui->GraphsLineWidth->value();
|
||||
p->Graphs.fontSizeTitle = ui->GraphsFontSizeTitle->value();
|
||||
p->Graphs.fontSizeAxis = ui->GraphsFontSizeAxis->value();
|
||||
p->Graphs.fontSizeCursorOverlay = ui->GraphsFontSizeCursorOverlay->value();
|
||||
p->Graphs.fontSizeMarkerData = ui->GraphsFontSizeMarkerData->value();
|
||||
|
|
@ -408,6 +430,11 @@ void PreferencesDialog::updateFromGUI()
|
|||
p->Graphs.SweepIndicator.hide = ui->GraphsSweepHide->isChecked();
|
||||
p->Graphs.SweepIndicator.hidePercent = ui->GraphsSweepHidePercent->value();
|
||||
p->Graphs.enableMasterTicksForYAxis = ui->graphsEnableMasterTicksForYAxis->isChecked();
|
||||
for(unsigned int i=(int) YAxis::Type::Disabled + 1;i<(int) YAxis::Type::Last;i++) {
|
||||
auto type = (YAxis::Type) i;
|
||||
p->Graphs.defaultAxisLimits.min[i] = graphAxisLimitsMinEntries[type]->value();
|
||||
p->Graphs.defaultAxisLimits.max[i] = graphAxisLimitsMaxEntries[type]->value();
|
||||
}
|
||||
|
||||
p->Marker.defaultBehavior.showDataOnGraphs = ui->MarkerShowMarkerData->isChecked();
|
||||
p->Marker.defaultBehavior.showdB = ui->MarkerShowdB->isChecked();
|
||||
|
|
@ -437,6 +464,7 @@ void PreferencesDialog::updateFromGUI()
|
|||
p->Marker.interpolatePoints = ui->MarkerInterpolate->currentIndex() == 1;
|
||||
p->Marker.sortOrder = (MarkerSortOrder) ui->MarkerSortOrder->currentIndex();
|
||||
p->Marker.symbolStyle = (MarkerSymbolStyle) ui->MarkerSymbolStyle->currentIndex();
|
||||
p->Marker.clipToYAxis = ui->MarkerClipToYAxis->isChecked();
|
||||
|
||||
p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked();
|
||||
p->SCPIServer.port = ui->SCPIServerPort->value();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "Util/qpointervariant.h"
|
||||
#include "savable.h"
|
||||
#include "Traces/traceaxis.h"
|
||||
#include "CustomWidgets/siunitedit.h"
|
||||
|
||||
#include "Device/LibreVNA/Compound/compounddevice.h"
|
||||
|
||||
|
|
@ -44,7 +46,8 @@ enum MarkerSymbolStyle {
|
|||
Q_DECLARE_METATYPE(MarkerSymbolStyle);
|
||||
|
||||
|
||||
class Preferences : public Savable {
|
||||
class Preferences : public QObject, public Savable {
|
||||
Q_OBJECT
|
||||
friend class PreferencesDialog;
|
||||
public:
|
||||
static Preferences& getInstance() {
|
||||
|
|
@ -133,6 +136,7 @@ public:
|
|||
bool limitNaNpasses;
|
||||
|
||||
double lineWidth;
|
||||
int fontSizeTitle;
|
||||
int fontSizeAxis;
|
||||
int fontSizeMarkerData;
|
||||
int fontSizeTraceNames;
|
||||
|
|
@ -155,6 +159,11 @@ public:
|
|||
QString transmission;
|
||||
QString reflection;
|
||||
} defaultGraphs;
|
||||
|
||||
struct {
|
||||
double min[(int) YAxis::Type::Last];
|
||||
double max[(int) YAxis::Type::Last];
|
||||
} defaultAxisLimits;
|
||||
} Graphs;
|
||||
struct {
|
||||
struct {
|
||||
|
|
@ -165,6 +174,7 @@ public:
|
|||
bool interpolatePoints;
|
||||
MarkerSortOrder sortOrder;
|
||||
MarkerSymbolStyle symbolStyle;
|
||||
bool clipToYAxis;
|
||||
} Marker;
|
||||
struct {
|
||||
bool enabled;
|
||||
|
|
@ -206,6 +216,9 @@ public:
|
|||
bool set(QString name, QVariant value);
|
||||
QVariant get(QString name);
|
||||
|
||||
signals:
|
||||
void updated();
|
||||
|
||||
private:
|
||||
Preferences() :
|
||||
TCPoverride(false) {}
|
||||
|
|
@ -262,6 +275,7 @@ private:
|
|||
{&Graphs.limitIndication, "Graphs.limitIndication", GraphLimitIndication::PassFailText},
|
||||
{&Graphs.limitNaNpasses, "Graphs.limitNaNpasses", false},
|
||||
{&Graphs.lineWidth, "Graphs.lineWidth", 1.0},
|
||||
{&Graphs.fontSizeTitle, "Graphs.fontSizeTitle", 18},
|
||||
{&Graphs.fontSizeAxis, "Graphs.fontSizeAxis", 10},
|
||||
{&Graphs.fontSizeCursorOverlay, "Graphs.fontSizeCursorOverlay", 12},
|
||||
{&Graphs.fontSizeMarkerData, "Graphs.fontSizeMarkerData", 12},
|
||||
|
|
@ -276,6 +290,46 @@ private:
|
|||
{&Graphs.SweepIndicator.hidePercent, "Graphs.SweepIndicator.hidePercent", 3.0},
|
||||
{&Graphs.defaultGraphs.transmission, "Graphs.defaultGraphs.transmission", "XY Plot"},
|
||||
{&Graphs.defaultGraphs.reflection, "Graphs.defaultGraphs.reflection", "Smith Chart"},
|
||||
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Magnitude], "Graphs.defaultAxisLimits.Magnitude.max", 20.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Magnitude], "Graphs.defaultAxisLimits.Magnitude.min", -120.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::MagnitudedBuV], "Graphs.defaultAxisLimits.MagnitudedBuV.max", 128.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::MagnitudedBuV], "Graphs.defaultAxisLimits.MagnitudedBuV.min", -13.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::MagnitudeLinear], "Graphs.defaultAxisLimits.MagnitudeLinear.max", 1.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::MagnitudeLinear], "Graphs.defaultAxisLimits.MagnitudeLinear.min", 0.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Phase], "Graphs.defaultAxisLimits.Phase.max",180.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Phase], "Graphs.defaultAxisLimits.Phase.min", -180.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::UnwrappedPhase], "Graphs.defaultAxisLimits.UnwrappedPhase.max", 0.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::UnwrappedPhase], "Graphs.defaultAxisLimits.UnwrappedPhase.min", -360.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::VSWR], "Graphs.defaultAxisLimits.VSWR.max", 10.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::VSWR], "Graphs.defaultAxisLimits.VSWR.min", 1.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Real], "Graphs.defaultAxisLimits.Real.max", 1.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Real], "Graphs.defaultAxisLimits.Real.min", -1.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Imaginary], "Graphs.defaultAxisLimits.Imaginary.max", 1.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Imaginary], "Graphs.defaultAxisLimits.Imaginary.min", -1.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::AbsImpedance], "Graphs.defaultAxisLimits.AbsImpedance.max", 100.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::AbsImpedance], "Graphs.defaultAxisLimits.AbsImpedance.min", 0.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::SeriesR], "Graphs.defaultAxisLimits.SeriesR.max", 100.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::SeriesR], "Graphs.defaultAxisLimits.SeriesR.min", 0.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Reactance], "Graphs.defaultAxisLimits.Reactance.max", 100.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Reactance], "Graphs.defaultAxisLimits.Reactance.min", 0.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Capacitance], "Graphs.defaultAxisLimits.Capacitance.max", 10e-6},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Capacitance], "Graphs.defaultAxisLimits.Capacitance.min", 0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Inductance], "Graphs.defaultAxisLimits.Inductance.max", 1e-3},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Inductance], "Graphs.defaultAxisLimits.Inductance.min", 0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::QualityFactor], "Graphs.defaultAxisLimits.QualityFactor.max", 100.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::QualityFactor], "Graphs.defaultAxisLimits.QualityFactor.min", 0.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::GroupDelay], "Graphs.defaultAxisLimits.GroupDelay.max", 1e-6},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::GroupDelay], "Graphs.defaultAxisLimits.GroupDelay.min", 0.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::ImpulseReal], "Graphs.defaultAxisLimits.ImpulseReal.max", 1.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::ImpulseReal], "Graphs.defaultAxisLimits.ImpulseReal.min", -1.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::ImpulseMag], "Graphs.defaultAxisLimits.ImpulseMag.max", 0.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::ImpulseMag], "Graphs.defaultAxisLimits.ImpulseMag.min", -100.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Step], "Graphs.defaultAxisLimits.Step.max", 1.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Step], "Graphs.defaultAxisLimits.Step.min", -1.0},
|
||||
{&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Impedance], "Graphs.defaultAxisLimits.Impedance.max", 100.0},
|
||||
{&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Impedance], "Graphs.defaultAxisLimits.Impedance.min", 0.0},
|
||||
|
||||
{&Marker.defaultBehavior.showDataOnGraphs, "Marker.defaultBehavior.ShowDataOnGraphs", true},
|
||||
{&Marker.defaultBehavior.showdB, "Marker.defaultBehavior.showdB", true},
|
||||
{&Marker.defaultBehavior.showdBm, "Marker.defaultBehavior.showdBm", true},
|
||||
|
|
@ -303,7 +357,8 @@ private:
|
|||
{&Marker.defaultBehavior.showMaxDeltaPos, "Marker.defaultBehavior.showMaxDeltaPos", true},
|
||||
{&Marker.interpolatePoints, "Marker.interpolatePoints", false},
|
||||
{&Marker.sortOrder, "Marker.sortOrder", MarkerSortOrder::PrefMarkerSortXCoord},
|
||||
{&Marker.symbolStyle, "Marker.symbolStyle", MarkerSymbolStyle::EmptyNumberAbove},
|
||||
{&Marker.symbolStyle, "Marker.symbolStyle", MarkerSymbolStyle::FilledNumberAbove},
|
||||
{&Marker.clipToYAxis, "Marker.clipToYAxis", true},
|
||||
{&SCPIServer.enabled, "SCPIServer.enabled", true},
|
||||
{&SCPIServer.port, "SCPIServer.port", 19542},
|
||||
{&StreamingServers.VNARawData.enabled, "StreamingServers.VNARawData.enabled", false},
|
||||
|
|
@ -339,6 +394,8 @@ private:
|
|||
void updateFromGUI();
|
||||
Ui::PreferencesDialog *ui;
|
||||
Preferences *p;
|
||||
std::map<YAxis::Type, SIUnitEdit*> graphAxisLimitsMaxEntries;
|
||||
std::map<YAxis::Type, SIUnitEdit*> graphAxisLimitsMinEntries;
|
||||
};
|
||||
|
||||
#endif // PREFERENCESDIALOG_H
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="Startup">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
|
|
@ -112,8 +112,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>683</width>
|
||||
<height>928</height>
|
||||
<width>522</width>
|
||||
<height>945</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
|
|
@ -955,7 +955,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>683</width>
|
||||
<height>1118</height>
|
||||
<height>1217</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_22">
|
||||
|
|
@ -1066,62 +1066,76 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_39">
|
||||
<property name="text">
|
||||
<string>Font (axes):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="GraphsFontSizeAxis">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="GraphsFontSizeTraceNames">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="GraphsFontSizeMarkerData">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="GraphsFontSizeCursorOverlay">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_40">
|
||||
<property name="text">
|
||||
<string>Font (trace names):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_41">
|
||||
<property name="text">
|
||||
<string>Font (marker data):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_42">
|
||||
<property name="text">
|
||||
<string>Font (cursor overlay):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_68">
|
||||
<property name="text">
|
||||
<string>Font (title):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="GraphsFontSizeTitle">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -1443,6 +1457,36 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="GraphAxisLimitGroup">
|
||||
<property name="title">
|
||||
<string>Default Y Axis limits</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_66">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:700;">Default Maximum Limit</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_65">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:700;">Axis Type</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_67">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:700;">Default Minimum Limit</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
|
|
@ -1476,8 +1520,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>683</width>
|
||||
<height>605</height>
|
||||
<width>602</width>
|
||||
<height>628</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
|
|
@ -1787,6 +1831,20 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_64">
|
||||
<property name="text">
|
||||
<string>Show out-of-range marker at top/bottom:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="MarkerClipToYAxis">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
|
@ -1822,8 +1880,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>697</width>
|
||||
<height>563</height>
|
||||
<width>168</width>
|
||||
<height>127</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
|
|
@ -2105,8 +2163,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>697</width>
|
||||
<height>563</height>
|
||||
<width>258</width>
|
||||
<height>241</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_19">
|
||||
|
|
|
|||
BIN
Software/PC_Application/LibreVNA-GUI/resources/librevna.icns
Normal file
BIN
Software/PC_Application/LibreVNA-GUI/resources/librevna.icns
Normal file
Binary file not shown.
|
|
@ -20,12 +20,16 @@ StreamingServer::StreamingServer(int port)
|
|||
});
|
||||
}
|
||||
|
||||
void StreamingServer::addData(const DeviceDriver::VNAMeasurement &m)
|
||||
void StreamingServer::addData(const DeviceDriver::VNAMeasurement &m, bool is_zerospan)
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["pointNum"] = m.pointNum;
|
||||
j["frequency"] = m.frequency;
|
||||
j["dBm"] = m.dBm;
|
||||
if(is_zerospan) {
|
||||
j["time"] = m.us * 0.000001;
|
||||
} else {
|
||||
j["frequency"] = m.frequency;
|
||||
j["dBm"] = m.dBm;
|
||||
}
|
||||
j["Z0"] = m.Z0;
|
||||
nlohmann::json jp;
|
||||
for(auto const &p : m.measurements) {
|
||||
|
|
@ -41,11 +45,15 @@ void StreamingServer::addData(const DeviceDriver::VNAMeasurement &m)
|
|||
}
|
||||
}
|
||||
|
||||
void StreamingServer::addData(const DeviceDriver::SAMeasurement &m)
|
||||
void StreamingServer::addData(const DeviceDriver::SAMeasurement &m, bool is_zerospan)
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["pointNum"] = m.pointNum;
|
||||
j["frequency"] = m.frequency;
|
||||
if(is_zerospan) {
|
||||
j["time"] = m.us * 0.000001;
|
||||
} else {
|
||||
j["frequency"] = m.frequency;
|
||||
}
|
||||
nlohmann::json jp;
|
||||
for(auto const &p : m.measurements) {
|
||||
jp[p.first.toStdString()] = p.second;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ class StreamingServer : public QObject
|
|||
public:
|
||||
StreamingServer(int port);
|
||||
|
||||
void addData(const DeviceDriver::VNAMeasurement &m);
|
||||
void addData(const DeviceDriver::SAMeasurement &m);
|
||||
void addData(const DeviceDriver::VNAMeasurement &m, bool is_zerospan);
|
||||
void addData(const DeviceDriver::SAMeasurement &m, bool is_zerospan);
|
||||
|
||||
int getPort() {return port;}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue