mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-06 15:04:11 +00:00
Min/Max/Delta markers
This commit is contained in:
parent
b5cd6e0072
commit
49fb02be23
16 changed files with 351 additions and 45 deletions
|
|
@ -1,12 +1,22 @@
|
|||
#include "tracemarker.h"
|
||||
#include <QPainter>
|
||||
#include "CustomWidgets/siunitedit.h"
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
#include <QDebug>
|
||||
#include "tracemarkermodel.h"
|
||||
#include "unit.h"
|
||||
|
||||
TraceMarker::TraceMarker(int number)
|
||||
TraceMarker::TraceMarker(TraceMarkerModel *model, int number)
|
||||
: editingFrequeny(false),
|
||||
model(model),
|
||||
parentTrace(nullptr),
|
||||
frequency(1000000000),
|
||||
number(number),
|
||||
data(0)
|
||||
data(0),
|
||||
type(Type::Manual),
|
||||
delta(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -35,6 +45,7 @@ void TraceMarker::assignTrace(Trace *t)
|
|||
constrainFrequency();
|
||||
updateSymbol();
|
||||
parentTrace->addMarker(this);
|
||||
update();
|
||||
}
|
||||
|
||||
Trace *TraceMarker::trace()
|
||||
|
|
@ -44,9 +55,26 @@ Trace *TraceMarker::trace()
|
|||
|
||||
QString TraceMarker::readableData()
|
||||
{
|
||||
auto db = 20*log10(abs(data));
|
||||
auto phase = arg(data);
|
||||
return QString::number(db, 'g', 4) + "db@" + QString::number(phase*180/M_PI, 'g', 4);
|
||||
switch(type) {
|
||||
case Type::Manual:
|
||||
case Type::Maximum:
|
||||
case Type::Minimum: {
|
||||
auto db = 20*log10(abs(data));
|
||||
auto phase = arg(data);
|
||||
return QString::number(db, 'g', 4) + "db@" + QString::number(phase*180/M_PI, 'g', 4);
|
||||
}
|
||||
case Type::Delta:
|
||||
if(!delta) {
|
||||
return "Invalid delta marker";
|
||||
} else {
|
||||
// calculate difference between markers
|
||||
auto freqDiff = frequency - delta->frequency;
|
||||
auto valueDiff = data / delta->data;
|
||||
auto db = 20*log10(abs(valueDiff));
|
||||
auto phase = arg(valueDiff);
|
||||
return Unit::ToString(freqDiff, "Hz", " kMG") + " / " + QString::number(db, 'g', 4) + "db@" + QString::number(phase*180/M_PI, 'g', 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TraceMarker::setFrequency(double freq)
|
||||
|
|
@ -68,7 +96,8 @@ void TraceMarker::traceDataChanged()
|
|||
auto tracedata = parentTrace->getData(frequency);
|
||||
if(tracedata != data) {
|
||||
data = tracedata;
|
||||
emit dataChanged(this);
|
||||
update();
|
||||
emit rawDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +116,7 @@ void TraceMarker::updateSymbol()
|
|||
auto brightness = traceColor.redF() * 0.299 + traceColor.greenF() * 0.587 + traceColor.blueF() * 0.114;
|
||||
p.setPen((brightness > 0.6) ? Qt::black : Qt::white);
|
||||
p.drawText(QRectF(0,0,width, height*2.0/3.0), Qt::AlignCenter, QString::number(number));
|
||||
emit symbolChanged(this);
|
||||
}
|
||||
|
||||
void TraceMarker::constrainFrequency()
|
||||
|
|
@ -101,6 +131,147 @@ void TraceMarker::constrainFrequency()
|
|||
}
|
||||
}
|
||||
|
||||
void TraceMarker::assignDeltaMarker(TraceMarker *m)
|
||||
{
|
||||
if(delta) {
|
||||
disconnect(delta, &TraceMarker::dataChanged, this, &TraceMarker::update);
|
||||
}
|
||||
delta = m;
|
||||
if(delta && delta != this) {
|
||||
// this marker has to be updated when the delta marker changes
|
||||
connect(delta, &TraceMarker::rawDataChanged, this, &TraceMarker::update);
|
||||
connect(delta, &TraceMarker::deleted, [=](){
|
||||
delta = nullptr;
|
||||
update();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TraceMarker::setNumber(int value)
|
||||
{
|
||||
number = value;
|
||||
updateSymbol();
|
||||
}
|
||||
|
||||
QWidget *TraceMarker::getTypeEditor(QAbstractItemDelegate *delegate)
|
||||
{
|
||||
auto c = new QComboBox;
|
||||
for(auto t : getTypes()) {
|
||||
c->addItem(typeToString(t));
|
||||
if(type == t) {
|
||||
// select this item
|
||||
c->setCurrentIndex(c->count() - 1);
|
||||
}
|
||||
}
|
||||
if(type == Type::Delta) {
|
||||
// add additional spinbox to choose corresponding delta marker
|
||||
auto w = new QWidget;
|
||||
auto layout = new QHBoxLayout;
|
||||
layout->addWidget(c);
|
||||
c->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(new QLabel("to"));
|
||||
auto spinbox = new QSpinBox;
|
||||
if(delta) {
|
||||
spinbox->setValue(delta->number);
|
||||
}
|
||||
connect(spinbox, qOverload<int>(&QSpinBox::valueChanged), [=](int newval){
|
||||
bool found = false;
|
||||
for(auto m : model->getMarkers()) {
|
||||
if(m->number == newval) {
|
||||
assignDeltaMarker(m);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
assignDeltaMarker(nullptr);
|
||||
}
|
||||
update();
|
||||
});
|
||||
spinbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
layout->addWidget(spinbox);
|
||||
w->setLayout(layout);
|
||||
c->setObjectName("Type");
|
||||
if(delegate){
|
||||
connect(c, qOverload<int>(&QComboBox::currentIndexChanged), [=](int) {
|
||||
emit delegate->commitData(w);
|
||||
});
|
||||
}
|
||||
return w;
|
||||
} else {
|
||||
// no delta marker, simply return the combobox
|
||||
connect(c, qOverload<int>(&QComboBox::currentIndexChanged), [=](int) {
|
||||
emit delegate->commitData(c);
|
||||
});
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
void TraceMarker::updateTypeFromEditor(QWidget *w)
|
||||
{
|
||||
QComboBox *c;
|
||||
if(type == Type::Delta) {
|
||||
c = w->findChild<QComboBox*>("Type");
|
||||
} else {
|
||||
c = (QComboBox*) w;
|
||||
}
|
||||
for(auto t : getTypes()) {
|
||||
if(c->currentText() == typeToString(t)) {
|
||||
if(type != t) {
|
||||
type = t;
|
||||
if(type == Type::Delta && !delta) {
|
||||
// invalid delta marker assigned, attempt to find a matching marker
|
||||
for(int pass = 0;pass < 3;pass++) {
|
||||
for(auto m : model->getMarkers()) {
|
||||
if(pass == 0 && m->parentTrace != parentTrace) {
|
||||
// ignore markers on different traces in first pass
|
||||
continue;
|
||||
}
|
||||
if(pass <= 1 && m == this) {
|
||||
// ignore itself on second pass
|
||||
continue;
|
||||
}
|
||||
|
||||
assignDeltaMarker(m);
|
||||
break;
|
||||
}
|
||||
if(delta) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
emit typeChanged(this);
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SIUnitEdit *TraceMarker::getSettingsEditor()
|
||||
{
|
||||
return new SIUnitEdit("Hz", " kMG");
|
||||
}
|
||||
|
||||
void TraceMarker::update()
|
||||
{
|
||||
switch(type) {
|
||||
case Type::Manual:
|
||||
// nothing to do
|
||||
break;
|
||||
case Type::Maximum:
|
||||
setFrequency(parentTrace->findExtremumFreq(true));
|
||||
break;
|
||||
case Type::Minimum:
|
||||
setFrequency(parentTrace->findExtremumFreq(false));
|
||||
break;
|
||||
}
|
||||
emit dataChanged(this);
|
||||
}
|
||||
|
||||
Trace *TraceMarker::getTrace() const
|
||||
{
|
||||
return parentTrace;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue