Min/Max/Delta markers
This commit is contained in:
parent
b5cd6e0072
commit
49fb02be23
@ -29,6 +29,7 @@ void SIUnitEdit::setValue(double value)
|
|||||||
{
|
{
|
||||||
setValueQuiet(value);
|
setValueQuiet(value);
|
||||||
emit valueChanged(value);
|
emit valueChanged(value);
|
||||||
|
emit valueUpdated(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SIUnitEdit::eventFilter(QObject *, QEvent *event)
|
bool SIUnitEdit::eventFilter(QObject *, QEvent *event)
|
||||||
@ -38,6 +39,7 @@ bool SIUnitEdit::eventFilter(QObject *, QEvent *event)
|
|||||||
if(key == Qt::Key_Escape) {
|
if(key == Qt::Key_Escape) {
|
||||||
// abort editing process and set old value
|
// abort editing process and set old value
|
||||||
setValueQuiet(_value);
|
setValueQuiet(_value);
|
||||||
|
clearFocus();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(key == Qt::Key_Return) {
|
if(key == Qt::Key_Return) {
|
||||||
@ -69,11 +71,11 @@ void SIUnitEdit::setValueQuiet(double value)
|
|||||||
_value = value;
|
_value = value;
|
||||||
clear();
|
clear();
|
||||||
setPlaceholderText(Unit::ToString(value, unit, prefixes, precision));
|
setPlaceholderText(Unit::ToString(value, unit, prefixes, precision));
|
||||||
clearFocus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIUnitEdit::parseNewValue(double factor)
|
void SIUnitEdit::parseNewValue(double factor)
|
||||||
{
|
{
|
||||||
double v = text().toDouble() * factor;
|
double v = text().toDouble() * factor;
|
||||||
setValue(v);
|
setValue(v);
|
||||||
|
clearFocus();
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ public slots:
|
|||||||
void setValueQuiet(double value);
|
void setValueQuiet(double value);
|
||||||
signals:
|
signals:
|
||||||
void valueChanged(double newvalue);
|
void valueChanged(double newvalue);
|
||||||
|
void valueUpdated(QWidget *w);
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||||
private:
|
private:
|
||||||
|
@ -226,6 +226,9 @@ void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
|
|||||||
d = average.process(d);
|
d = average.process(d);
|
||||||
traceModel.addSAData(d);
|
traceModel.addSAData(d);
|
||||||
emit dataChanged();
|
emit dataChanged();
|
||||||
|
if(d.pointNum == settings.pointNum - 1) {
|
||||||
|
markerModel->updateMarkers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpectrumAnalyzer::SettingsChanged()
|
void SpectrumAnalyzer::SettingsChanged()
|
||||||
|
@ -37,7 +37,7 @@ ImpedanceMatchDialog::ImpedanceMatchDialog(TraceMarkerModel &model, TraceMarker
|
|||||||
connect(ui->zGroup, qOverload<int>(&QButtonGroup::buttonClicked), this, &ImpedanceMatchDialog::calculateMatch);
|
connect(ui->zGroup, qOverload<int>(&QButtonGroup::buttonClicked), this, &ImpedanceMatchDialog::calculateMatch);
|
||||||
|
|
||||||
// populate marker options
|
// populate marker options
|
||||||
auto markers = model.getMarker();
|
auto markers = model.getMarkers();
|
||||||
for(auto m : markers) {
|
for(auto m : markers) {
|
||||||
if(!m->trace()->isReflection()) {
|
if(!m->trace()->isReflection()) {
|
||||||
// matching only possible for reflections
|
// matching only possible for reflections
|
||||||
|
@ -8,8 +8,9 @@ MarkerWidget::MarkerWidget(TraceMarkerModel &model, QWidget *parent) :
|
|||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->tableView->setModel(&model);
|
ui->tableView->setModel(&model);
|
||||||
ui->tableView->setItemDelegateForColumn(TraceMarkerModel::ColIndexTrace, new TraceChooserDelegate);
|
ui->tableView->setItemDelegateForColumn(TraceMarkerModel::ColIndexTrace, new MarkerTraceDelegate);
|
||||||
ui->tableView->setItemDelegateForColumn(TraceMarkerModel::ColIndexFreq, new TraceFrequencyDelegate);
|
ui->tableView->setItemDelegateForColumn(TraceMarkerModel::ColIndexType, new MarkerTypeDelegate);
|
||||||
|
ui->tableView->setItemDelegateForColumn(TraceMarkerModel::ColIndexFreq, new MarkerFrequencyDelegate);
|
||||||
|
|
||||||
connect(&model.getModel(), &TraceModel::traceAdded, this, &MarkerWidget::updatePersistentEditors);
|
connect(&model.getModel(), &TraceModel::traceAdded, this, &MarkerWidget::updatePersistentEditors);
|
||||||
connect(&model.getModel(), &TraceModel::traceRemoved, this, &MarkerWidget::updatePersistentEditors);
|
connect(&model.getModel(), &TraceModel::traceRemoved, this, &MarkerWidget::updatePersistentEditors);
|
||||||
@ -28,15 +29,19 @@ void MarkerWidget::on_bDelete_clicked()
|
|||||||
void MarkerWidget::on_bAdd_clicked()
|
void MarkerWidget::on_bAdd_clicked()
|
||||||
{
|
{
|
||||||
auto marker = model.createDefaultMarker();
|
auto marker = model.createDefaultMarker();
|
||||||
|
connect(marker, &TraceMarker::typeChanged, this, &MarkerWidget::updatePersistentEditors);
|
||||||
model.addMarker(marker);
|
model.addMarker(marker);
|
||||||
updatePersistentEditors();
|
updatePersistentEditors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarkerWidget::updatePersistentEditors(Trace *)
|
void MarkerWidget::updatePersistentEditors()
|
||||||
{
|
{
|
||||||
for(int i=0;i<model.rowCount();i++) {
|
for(int i=0;i<model.rowCount();i++) {
|
||||||
auto index = model.index(i, TraceMarkerModel::ColIndexTrace);
|
auto columns = {TraceMarkerModel::ColIndexTrace, TraceMarkerModel::ColIndexType};
|
||||||
|
for(auto c : columns) {
|
||||||
|
auto index = model.index(i, c);
|
||||||
ui->tableView->closePersistentEditor(index);
|
ui->tableView->closePersistentEditor(index);
|
||||||
ui->tableView->openPersistentEditor(index);
|
ui->tableView->openPersistentEditor(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -19,7 +19,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void on_bDelete_clicked();
|
void on_bDelete_clicked();
|
||||||
void on_bAdd_clicked();
|
void on_bAdd_clicked();
|
||||||
void updatePersistentEditors(Trace *dummy = nullptr);
|
void updatePersistentEditors();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MarkerWidget *ui;
|
Ui::MarkerWidget *ui;
|
||||||
|
@ -201,6 +201,21 @@ bool Trace::isReflection()
|
|||||||
return reflection;
|
return reflection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Trace::findExtremumFreq(bool max)
|
||||||
|
{
|
||||||
|
double compare = max ? numeric_limits<double>::min() : numeric_limits<double>::max();
|
||||||
|
double freq = 0.0;
|
||||||
|
for(auto d : _data) {
|
||||||
|
double amplitude = abs(d.S);
|
||||||
|
if((max && (amplitude > compare)) || (!max && (amplitude < compare))) {
|
||||||
|
// higher/lower extremum found
|
||||||
|
compare = amplitude;
|
||||||
|
freq = d.frequency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
QString Trace::getTouchstoneFilename() const
|
QString Trace::getTouchstoneFilename() const
|
||||||
{
|
{
|
||||||
return touchstoneFilename;
|
return touchstoneFilename;
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
unsigned int size() { return _data.size(); }
|
unsigned int size() { return _data.size(); }
|
||||||
double minFreq() { return _data.front().frequency; };
|
double minFreq() { return _data.front().frequency; };
|
||||||
double maxFreq() { return _data.back().frequency; };
|
double maxFreq() { return _data.back().frequency; };
|
||||||
|
double findExtremumFreq(bool max);
|
||||||
Data sample(unsigned int index) { return _data.at(index); }
|
Data sample(unsigned int index) { return _data.at(index); }
|
||||||
QString getTouchstoneFilename() const;
|
QString getTouchstoneFilename() const;
|
||||||
unsigned int getTouchstoneParameter() const;
|
unsigned int getTouchstoneParameter() const;
|
||||||
|
@ -410,13 +410,11 @@ void TraceBodePlot::markerAdded(TraceMarker *m)
|
|||||||
if(markers.count(m)) {
|
if(markers.count(m)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QwtSymbol *sym=new QwtSymbol;
|
|
||||||
sym->setPixmap(m->getSymbol());
|
|
||||||
sym->setPinPoint(QPointF(m->getSymbol().width()/2, m->getSymbol().height()));
|
|
||||||
auto qwtMarker = new QwtPlotMarker;
|
auto qwtMarker = new QwtPlotMarker;
|
||||||
qwtMarker->setSymbol(sym);
|
|
||||||
connect(m, &TraceMarker::dataChanged, this, &TraceBodePlot::markerDataChanged);
|
|
||||||
markers[m] = qwtMarker;
|
markers[m] = qwtMarker;
|
||||||
|
markerSymbolChanged(m);
|
||||||
|
connect(m, &TraceMarker::symbolChanged, this, &TraceBodePlot::markerSymbolChanged);
|
||||||
|
connect(m, &TraceMarker::dataChanged, this, &TraceBodePlot::markerDataChanged);
|
||||||
markerDataChanged(m);
|
markerDataChanged(m);
|
||||||
qwtMarker->attach(plot);
|
qwtMarker->attach(plot);
|
||||||
triggerReplot();
|
triggerReplot();
|
||||||
@ -424,6 +422,7 @@ void TraceBodePlot::markerAdded(TraceMarker *m)
|
|||||||
|
|
||||||
void TraceBodePlot::markerRemoved(TraceMarker *m)
|
void TraceBodePlot::markerRemoved(TraceMarker *m)
|
||||||
{
|
{
|
||||||
|
disconnect(m, &TraceMarker::symbolChanged, this, &TraceBodePlot::markerSymbolChanged);
|
||||||
disconnect(m, &TraceMarker::dataChanged, this, &TraceBodePlot::markerDataChanged);
|
disconnect(m, &TraceMarker::dataChanged, this, &TraceBodePlot::markerDataChanged);
|
||||||
if(markers.count(m)) {
|
if(markers.count(m)) {
|
||||||
markers[m]->detach();
|
markers[m]->detach();
|
||||||
@ -441,6 +440,20 @@ void TraceBodePlot::markerDataChanged(TraceMarker *m)
|
|||||||
triggerReplot();
|
triggerReplot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TraceBodePlot::markerSymbolChanged(TraceMarker *m)
|
||||||
|
{
|
||||||
|
auto qwtMarker = markers[m];
|
||||||
|
auto old_sym = qwtMarker->symbol();
|
||||||
|
qwtMarker->setSymbol(nullptr);
|
||||||
|
delete old_sym;
|
||||||
|
|
||||||
|
QwtSymbol *sym=new QwtSymbol;
|
||||||
|
sym->setPixmap(m->getSymbol());
|
||||||
|
sym->setPinPoint(QPointF(m->getSymbol().width()/2, m->getSymbol().height()));
|
||||||
|
qwtMarker->setSymbol(sym);
|
||||||
|
triggerReplot();
|
||||||
|
}
|
||||||
|
|
||||||
void TraceBodePlot::clicked(const QPointF pos)
|
void TraceBodePlot::clicked(const QPointF pos)
|
||||||
{
|
{
|
||||||
auto clickPoint = drawPicker->plotToPixel(pos);
|
auto clickPoint = drawPicker->plotToPixel(pos);
|
||||||
|
@ -55,6 +55,7 @@ private slots:
|
|||||||
void markerAdded(TraceMarker *m) override;
|
void markerAdded(TraceMarker *m) override;
|
||||||
void markerRemoved(TraceMarker *m) override;
|
void markerRemoved(TraceMarker *m) override;
|
||||||
void markerDataChanged(TraceMarker *m);
|
void markerDataChanged(TraceMarker *m);
|
||||||
|
void markerSymbolChanged(TraceMarker *m);
|
||||||
|
|
||||||
void clicked(const QPointF pos);
|
void clicked(const QPointF pos);
|
||||||
void moved(const QPointF pos);
|
void moved(const QPointF pos);
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
#include "tracemarker.h"
|
#include "tracemarker.h"
|
||||||
#include <QPainter>
|
#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),
|
: editingFrequeny(false),
|
||||||
|
model(model),
|
||||||
parentTrace(nullptr),
|
parentTrace(nullptr),
|
||||||
frequency(1000000000),
|
frequency(1000000000),
|
||||||
number(number),
|
number(number),
|
||||||
data(0)
|
data(0),
|
||||||
|
type(Type::Manual),
|
||||||
|
delta(nullptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -35,6 +45,7 @@ void TraceMarker::assignTrace(Trace *t)
|
|||||||
constrainFrequency();
|
constrainFrequency();
|
||||||
updateSymbol();
|
updateSymbol();
|
||||||
parentTrace->addMarker(this);
|
parentTrace->addMarker(this);
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace *TraceMarker::trace()
|
Trace *TraceMarker::trace()
|
||||||
@ -44,10 +55,27 @@ Trace *TraceMarker::trace()
|
|||||||
|
|
||||||
QString TraceMarker::readableData()
|
QString TraceMarker::readableData()
|
||||||
{
|
{
|
||||||
|
switch(type) {
|
||||||
|
case Type::Manual:
|
||||||
|
case Type::Maximum:
|
||||||
|
case Type::Minimum: {
|
||||||
auto db = 20*log10(abs(data));
|
auto db = 20*log10(abs(data));
|
||||||
auto phase = arg(data);
|
auto phase = arg(data);
|
||||||
return QString::number(db, 'g', 4) + "db@" + QString::number(phase*180/M_PI, 'g', 4);
|
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)
|
void TraceMarker::setFrequency(double freq)
|
||||||
{
|
{
|
||||||
@ -68,7 +96,8 @@ void TraceMarker::traceDataChanged()
|
|||||||
auto tracedata = parentTrace->getData(frequency);
|
auto tracedata = parentTrace->getData(frequency);
|
||||||
if(tracedata != data) {
|
if(tracedata != data) {
|
||||||
data = tracedata;
|
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;
|
auto brightness = traceColor.redF() * 0.299 + traceColor.greenF() * 0.587 + traceColor.blueF() * 0.114;
|
||||||
p.setPen((brightness > 0.6) ? Qt::black : Qt::white);
|
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));
|
p.drawText(QRectF(0,0,width, height*2.0/3.0), Qt::AlignCenter, QString::number(number));
|
||||||
|
emit symbolChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceMarker::constrainFrequency()
|
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
|
Trace *TraceMarker::getTrace() const
|
||||||
{
|
{
|
||||||
return parentTrace;
|
return parentTrace;
|
||||||
|
@ -4,12 +4,16 @@
|
|||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
#include <QComboBox>
|
||||||
|
#include "CustomWidgets/siunitedit.h"
|
||||||
|
|
||||||
|
class TraceMarkerModel;
|
||||||
|
|
||||||
class TraceMarker : public QObject
|
class TraceMarker : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
public:
|
public:
|
||||||
TraceMarker(int number = 1);
|
TraceMarker(TraceMarkerModel *model, int number = 1);
|
||||||
~TraceMarker();
|
~TraceMarker();
|
||||||
void assignTrace(Trace *t);
|
void assignTrace(Trace *t);
|
||||||
Trace* trace();
|
Trace* trace();
|
||||||
@ -24,23 +28,62 @@ public:
|
|||||||
bool editingFrequeny;
|
bool editingFrequeny;
|
||||||
Trace *getTrace() const;
|
Trace *getTrace() const;
|
||||||
|
|
||||||
|
void setNumber(int value);
|
||||||
|
|
||||||
|
QWidget *getTypeEditor(QAbstractItemDelegate *delegate = nullptr);
|
||||||
|
void updateTypeFromEditor(QWidget *c);
|
||||||
|
|
||||||
|
SIUnitEdit* getSettingsEditor();
|
||||||
|
|
||||||
|
// Updates marker position and data on automatic markers. Should be called whenever the tracedata is complete
|
||||||
|
void update();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setFrequency(double freq);
|
void setFrequency(double freq);
|
||||||
signals:
|
signals:
|
||||||
void deleted(TraceMarker *m);
|
void deleted(TraceMarker *m);
|
||||||
void dataChanged(TraceMarker *m);
|
void dataChanged(TraceMarker *m);
|
||||||
|
void symbolChanged(TraceMarker *m);
|
||||||
|
void typeChanged(TraceMarker *m);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void parentTraceDeleted(Trace *t);
|
void parentTraceDeleted(Trace *t);
|
||||||
void traceDataChanged();
|
void traceDataChanged();
|
||||||
void updateSymbol();
|
void updateSymbol();
|
||||||
|
signals:
|
||||||
|
void rawDataChanged();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
Manual,
|
||||||
|
Maximum,
|
||||||
|
Minimum,
|
||||||
|
Delta,
|
||||||
|
};
|
||||||
|
static std::vector<Type> getTypes() {
|
||||||
|
return {Type::Manual, Type::Maximum, Type::Minimum, Type::Delta};
|
||||||
|
}
|
||||||
|
static QString typeToString(Type t) {
|
||||||
|
switch(t) {
|
||||||
|
case Type::Manual: return "Manual";
|
||||||
|
case Type::Maximum: return "Maximum";
|
||||||
|
case Type::Minimum: return "Minimum";
|
||||||
|
case Type::Delta: return "Delta";
|
||||||
|
default: return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
void constrainFrequency();
|
void constrainFrequency();
|
||||||
|
void assignDeltaMarker(TraceMarker *m);
|
||||||
|
|
||||||
|
TraceMarkerModel *model;
|
||||||
Trace *parentTrace;
|
Trace *parentTrace;
|
||||||
double frequency;
|
double frequency;
|
||||||
int number;
|
int number;
|
||||||
std::complex<double> data;
|
std::complex<double> data;
|
||||||
QPixmap symbol;
|
QPixmap symbol;
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
TraceMarker *delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRACEMARKER_H
|
#endif // TRACEMARKER_H
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include "CustomWidgets/siunitedit.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
TraceMarkerModel::TraceMarkerModel(TraceModel &model, QObject *parent)
|
TraceMarkerModel::TraceMarkerModel(TraceModel &model, QObject *parent)
|
||||||
: QAbstractTableModel(parent),
|
: QAbstractTableModel(parent),
|
||||||
@ -25,7 +27,7 @@ TraceMarker *TraceMarkerModel::createDefaultMarker()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (used);
|
} while (used);
|
||||||
auto marker = new TraceMarker(number);
|
auto marker = new TraceMarker(this, number);
|
||||||
marker->setFrequency(2150000000);
|
marker->setFrequency(2150000000);
|
||||||
marker->assignTrace(model.trace(0));
|
marker->assignTrace(model.trace(0));
|
||||||
return marker;
|
return marker;
|
||||||
@ -65,11 +67,12 @@ void TraceMarkerModel::removeMarker(TraceMarker *m)
|
|||||||
|
|
||||||
void TraceMarkerModel::markerDataChanged(TraceMarker *m)
|
void TraceMarkerModel::markerDataChanged(TraceMarker *m)
|
||||||
{
|
{
|
||||||
|
auto row = find(markers.begin(), markers.end(), m) - markers.begin();
|
||||||
if(m->editingFrequeny) {
|
if(m->editingFrequeny) {
|
||||||
// only update the other columns, do not override editor data
|
// only update the other columns, do not override editor data
|
||||||
emit dataChanged(index(0, ColIndexData), index(markers.size()-1, ColIndexData));
|
emit dataChanged(index(row, ColIndexData), index(row, ColIndexData));
|
||||||
} else {
|
} else {
|
||||||
emit dataChanged(index(0, ColIndexFreq), index(markers.size()-1, ColIndexData));
|
emit dataChanged(index(row, ColIndexFreq), index(row, ColIndexData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +88,7 @@ int TraceMarkerModel::rowCount(const QModelIndex &) const
|
|||||||
|
|
||||||
int TraceMarkerModel::columnCount(const QModelIndex &) const
|
int TraceMarkerModel::columnCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
return 4;
|
return ColIndexLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TraceMarkerModel::data(const QModelIndex &index, int role) const
|
QVariant TraceMarkerModel::data(const QModelIndex &index, int role) const
|
||||||
@ -123,6 +126,7 @@ QVariant TraceMarkerModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
switch(section) {
|
switch(section) {
|
||||||
case ColIndexNumber: return "#"; break;
|
case ColIndexNumber: return "#"; break;
|
||||||
case ColIndexTrace: return "Trace"; break;
|
case ColIndexTrace: return "Trace"; break;
|
||||||
|
case ColIndexType: return "Type"; break;
|
||||||
case ColIndexFreq: return "Frequency"; break;
|
case ColIndexFreq: return "Frequency"; break;
|
||||||
case ColIndexData: return "Data"; break;
|
case ColIndexData: return "Data"; break;
|
||||||
default: return QVariant(); break;
|
default: return QVariant(); break;
|
||||||
@ -139,6 +143,10 @@ bool TraceMarkerModel::setData(const QModelIndex &index, const QVariant &value,
|
|||||||
}
|
}
|
||||||
auto m = markers[index.row()];
|
auto m = markers[index.row()];
|
||||||
switch(index.column()) {
|
switch(index.column()) {
|
||||||
|
case ColIndexNumber: {
|
||||||
|
m->setNumber(value.toInt());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ColIndexTrace: {
|
case ColIndexTrace: {
|
||||||
auto trace = qvariant_cast<Trace*>(value);
|
auto trace = qvariant_cast<Trace*>(value);
|
||||||
m->assignTrace(trace);
|
m->assignTrace(trace);
|
||||||
@ -160,20 +168,21 @@ Qt::ItemFlags TraceMarkerModel::flags(const QModelIndex &index) const
|
|||||||
{
|
{
|
||||||
int flags = Qt::NoItemFlags;
|
int flags = Qt::NoItemFlags;
|
||||||
switch(index.column()) {
|
switch(index.column()) {
|
||||||
case ColIndexNumber: flags |= Qt::ItemIsEnabled; break;
|
case ColIndexNumber: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
|
||||||
case ColIndexTrace: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
|
case ColIndexTrace: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
|
||||||
|
case ColIndexType: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
|
||||||
case ColIndexFreq: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
|
case ColIndexFreq: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
|
||||||
case ColIndexData: flags |= Qt::ItemIsEnabled; break;
|
case ColIndexData: flags |= Qt::ItemIsEnabled; break;
|
||||||
}
|
}
|
||||||
return (Qt::ItemFlags) flags;
|
return (Qt::ItemFlags) flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TraceMarker *> TraceMarkerModel::getMarker()
|
std::vector<TraceMarker *> TraceMarkerModel::getMarkers()
|
||||||
{
|
{
|
||||||
return markers;
|
return markers;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TraceMarker *> TraceMarkerModel::getMarker(Trace *t)
|
std::vector<TraceMarker *> TraceMarkerModel::getMarkers(Trace *t)
|
||||||
{
|
{
|
||||||
std::vector<TraceMarker*> attachedMarkers;
|
std::vector<TraceMarker*> attachedMarkers;
|
||||||
for(auto m : markers) {
|
for(auto m : markers) {
|
||||||
@ -189,7 +198,14 @@ TraceModel &TraceMarkerModel::getModel()
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *TraceChooserDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const
|
void TraceMarkerModel::updateMarkers()
|
||||||
|
{
|
||||||
|
for(auto m : markers) {
|
||||||
|
m->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *MarkerTraceDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
auto model = (TraceMarkerModel*) index.model();
|
auto model = (TraceMarkerModel*) index.model();
|
||||||
auto c = new QComboBox(parent);
|
auto c = new QComboBox(parent);
|
||||||
@ -203,10 +219,10 @@ QWidget *TraceChooserDelegate::createEditor(QWidget *parent, const QStyleOptionV
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceChooserDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
void MarkerTraceDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
auto model = (TraceMarkerModel*) index.model();
|
auto model = (TraceMarkerModel*) index.model();
|
||||||
auto marker = model->getMarker()[index.row()];
|
auto marker = model->getMarkers()[index.row()];
|
||||||
auto c = (QComboBox*) editor;
|
auto c = (QComboBox*) editor;
|
||||||
for(int i=0;i<c->count();i++) {
|
for(int i=0;i<c->count();i++) {
|
||||||
if(qvariant_cast<Trace*>(c->itemData(i)) == marker->trace()) {
|
if(qvariant_cast<Trace*>(c->itemData(i)) == marker->trace()) {
|
||||||
@ -216,25 +232,46 @@ void TraceChooserDelegate::setEditorData(QWidget *editor, const QModelIndex &ind
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceChooserDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
void MarkerTraceDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
auto markerModel = (TraceMarkerModel*) model;
|
auto markerModel = (TraceMarkerModel*) model;
|
||||||
auto c = (QComboBox*) editor;
|
auto c = (QComboBox*) editor;
|
||||||
markerModel->setData(index, c->itemData(c->currentIndex()));
|
markerModel->setData(index, c->itemData(c->currentIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *TraceFrequencyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
QWidget *MarkerFrequencyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
auto model = (TraceMarkerModel*) index.model();
|
auto model = (TraceMarkerModel*) index.model();
|
||||||
auto marker = model->getMarker()[index.row()];
|
auto marker = model->getMarkers()[index.row()];
|
||||||
marker->editingFrequeny = true;
|
marker->editingFrequeny = true;
|
||||||
return QStyledItemDelegate::createEditor(parent, option, index);
|
auto e = marker->getSettingsEditor();
|
||||||
|
e->setParent(parent);
|
||||||
|
connect(e, &SIUnitEdit::valueUpdated, this, &MarkerFrequencyDelegate::commitData);
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceFrequencyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
void MarkerFrequencyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
auto markerModel = (TraceMarkerModel*) model;
|
auto markerModel = (TraceMarkerModel*) model;
|
||||||
auto marker = markerModel->getMarker()[index.row()];
|
auto marker = markerModel->getMarkers()[index.row()];
|
||||||
marker->editingFrequeny = false;
|
marker->editingFrequeny = false;
|
||||||
QStyledItemDelegate::setModelData(editor, model, index);
|
auto si = (SIUnitEdit*) editor;
|
||||||
|
markerModel->setData(index, si->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *MarkerTypeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
auto model = (TraceMarkerModel*) index.model();
|
||||||
|
auto marker = model->getMarkers()[index.row()];
|
||||||
|
auto editor = marker->getTypeEditor(const_cast<MarkerTypeDelegate*>(this));
|
||||||
|
editor->setParent(parent);
|
||||||
|
// connect(editor, &QWidget::focusC)
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkerTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
auto markerModel = (TraceMarkerModel*) model;
|
||||||
|
auto marker = markerModel->getMarkers()[index.row()];
|
||||||
|
marker->updateTypeFromEditor(editor);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "tracemodel.h"
|
#include "tracemodel.h"
|
||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
class TraceChooserDelegate : public QStyledItemDelegate
|
class MarkerTraceDelegate : public QStyledItemDelegate
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||||
@ -15,7 +15,14 @@ class TraceChooserDelegate : public QStyledItemDelegate
|
|||||||
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
|
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TraceFrequencyDelegate : public QStyledItemDelegate
|
class MarkerTypeDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT;
|
||||||
|
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||||
|
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MarkerFrequencyDelegate : public QStyledItemDelegate
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||||
@ -31,8 +38,10 @@ public:
|
|||||||
enum {
|
enum {
|
||||||
ColIndexNumber = 0,
|
ColIndexNumber = 0,
|
||||||
ColIndexTrace = 1,
|
ColIndexTrace = 1,
|
||||||
ColIndexFreq = 2,
|
ColIndexType = 2,
|
||||||
ColIndexData = 3,
|
ColIndexFreq = 3,
|
||||||
|
ColIndexData = 4,
|
||||||
|
ColIndexLast,
|
||||||
};
|
};
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
@ -44,9 +53,10 @@ public:
|
|||||||
|
|
||||||
TraceMarker* createDefaultMarker();
|
TraceMarker* createDefaultMarker();
|
||||||
TraceMarker *marker(int index);
|
TraceMarker *marker(int index);
|
||||||
std::vector<TraceMarker*> getMarker();
|
std::vector<TraceMarker*> getMarkers();
|
||||||
std::vector<TraceMarker*> getMarker(Trace *t);
|
std::vector<TraceMarker*> getMarkers(Trace *t);
|
||||||
TraceModel& getModel();
|
TraceModel& getModel();
|
||||||
|
void updateMarkers();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void addMarker(TraceMarker *t);
|
void addMarker(TraceMarker *t);
|
||||||
|
@ -129,10 +129,13 @@ void TracePlot::triggerReplot()
|
|||||||
void TracePlot::markerAdded(TraceMarker *m)
|
void TracePlot::markerAdded(TraceMarker *m)
|
||||||
{
|
{
|
||||||
connect(m, &TraceMarker::dataChanged, this, &TracePlot::triggerReplot);
|
connect(m, &TraceMarker::dataChanged, this, &TracePlot::triggerReplot);
|
||||||
|
connect(m, &TraceMarker::symbolChanged, this, &TracePlot::triggerReplot);
|
||||||
triggerReplot();
|
triggerReplot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TracePlot::markerRemoved(TraceMarker *)
|
void TracePlot::markerRemoved(TraceMarker *m)
|
||||||
{
|
{
|
||||||
|
disconnect(m, &TraceMarker::dataChanged, this, &TracePlot::triggerReplot);
|
||||||
|
disconnect(m, &TraceMarker::symbolChanged, this, &TracePlot::triggerReplot);
|
||||||
triggerReplot();
|
triggerReplot();
|
||||||
}
|
}
|
||||||
|
@ -504,6 +504,7 @@ void VNA::NewDatapoint(Protocol::Datapoint d)
|
|||||||
emit dataChanged();
|
emit dataChanged();
|
||||||
if(d.pointNum == settings.points - 1) {
|
if(d.pointNum == settings.points - 1) {
|
||||||
UpdateStatusPanel();
|
UpdateStatusPanel();
|
||||||
|
markerModel->updateMarkers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user