diff --git a/Software/PC_Application/LibreVNA-GUI.pro b/Software/PC_Application/LibreVNA-GUI.pro index e3f723d..58cb655 100644 --- a/Software/PC_Application/LibreVNA-GUI.pro +++ b/Software/PC_Application/LibreVNA-GUI.pro @@ -28,6 +28,10 @@ HEADERS += \ Tools/eseries.h \ Tools/impedancematchdialog.h \ Tools/parameters.h \ + Traces/Marker/marker.h \ + Traces/Marker/markergroup.h \ + Traces/Marker/markermodel.h \ + Traces/Marker/markerwidget.h \ Traces/Math/dft.h \ Traces/Math/expression.h \ Traces/Math/medianfilter.h \ @@ -84,14 +88,11 @@ HEADERS += \ Traces/Math/tracemath.h \ Traces/Math/windowfunction.h \ Traces/fftcomplex.h \ - Traces/markerwidget.h \ Traces/sparamtraceselector.h \ Traces/trace.h \ Traces/tracecsvexport.h \ Traces/traceeditdialog.h \ Traces/traceimportdialog.h \ - Traces/tracemarker.h \ - Traces/tracemarkermodel.h \ Traces/tracemodel.h \ Traces/traceplot.h \ Traces/tracesmithchart.h \ @@ -152,6 +153,10 @@ SOURCES += \ Tools/eseries.cpp \ Tools/impedancematchdialog.cpp \ Tools/parameters.cpp \ + Traces/Marker/marker.cpp \ + Traces/Marker/markergroup.cpp \ + Traces/Marker/markermodel.cpp \ + Traces/Marker/markerwidget.cpp \ Traces/Math/dft.cpp \ Traces/Math/expression.cpp \ Traces/Math/medianfilter.cpp \ @@ -197,14 +202,11 @@ SOURCES += \ Traces/Math/tracemath.cpp \ Traces/Math/windowfunction.cpp \ Traces/fftcomplex.cpp \ - Traces/markerwidget.cpp \ Traces/sparamtraceselector.cpp \ Traces/trace.cpp \ Traces/tracecsvexport.cpp \ Traces/traceeditdialog.cpp \ Traces/traceimportdialog.cpp \ - Traces/tracemarker.cpp \ - Traces/tracemarkermodel.cpp \ Traces/tracemodel.cpp \ Traces/traceplot.cpp \ Traces/tracesmithchart.cpp \ @@ -256,6 +258,7 @@ FORMS += \ Device/manualcontroldialog.ui \ Generator/signalgenwidget.ui \ Tools/impedancematchdialog.ui \ + Traces/Marker/markerwidget.ui \ Traces/Math/dftdialog.ui \ Traces/Math/dftexplanationwidget.ui \ Traces/Math/expressiondialog.ui \ @@ -268,7 +271,6 @@ FORMS += \ Traces/Math/timedomaingatingexplanationwidget.ui \ Traces/Math/timegatedialog.ui \ Traces/Math/timegateexplanationwidget.ui \ - Traces/markerwidget.ui \ Traces/smithchartdialog.ui \ Traces/tracecsvexport.ui \ Traces/traceeditdialog.ui \ diff --git a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp index 10fab4c..488fef8 100644 --- a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp +++ b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp @@ -30,7 +30,7 @@ #include "CustomWidgets/tilewidget.h" #include "CustomWidgets/siunitedit.h" #include -#include "Traces/markerwidget.h" +#include "Traces/Marker/markerwidget.h" #include "Tools/impedancematchdialog.h" #include "Calibration/calibrationtracedialog.h" #include "ui_main.h" @@ -232,7 +232,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window) window->addToolBar(tb_trackgen); toolbars.insert(tb_trackgen); - markerModel = new TraceMarkerModel(traceModel, this); + markerModel = new MarkerModel(traceModel, this); auto tracesDock = new QDockWidget("Traces"); traceWidget = new TraceWidgetSA(traceModel, window); diff --git a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h index 0a3a696..1f8e7ac 100644 --- a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h +++ b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h @@ -78,7 +78,7 @@ private: unsigned int averages; TraceModel traceModel; TraceWidget *traceWidget; - TraceMarkerModel *markerModel; + MarkerModel *markerModel; Averaging average; TileWidget *central; diff --git a/Software/PC_Application/Tools/impedancematchdialog.cpp b/Software/PC_Application/Tools/impedancematchdialog.cpp index 9ae154a..a5100bd 100644 --- a/Software/PC_Application/Tools/impedancematchdialog.cpp +++ b/Software/PC_Application/Tools/impedancematchdialog.cpp @@ -7,7 +7,7 @@ using namespace std; constexpr double ImpedanceMatchDialog::Z0; -ImpedanceMatchDialog::ImpedanceMatchDialog(TraceMarkerModel &model, TraceMarker *marker, QWidget *parent) : +ImpedanceMatchDialog::ImpedanceMatchDialog(MarkerModel &model, Marker *marker, QWidget *parent) : QDialog(parent), ui(new Ui::ImpedanceMatchDialog) { @@ -44,7 +44,7 @@ ImpedanceMatchDialog::ImpedanceMatchDialog(TraceMarkerModel &model, TraceMarker // matching only possible for reflections continue; } - ui->cSource->addItem("From Marker "+QString::number(m->getNumber()), QVariant::fromValue(m)); + ui->cSource->addItem("From Marker "+QString::number(m->getNumber()), QVariant::fromValue(m)); if(m == marker) { // select the last index, e.i. the just created marker ui->cSource->setCurrentIndex(ui->cSource->count()-1); @@ -65,7 +65,7 @@ void ImpedanceMatchDialog::on_cSource_currentIndexChanged(int index) ui->zImag->setEnabled(index == 0); ui->zFreq->setEnabled(index == 0); if(index > 0) { - auto m = qvariant_cast(ui->cSource->itemData(index)); + auto m = qvariant_cast(ui->cSource->itemData(index)); ui->rbSeries->setChecked(true); auto data = m->getData(); auto reflection = Z0 * (1.0 + data) / (1.0 - data); diff --git a/Software/PC_Application/Tools/impedancematchdialog.h b/Software/PC_Application/Tools/impedancematchdialog.h index 1c520cb..95f8251 100644 --- a/Software/PC_Application/Tools/impedancematchdialog.h +++ b/Software/PC_Application/Tools/impedancematchdialog.h @@ -2,7 +2,7 @@ #define IMPEDANCEMATCHDIALOG_H #include -#include "Traces/tracemarkermodel.h" +#include "Traces/Marker/markermodel.h" namespace Ui { class ImpedanceMatchDialog; @@ -13,7 +13,7 @@ class ImpedanceMatchDialog : public QDialog Q_OBJECT public: - explicit ImpedanceMatchDialog(TraceMarkerModel &model, TraceMarker *marker = nullptr, QWidget *parent = nullptr); + explicit ImpedanceMatchDialog(MarkerModel &model, Marker *marker = nullptr, QWidget *parent = nullptr); ~ImpedanceMatchDialog(); private slots: diff --git a/Software/PC_Application/Traces/tracemarker.cpp b/Software/PC_Application/Traces/Marker/marker.cpp similarity index 85% rename from Software/PC_Application/Traces/tracemarker.cpp rename to Software/PC_Application/Traces/Marker/marker.cpp index 1cb7a8a..53c40c5 100644 --- a/Software/PC_Application/Traces/tracemarker.cpp +++ b/Software/PC_Application/Traces/Marker/marker.cpp @@ -1,20 +1,21 @@ -#include "tracemarker.h" +#include "marker.h" #include #include "CustomWidgets/siunitedit.h" #include #include #include #include -#include "tracemarkermodel.h" +#include "markermodel.h" #include "unit.h" #include #include #include #include "preferences.h" +#include "markergroup.h" using namespace std; -TraceMarker::TraceMarker(TraceMarkerModel *model, int number, TraceMarker *parent, QString descr) +Marker::Marker(MarkerModel *model, int number, Marker *parent, QString descr) : editingFrequency(false), model(model), parentTrace(nullptr), @@ -29,14 +30,15 @@ TraceMarker::TraceMarker(TraceMarkerModel *model, int number, TraceMarker *paren cutoffAmplitude(-3.0), peakThreshold(-40.0), offset(10000), - formatTable(Format::dBAngle) + formatTable(Format::dBAngle), + group(nullptr) { - connect(this, &TraceMarker::traceChanged, this, &TraceMarker::updateContextmenu); - connect(this, &TraceMarker::typeChanged, this, &TraceMarker::updateContextmenu); + connect(this, &Marker::traceChanged, this, &Marker::updateContextmenu); + connect(this, &Marker::typeChanged, this, &Marker::updateContextmenu); updateContextmenu(); } -TraceMarker::~TraceMarker() +Marker::~Marker() { if(parentTrace) { parentTrace->removeMarker(this); @@ -45,7 +47,7 @@ TraceMarker::~TraceMarker() emit deleted(this); } -void TraceMarker::assignTrace(Trace *t) +void Marker::assignTrace(Trace *t) { bool firstAssignment = false; if(parentTrace) { @@ -64,11 +66,11 @@ void TraceMarker::assignTrace(Trace *t) setType(type); } - connect(parentTrace, &Trace::deleted, this, &TraceMarker::parentTraceDeleted); - connect(parentTrace, &Trace::dataChanged, this, &TraceMarker::traceDataChanged); - connect(parentTrace, &Trace::colorChanged, this, &TraceMarker::updateSymbol); - connect(parentTrace, &Trace::typeChanged, this, &TraceMarker::domainChanged); - connect(parentTrace, &Trace::typeChanged, this, &TraceMarker::checkDeltaMarker); + connect(parentTrace, &Trace::deleted, this, &Marker::parentTraceDeleted); + connect(parentTrace, &Trace::dataChanged, this, &Marker::traceDataChanged); + connect(parentTrace, &Trace::colorChanged, this, &Marker::updateSymbol); + connect(parentTrace, &Trace::typeChanged, this, &Marker::traceTypeChanged); + connect(parentTrace, &Trace::typeChanged, this, &Marker::checkDeltaMarker); constrainPosition(); updateSymbol(); parentTrace->addMarker(this); @@ -95,18 +97,19 @@ void TraceMarker::assignTrace(Trace *t) emit traceChanged(this); } -Trace *TraceMarker::trace() +Trace *Marker::trace() { return parentTrace; } -QString TraceMarker::formatToString(TraceMarker::Format f) +QString Marker::formatToString(Marker::Format f) { switch(f) { case Format::dB: return "dB"; case Format::dBAngle: return "dB + angle"; case Format::RealImag: return "real + imag"; case Format::Impedance: return "Impedance"; + case Format::VSWR: return "VSWR"; case Format::TOI: return "Third order intercept"; case Format::AvgTone: return "Average Tone Level"; case Format::AvgModulationProduct: return "Average Modulation Product Level"; @@ -120,7 +123,7 @@ QString TraceMarker::formatToString(TraceMarker::Format f) return ""; } -TraceMarker::Format TraceMarker::formatFromString(QString s) +Marker::Format Marker::formatFromString(QString s) { for(int i=0;i<(int) Format::Last;i++) { if(s.compare(formatToString((Format) i)) == 0) { @@ -130,7 +133,7 @@ TraceMarker::Format TraceMarker::formatFromString(QString s) return Format::Last; } -std::vector TraceMarker::formats() +std::vector Marker::formats() { std::vector ret; for(int i=0;i<(int) Format::Last;i++) { @@ -139,7 +142,7 @@ std::vector TraceMarker::formats() return ret; } -std::vector TraceMarker::applicableFormats() +std::vector Marker::applicableFormats() { std::vector ret; if(isTimeDomain()) { @@ -171,12 +174,12 @@ std::vector TraceMarker::applicableFormats() if(parentTrace) { if(parentTrace->isReflection()) { ret.push_back(Format::Impedance); + ret.push_back(Format::VSWR); } if(!isnan(parentTrace->getNoise(parentTrace->minX()))) { ret.push_back(Format::Noise); } } - break; case Type::Bandpass: ret.push_back(Format::CenterBandwidth); @@ -203,7 +206,7 @@ std::vector TraceMarker::applicableFormats() return ret; } -QString TraceMarker::readableData(Format f) +QString Marker::readableData(Format f) { if(!parentTrace) { return ""; @@ -293,6 +296,13 @@ QString TraceMarker::readableData(Format f) case Format::dB: return Unit::ToString(Unit::dB(data), "dB", " ", 4); case Format::dBAngle: return Unit::ToString(Unit::dB(data), "dB", " ", 4) + "/"+Unit::ToString(arg(data)*180/M_PI, "°", " ", 4); case Format::RealImag: return Unit::ToString(data.real(), "", " ", 5) + "+"+Unit::ToString(data.imag(), "", " ", 5)+"j"; + case Format::VSWR: + if(abs(data) < 1.0) { + return "VSWR: "+Unit::ToString(((1+abs(data)) / (1-abs(data))), ":1", " ", 5); + } else { + return "VSWR: NaN"; + } + break; case Format::Noise: return Unit::ToString(parentTrace->getNoise(position), "dbm/Hz", " ", 3); case Format::TOI: { auto avgFundamental = (helperMarkers[0]->toDecibel() + helperMarkers[1]->toDecibel()) / 2; @@ -362,7 +372,7 @@ QString TraceMarker::readableData(Format f) return "Invalid"; } -QString TraceMarker::readablePosition() +QString Marker::readablePosition() { auto pos = position; QString ret; @@ -378,7 +388,7 @@ QString TraceMarker::readablePosition() return ret; } -QString TraceMarker::readableSettings() +QString Marker::readableSettings() { if(isTimeDomain()) { switch(type) { @@ -411,7 +421,7 @@ QString TraceMarker::readableSettings() } } -QString TraceMarker::tooltipSettings() +QString Marker::tooltipSettings() { if(isTimeDomain()) { switch(type) { @@ -442,7 +452,7 @@ QString TraceMarker::tooltipSettings() } } -QString TraceMarker::readableType() +QString Marker::readableType() { if(parent) { return description; @@ -451,20 +461,21 @@ QString TraceMarker::readableType() } } -void TraceMarker::setPosition(double pos) +void Marker::setPosition(double pos) { position = pos; constrainPosition(); + emit positionChanged(position); } -void TraceMarker::parentTraceDeleted(Trace *t) +void Marker::parentTraceDeleted(Trace *t) { if(t == parentTrace) { delete this; } } -void TraceMarker::traceDataChanged() +void Marker::traceDataChanged() { complex newdata; if(!parentTrace || parentTrace->numSamples() == 0) { @@ -488,7 +499,7 @@ void TraceMarker::traceDataChanged() } } -void TraceMarker::updateSymbol() +void Marker::updateSymbol() { if(isVisible()) { constexpr int width = 15, height = 15; @@ -510,7 +521,7 @@ void TraceMarker::updateSymbol() emit symbolChanged(this); } -void TraceMarker::checkDeltaMarker() +void Marker::checkDeltaMarker() { if(type != Type::Delta) { // not a delta marker, nothing to do @@ -523,7 +534,7 @@ void TraceMarker::checkDeltaMarker() } } -void TraceMarker::deltaDeleted() +void Marker::deltaDeleted() { // the delta marker of this marker has been deleted, find new match delta = nullptr; @@ -532,7 +543,7 @@ void TraceMarker::deltaDeleted() update(); } -void TraceMarker::updateContextmenu() +void Marker::updateContextmenu() { if(parent) { // do nothing, using contextmenu from parent anyway @@ -600,14 +611,66 @@ void TraceMarker::updateContextmenu() graph->addAction(setFormatAction); } + std::vector applicableGroups; + for(auto g : model->getGroups()) { + if(g->applicable(this)) { + applicableGroups.push_back(g); + } + } + + contextmenu.addSeparator(); + + bool needsSeparator = false; + if((applicableGroups.size() > 0 && group == nullptr) || applicableGroups.size() > 1) { + // there are other groups available than the one the marker might already be assigned to + auto addGroupMenu = new QMenu("Add to linked group"); + auto groupGroup = new QActionGroup(addGroupMenu); + for(auto g : model->getGroups()) { + auto addGroupAction = new QAction(QString::number(g->getNumber())); + groupGroup->addAction(addGroupAction); + addGroupAction->setCheckable(true); + if(g == group) { + // already assigned to this group + addGroupAction->setChecked(true); + } + connect(addGroupAction, &QAction::triggered, [=](bool checked){ + if(checked) { + g->add(this); + } + }); + addGroupMenu->addAction(addGroupAction); + } + contextmenu.addMenu(addGroupMenu); + needsSeparator = true; + } + if(group != nullptr) { + // "remove from group" available + auto removeGroup = new QAction("Remove from linked group"); + connect(removeGroup, &QAction::triggered, [=](){ + group->remove(this); + }); + contextmenu.addAction(removeGroup); + needsSeparator = true; + } + if(needsSeparator) { + contextmenu.addSeparator(); + } + + auto deleteAction = new QAction("Delete"); - connect(deleteAction, &QAction::triggered, this, &TraceMarker::deleteLater); + connect(deleteAction, &QAction::triggered, this, &Marker::deleteLater); contextmenu.addAction(deleteAction); } -std::set TraceMarker::getSupportedTypes() +void Marker::traceTypeChanged() { - set supported; + // domain may have changed + emit domainChanged(this); +} + +std::set Marker::getSupportedTypes() +{ + set supported; if(parentTrace) { if(isTimeDomain()) { // only basic markers in time domain @@ -647,7 +710,7 @@ std::set TraceMarker::getSupportedTypes() return supported; } -void TraceMarker::constrainPosition() +void Marker::constrainPosition() { if(parentTrace) { if(parentTrace->size() > 0) { @@ -661,7 +724,7 @@ void TraceMarker::constrainPosition() } } -void TraceMarker::constrainFormat() +void Marker::constrainFormat() { auto vec = applicableFormats(); // check format @@ -679,9 +742,9 @@ void TraceMarker::constrainFormat() } } -TraceMarker *TraceMarker::bestDeltaCandidate() +Marker *Marker::bestDeltaCandidate() { - TraceMarker *match = nullptr; + Marker *match = nullptr; // invalid delta marker assigned, attempt to find a matching marker for(int pass = 0;pass < 3;pass++) { for(auto m : model->getMarkers()) { @@ -707,26 +770,26 @@ TraceMarker *TraceMarker::bestDeltaCandidate() return match; } -void TraceMarker::assignDeltaMarker(TraceMarker *m) +void Marker::assignDeltaMarker(Marker *m) { if(type != Type::Delta) { // ignore return; } if(delta) { - disconnect(delta, &TraceMarker::dataChanged, this, &TraceMarker::update); + disconnect(delta, &Marker::dataChanged, this, &Marker::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::domainChanged, this, &TraceMarker::checkDeltaMarker); - connect(delta, &TraceMarker::deleted, this, &TraceMarker::deltaDeleted); + connect(delta, &Marker::rawDataChanged, this, &Marker::update); + connect(delta, &Marker::domainChanged, this, &Marker::checkDeltaMarker); + connect(delta, &Marker::deleted, this, &Marker::deltaDeleted); } emit assignedDeltaChanged(this); } -void TraceMarker::deleteHelperMarkers() +void Marker::deleteHelperMarkers() { if(helperMarkers.size() > 0) { emit beginRemoveHelperMarkers(this); @@ -738,7 +801,7 @@ void TraceMarker::deleteHelperMarkers() } } -void TraceMarker::setType(TraceMarker::Type t) +void Marker::setType(Marker::Type t) { // remove any potential helper markers deleteHelperMarkers(); @@ -775,7 +838,7 @@ void TraceMarker::setType(TraceMarker::Type t) } // create helper markers for(auto h : required_helpers) { - auto helper = new TraceMarker(model, number, this, h.description); + auto helper = new Marker(model, number, this, h.description); helper->suffix = h.suffix; helper->assignTrace(parentTrace); helper->setType(h.type); @@ -788,12 +851,12 @@ void TraceMarker::setType(TraceMarker::Type t) update(); } -double TraceMarker::toDecibel() +double Marker::toDecibel() { return Unit::dB(data); } -bool TraceMarker::isVisible() +bool Marker::isVisible() { switch(type) { case Type::Manual: @@ -807,7 +870,7 @@ bool TraceMarker::isVisible() } } -void TraceMarker::setTableFormat(TraceMarker::Format f) +void Marker::setTableFormat(Marker::Format f) { if(formatTable == f) { // already correct format, nothing to do @@ -825,28 +888,42 @@ void TraceMarker::setTableFormat(TraceMarker::Format f) emit dataFormatChanged(this); } -std::set TraceMarker::getGraphDisplayFormats() const +MarkerGroup *Marker::getGroup() const +{ + return group; +} + +void Marker::setGroup(MarkerGroup *value) +{ + group = value; + updateContextmenu(); +} + +std::set Marker::getGraphDisplayFormats() const { return formatGraph; } -TraceMarker::Type TraceMarker::getType() const +Marker::Type Marker::getType() const { return type; } -QString TraceMarker::getSuffix() const +QString Marker::getSuffix() const { return suffix; } -nlohmann::json TraceMarker::toJSON() +nlohmann::json Marker::toJSON() { nlohmann::json j; j["trace"] = parentTrace->toHash(); j["type"] = typeToString(type).toStdString(); j["number"] = number; j["position"] = position; + if(group) { + j["group"] = group->getNumber(); + } switch(type) { case Type::Delta: j["delta_marker"] = delta->toHash(); @@ -875,7 +952,7 @@ nlohmann::json TraceMarker::toJSON() return j; } -void TraceMarker::fromJSON(nlohmann::json j) +void Marker::fromJSON(nlohmann::json j) { if(!j.contains("trace")) { throw runtime_error("Marker has no trace assigned"); @@ -937,9 +1014,14 @@ void TraceMarker::fromJSON(nlohmann::json j) } updateContextmenu(); update(); + + if(j.contains("group")) { + unsigned int number = j.value("group", 1); + model->addToGroupCreateIfNotExisting(this, number); + } } -unsigned int TraceMarker::toHash() +unsigned int Marker::toHash() { // taking the easy way: create the json string and hash it (already contains all necessary information) // This is slower than it could be, but this function is only used when loading setups, so this isn't a big problem @@ -947,12 +1029,12 @@ unsigned int TraceMarker::toHash() return hash{}(json_string); } -const std::vector &TraceMarker::getHelperMarkers() const +const std::vector &Marker::getHelperMarkers() const { return helperMarkers; } -TraceMarker *TraceMarker::helperMarker(unsigned int i) +Marker *Marker::helperMarker(unsigned int i) { if(i < helperMarkers.size()) { return helperMarkers[i]; @@ -961,12 +1043,12 @@ TraceMarker *TraceMarker::helperMarker(unsigned int i) } } -TraceMarker *TraceMarker::getParent() const +Marker *Marker::getParent() const { return parent; } -void TraceMarker::setNumber(int value) +void Marker::setNumber(int value) { number = value; updateSymbol(); @@ -975,7 +1057,7 @@ void TraceMarker::setNumber(int value) } } -QWidget *TraceMarker::getTypeEditor(QAbstractItemDelegate *delegate) +QWidget *Marker::getTypeEditor(QAbstractItemDelegate *delegate) { auto c = new QComboBox; for(auto t : getSupportedTypes()) { @@ -1032,7 +1114,7 @@ QWidget *TraceMarker::getTypeEditor(QAbstractItemDelegate *delegate) } } -void TraceMarker::updateTypeFromEditor(QWidget *w) +void Marker::updateTypeFromEditor(QWidget *w) { QComboBox *c; if(type == Type::Delta) { @@ -1050,13 +1132,16 @@ void TraceMarker::updateTypeFromEditor(QWidget *w) update(); } -SIUnitEdit *TraceMarker::getSettingsEditor() +SIUnitEdit *Marker::getSettingsEditor() { + SIUnitEdit *ret = nullptr; if(isTimeDomain()) { switch(type) { case Type::Manual: case Type::Delta: - return new SIUnitEdit("", "fpnum k", 6); + ret = new SIUnitEdit("", "fpnum k", 6); + ret->setValue(position); + break; default: return nullptr; } @@ -1066,21 +1151,32 @@ SIUnitEdit *TraceMarker::getSettingsEditor() case Type::Maximum: case Type::Minimum: case Type::Delta: + ret = new SIUnitEdit("Hz", " kMG", 6); + ret->setValue(position); + break; case Type::PhaseNoise: - default: - return new SIUnitEdit("Hz", " kMG", 6); + ret = new SIUnitEdit("Hz", " kMG", 6); + ret->setValue(offset); + break; case Type::Lowpass: case Type::Highpass: - case Type::PeakTable: case Type::Bandpass: // initialize with "dB" - return new SIUnitEdit("db", " ", 3); + ret = new SIUnitEdit("db", " ", 3); + ret->setValue(cutoffAmplitude); + break; + case Type::PeakTable: + ret = new SIUnitEdit("db", " ", 3); + ret->setValue(peakThreshold); + break; case Type::TOI: + case Type::Last: return nullptr; } } + return ret; } -void TraceMarker::adjustSettings(double value) +void Marker::adjustSettings(double value) { if(isTimeDomain()) { switch(type) { @@ -1127,7 +1223,7 @@ void TraceMarker::adjustSettings(double value) update(); } -QMenu *TraceMarker::getContextMenu() { +QMenu *Marker::getContextMenu() { if(parent) { return parent->getContextMenu(); } else { @@ -1135,7 +1231,7 @@ QMenu *TraceMarker::getContextMenu() { } } -void TraceMarker::update() +void Marker::update() { if(!parentTrace->size()) { // empty trace, nothing to do @@ -1157,7 +1253,7 @@ void TraceMarker::update() auto peaks = parentTrace->findPeakFrequencies(100, peakThreshold); char suffix = 'a'; for(auto p : peaks) { - auto helper = new TraceMarker(model, number, this); + auto helper = new Marker(model, number, this); helper->suffix = suffix; helper->assignTrace(parentTrace); helper->setPosition(p); @@ -1271,22 +1367,22 @@ void TraceMarker::update() emit dataChanged(this); } -Trace *TraceMarker::getTrace() const +Trace *Marker::getTrace() const { return parentTrace; } -int TraceMarker::getNumber() const +int Marker::getNumber() const { return number; } -std::complex TraceMarker::getData() const +std::complex Marker::getData() const { return data; } -bool TraceMarker::isMovable() +bool Marker::isMovable() { if(parent) { // helper traces are never movable by the user @@ -1301,17 +1397,17 @@ bool TraceMarker::isMovable() } } -QPixmap &TraceMarker::getSymbol() +QPixmap &Marker::getSymbol() { return symbol; } -double TraceMarker::getPosition() const +double Marker::getPosition() const { return position; } -bool TraceMarker::isTimeDomain() +bool Marker::isTimeDomain() { if(parentTrace) { if(parentTrace->outputType() == Trace::DataType::Time) { diff --git a/Software/PC_Application/Traces/tracemarker.h b/Software/PC_Application/Traces/Marker/marker.h similarity index 79% rename from Software/PC_Application/Traces/tracemarker.h rename to Software/PC_Application/Traces/Marker/marker.h index 330b664..c8ca56a 100644 --- a/Software/PC_Application/Traces/tracemarker.h +++ b/Software/PC_Application/Traces/Marker/marker.h @@ -3,20 +3,21 @@ #include #include -#include "trace.h" +#include "../trace.h" #include #include #include "CustomWidgets/siunitedit.h" #include "savable.h" -class TraceMarkerModel; +class MarkerModel; +class MarkerGroup; -class TraceMarker : public QObject, public Savable +class Marker : public QObject, public Savable { Q_OBJECT; public: - TraceMarker(TraceMarkerModel *model, int number = 1, TraceMarker *parent = nullptr, QString descr = QString()); - ~TraceMarker(); + Marker(MarkerModel *model, int number = 1, Marker *parent = nullptr, QString descr = QString()); + ~Marker(); void assignTrace(Trace *t); Trace* trace(); @@ -25,6 +26,7 @@ public: dBAngle, RealImag, Impedance, + VSWR, // Noise marker parameters Noise, PhaseNoise, @@ -88,10 +90,10 @@ public: // Updates marker position and data on automatic markers. Should be called whenever the tracedata is complete void update(); - TraceMarker *getParent() const; - const std::vector& getHelperMarkers() const; - TraceMarker *helperMarker(unsigned int i); - void assignDeltaMarker(TraceMarker *m); + Marker *getParent() const; + const std::vector& getHelperMarkers() const; + Marker *helperMarker(unsigned int i); + void assignDeltaMarker(Marker *m); QString getSuffix() const; virtual nlohmann::json toJSON() override; @@ -106,18 +108,23 @@ public: std::set getGraphDisplayFormats() const; + MarkerGroup *getGroup() const; + void setGroup(MarkerGroup *value); + public slots: void setPosition(double freq); + void updateContextmenu(); signals: - void deleted(TraceMarker *m); - void dataChanged(TraceMarker *m); - void symbolChanged(TraceMarker *m); - void typeChanged(TraceMarker *m); - void assignedDeltaChanged(TraceMarker *m); - void traceChanged(TraceMarker *m); - void beginRemoveHelperMarkers(TraceMarker *m); - void endRemoveHelperMarkers(TraceMarker *m); - void dataFormatChanged(TraceMarker *m); + void positionChanged(double pos); + void deleted(Marker *m); + void dataChanged(Marker *m); + void symbolChanged(Marker *m); + void typeChanged(Marker *m); + void assignedDeltaChanged(Marker *m); + void traceChanged(Marker *m); + void beginRemoveHelperMarkers(Marker *m); + void endRemoveHelperMarkers(Marker *m); + void dataFormatChanged(Marker *m); private slots: void parentTraceDeleted(Trace *t); @@ -125,10 +132,10 @@ private slots: void updateSymbol(); void checkDeltaMarker(); void deltaDeleted(); - void updateContextmenu(); + void traceTypeChanged(); signals: void rawDataChanged(); - void domainChanged(); + void domainChanged(Marker *m); private: std::set getSupportedTypes(); static QString typeToString(Type t) { @@ -148,7 +155,7 @@ private: } void constrainPosition(); void constrainFormat(); - TraceMarker *bestDeltaCandidate(); + Marker *bestDeltaCandidate(); void deleteHelperMarkers(); void setType(Type t); double toDecibel(); @@ -156,7 +163,7 @@ private: void setTableFormat(Format f); - TraceMarkerModel *model; + MarkerModel *model; Trace *parentTrace; double position; int number; @@ -170,9 +177,9 @@ private: QMenu contextmenu; - TraceMarker *delta; - std::vector helperMarkers; - TraceMarker *parent; + Marker *delta; + std::vector helperMarkers; + Marker *parent; // settings for the different marker types double cutoffAmplitude; double peakThreshold; @@ -180,6 +187,8 @@ private: Format formatTable; std::set formatGraph; + + MarkerGroup *group; }; #endif // TRACEMARKER_H diff --git a/Software/PC_Application/Traces/Marker/markergroup.cpp b/Software/PC_Application/Traces/Marker/markergroup.cpp new file mode 100644 index 0000000..3f3f827 --- /dev/null +++ b/Software/PC_Application/Traces/Marker/markergroup.cpp @@ -0,0 +1,106 @@ +#include "markergroup.h" + +MarkerGroup::~MarkerGroup() +{ + while(markers.size()) { + remove(*markers.begin()); + } +} + +bool MarkerGroup::add(Marker *m) +{ + if(!applicable(m)) { + // can't add to group + return false; + } + + if(m->getGroup()) { + // marker already in other group remove from it + m->getGroup()->remove(m); + } + + connect(m, &Marker::positionChanged, this, &MarkerGroup::markerMoved); + connect(m, &Marker::typeChanged, this, &MarkerGroup::checkMarker); + connect(m, &Marker::domainChanged, this, &MarkerGroup::checkMarker); + connect(m, &Marker::deleted, [=](){ + remove(m); + }); + + if(markers.size() > 0) { + m->setPosition((*markers.begin())->getPosition()); + } + + m->setGroup(this); + markers.insert(m); + + return true; +} + +bool MarkerGroup::remove(Marker *m) +{ + if(markers.count(m)) { + // todo break connections, notify marker + disconnect(m, &Marker::positionChanged, this, &MarkerGroup::markerMoved); + disconnect(m, &Marker::typeChanged, this, &MarkerGroup::checkMarker); + disconnect(m, &Marker::domainChanged, this, &MarkerGroup::checkMarker); + + m->setGroup(nullptr); + + markers.erase(m); + + if(markers.size() == 0) { + // all markers removed + emit emptied(this); + } + + return true; + } else { + // not in group + return false; + } +} + +bool MarkerGroup::applicable(Marker *m) +{ + if(!m->isMovable()) { + // can't add automatic markers to group + return false; + } + if(markers.size() == 0) { + // first marker in group + isTimeDomain = m->isTimeDomain(); + } else { + // check domain + if(isTimeDomain != m->isTimeDomain()) { + // only markers of the same domain are allowed in a group + return false; + } + } + return true; +} + +void MarkerGroup::markerMoved(double newpos) +{ + // moving the other markers will trigger additional calls to this slot. + // Set and check guard variable + if(adjustingMarkers) { + return; + } + adjustingMarkers = true; + for(auto m : markers) { + m->setPosition(newpos); + } + adjustingMarkers = false; +} + +void MarkerGroup::checkMarker(Marker *m) +{ + if(!applicable(m)) { + remove(m); + } +} + +unsigned int MarkerGroup::getNumber() const +{ + return number; +} diff --git a/Software/PC_Application/Traces/Marker/markergroup.h b/Software/PC_Application/Traces/Marker/markergroup.h new file mode 100644 index 0000000..a64cbad --- /dev/null +++ b/Software/PC_Application/Traces/Marker/markergroup.h @@ -0,0 +1,39 @@ +#ifndef MARKERGROUP_H +#define MARKERGROUP_H + +#include + +#include "marker.h" + +class MarkerGroup : public QObject +{ + Q_OBJECT +public: + MarkerGroup(unsigned int number) + : adjustingMarkers(false), + isTimeDomain(false), + markers(), + number(number){}; + ~MarkerGroup(); + + bool add(Marker *m); + bool remove(Marker *m); + + unsigned int getNumber() const; + bool applicable(Marker *m); + +signals: + void emptied(MarkerGroup*); + +private: + + void markerMoved(double newpos); + // Check if marker still applicable for group, remove if necessary + void checkMarker(Marker *m); + bool adjustingMarkers; + bool isTimeDomain; + std::set markers; + unsigned int number; +}; + +#endif // MARKERGROUP_H diff --git a/Software/PC_Application/Traces/tracemarkermodel.cpp b/Software/PC_Application/Traces/Marker/markermodel.cpp similarity index 63% rename from Software/PC_Application/Traces/tracemarkermodel.cpp rename to Software/PC_Application/Traces/Marker/markermodel.cpp index 1b01054..ca7703a 100644 --- a/Software/PC_Application/Traces/tracemarkermodel.cpp +++ b/Software/PC_Application/Traces/Marker/markermodel.cpp @@ -1,29 +1,30 @@ -#include "tracemarkermodel.h" +#include "markermodel.h" #include "unit.h" #include #include #include "CustomWidgets/siunitedit.h" #include +#include "markergroup.h" using namespace std; static constexpr int rowHeight = 21; -TraceMarkerModel::TraceMarkerModel(TraceModel &model, QObject *parent) +MarkerModel::MarkerModel(TraceModel &model, QObject *parent) : QAbstractItemModel(parent), model(model) { model.setMarkerModel(this); markers.clear(); - root = new TraceMarker(this); + root = new Marker(this); } -TraceMarkerModel::~TraceMarkerModel() +MarkerModel::~MarkerModel() { delete root; } -QModelIndex TraceMarkerModel::index(int row, int column, const QModelIndex &parent) const +QModelIndex MarkerModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) { return QModelIndex(); @@ -38,7 +39,7 @@ QModelIndex TraceMarkerModel::index(int row, int column, const QModelIndex &pare return createIndex(row, column, root); } -QModelIndex TraceMarkerModel::parent(const QModelIndex &index) const +QModelIndex MarkerModel::parent(const QModelIndex &index) const { if (!index.isValid()) { return QModelIndex(); @@ -57,7 +58,7 @@ QModelIndex TraceMarkerModel::parent(const QModelIndex &index) const } } -TraceMarker *TraceMarkerModel::createDefaultMarker() +Marker *MarkerModel::createDefaultMarker() { // find lowest free number int number = 0; @@ -72,34 +73,34 @@ TraceMarker *TraceMarkerModel::createDefaultMarker() } } } while (used); - auto marker = new TraceMarker(this, number); + auto marker = new Marker(this, number); marker->setPosition(2150000000); marker->assignTrace(model.trace(0)); return marker; } -void TraceMarkerModel::addMarker(TraceMarker *t) +void MarkerModel::addMarker(Marker *t) { beginInsertRows(QModelIndex(), markers.size(), markers.size()); markers.push_back(t); endInsertRows(); - connect(t, &TraceMarker::dataChanged, this, &TraceMarkerModel::markerDataChanged); - connect(t, &TraceMarker::typeChanged, this, &TraceMarkerModel::markerDataChanged); - connect(t, &TraceMarker::traceChanged, this, &TraceMarkerModel::markerDataChanged); - connect(t, &TraceMarker::beginRemoveHelperMarkers, [=](TraceMarker *m) { + connect(t, &Marker::dataChanged, this, &MarkerModel::markerDataChanged); + connect(t, &Marker::typeChanged, this, &MarkerModel::markerDataChanged); + connect(t, &Marker::traceChanged, this, &MarkerModel::markerDataChanged); + connect(t, &Marker::beginRemoveHelperMarkers, [=](Marker *m) { auto row = find(markers.begin(), markers.end(), m) - markers.begin(); auto modelIndex = createIndex(row, 0, root); beginRemoveRows(modelIndex, 0, m->getHelperMarkers().size() - 1); }); - connect(t, &TraceMarker::endRemoveHelperMarkers, [=](TraceMarker *m) { + connect(t, &Marker::endRemoveHelperMarkers, [=](Marker *m) { endRemoveRows(); markerDataChanged(m); }); - connect(t, &TraceMarker::deleted, this, qOverload(&TraceMarkerModel::removeMarker)); + connect(t, &Marker::deleted, this, qOverload(&MarkerModel::removeMarker)); emit markerAdded(t); } -void TraceMarkerModel::removeMarker(unsigned int index) +void MarkerModel::removeMarker(unsigned int index) { if (index < markers.size()) { beginRemoveRows(QModelIndex(), index, index); @@ -108,7 +109,7 @@ void TraceMarkerModel::removeMarker(unsigned int index) } } -void TraceMarkerModel::removeMarker(TraceMarker *m) +void MarkerModel::removeMarker(Marker *m) { auto it = std::find(markers.begin(), markers.end(), m); if(it != markers.end()) { @@ -116,7 +117,7 @@ void TraceMarkerModel::removeMarker(TraceMarker *m) } } -void TraceMarkerModel::markerDataChanged(TraceMarker *m) +void MarkerModel::markerDataChanged(Marker *m) { auto row = find(markers.begin(), markers.end(), m) - markers.begin(); if(m->editingFrequency) { @@ -132,12 +133,76 @@ void TraceMarkerModel::markerDataChanged(TraceMarker *m) } } -TraceMarker *TraceMarkerModel::marker(int index) +void MarkerModel::groupEmptied(MarkerGroup *g) +{ + groups.erase(g); + delete g; + // notify markers of deleted group + for(auto m : markers) { + m->updateContextmenu(); + } +} + +std::set MarkerModel::getGroups() const +{ + return groups; +} + +MarkerGroup *MarkerModel::createMarkerGroup() +{ + // find lowest available number + unsigned int number = 0; + bool used; + do { + number++; + used = false; + for(auto g : groups) { + if(g->getNumber() == number) { + used = true; + break; + } + } + } while (used); + auto group = createMarkerGroup(number); + return group; +} + +MarkerGroup *MarkerModel::createMarkerGroup(unsigned int number) +{ + auto group = new MarkerGroup(number); + groups.insert(group); + connect(group, &MarkerGroup::emptied, this, &MarkerModel::groupEmptied); + + // notify markers of additional group + for(auto m : markers) { + m->updateContextmenu(); + } + return group; +} + +void MarkerModel::addToGroupCreateIfNotExisting(Marker *m, unsigned int number) +{ + MarkerGroup *group = nullptr; + // find group + for(auto g : groups) { + if(g->getNumber() == number) { + group = g; + break; + } + } + if(!group) { + // group does not exist yet + group = createMarkerGroup(number); + } + group->add(m); +} + +Marker *MarkerModel::marker(int index) { return markers.at(index); } -int TraceMarkerModel::rowCount(const QModelIndex &index) const +int MarkerModel::rowCount(const QModelIndex &index) const { if(!index.isValid()) { return markers.size(); @@ -146,18 +211,23 @@ int TraceMarkerModel::rowCount(const QModelIndex &index) const return marker->getHelperMarkers().size(); } -int TraceMarkerModel::columnCount(const QModelIndex &) const +int MarkerModel::columnCount(const QModelIndex &) const { return ColIndexLast; } -QVariant TraceMarkerModel::data(const QModelIndex &index, int role) const +QVariant MarkerModel::data(const QModelIndex &index, int role) const { auto marker = markerFromIndex(index); if(role == Qt::DisplayRole) { switch(index.column()) { case ColIndexNumber: return QString::number(marker->getNumber()) + marker->getSuffix(); + case ColIndexGroup: + if(marker->getGroup()) { + return QString::number(marker->getGroup()->getNumber()); + } + break; case ColIndexTrace: if(marker->getTrace()) { return marker->getTrace()->name(); @@ -174,23 +244,41 @@ QVariant TraceMarkerModel::data(const QModelIndex &index, int role) const return QVariant(); } -QVariant TraceMarkerModel::headerData(int section, Qt::Orientation orientation, int role) const +QVariant MarkerModel::headerData(int section, Qt::Orientation orientation, int role) const { - if(orientation == Qt::Horizontal && role == Qt::DisplayRole) { - switch(section) { - case ColIndexNumber: return "#"; break; - case ColIndexTrace: return "Trace"; break; - case ColIndexType: return "Type"; break; - case ColIndexSettings: return "Settings"; break; - case ColIndexData: return "Data"; break; - default: return QVariant(); break; + if(orientation == Qt::Horizontal) { + switch(role) { + case Qt::DecorationRole: + switch(section) { + case ColIndexGroup: return QIcon(":/icons/chainlink.png"); + } + break; + case Qt::DisplayRole: + switch(section) { + case ColIndexNumber: return "#"; + case ColIndexTrace: return "Trace"; + case ColIndexType: return "Type"; + case ColIndexSettings: return "Settings"; + case ColIndexData: return "Data"; + } + break; + case Qt::ToolTipRole: + case Qt::WhatsThisRole: + switch(section) { + case ColIndexNumber: return "Marker number, used to identify markers on the graphs"; + case ColIndexGroup: return "Number of group this marker is linked to. Linked markers move together."; + case ColIndexTrace: return "The trace from which the marker gets its data"; + case ColIndexType: return "Markertype, depending on the type, the marker can be positioned by the user or will be set automatically"; + case ColIndexSettings: return "Configurable marker parameter, depends on the marker type"; + case ColIndexData: return "Tracedata at the marker position"; + } + break; } - } else { - return QVariant(); } + return QVariant(); } -bool TraceMarkerModel::setData(const QModelIndex &index, const QVariant &value, int) +bool MarkerModel::setData(const QModelIndex &index, const QVariant &value, int) { if((unsigned int) index.row() >= markers.size()) { return false; @@ -215,11 +303,12 @@ bool TraceMarkerModel::setData(const QModelIndex &index, const QVariant &value, return false; } -Qt::ItemFlags TraceMarkerModel::flags(const QModelIndex &index) const +Qt::ItemFlags MarkerModel::flags(const QModelIndex &index) const { int flags = Qt::ItemIsSelectable; switch(index.column()) { case ColIndexNumber: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break; + case ColIndexGroup: flags |= Qt::ItemIsEnabled; break; case ColIndexTrace: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break; case ColIndexType: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break; case ColIndexSettings: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break; @@ -233,14 +322,14 @@ Qt::ItemFlags TraceMarkerModel::flags(const QModelIndex &index) const return (Qt::ItemFlags) flags; } -std::vector TraceMarkerModel::getMarkers() +std::vector MarkerModel::getMarkers() { return markers; } -std::vector TraceMarkerModel::getMarkers(Trace *t) +std::vector MarkerModel::getMarkers(Trace *t) { - std::vector attachedMarkers; + std::vector attachedMarkers; for(auto m : markers) { if(m->getTrace() == t) { attachedMarkers.push_back(m); @@ -249,21 +338,21 @@ std::vector TraceMarkerModel::getMarkers(Trace *t) return attachedMarkers; } -TraceModel &TraceMarkerModel::getModel() +TraceModel &MarkerModel::getModel() { return model; } -void TraceMarkerModel::updateMarkers() +void MarkerModel::updateMarkers() { for(auto m : markers) { m->update(); } } -TraceMarker *TraceMarkerModel::markerFromIndex(const QModelIndex &index) const +Marker *MarkerModel::markerFromIndex(const QModelIndex &index) const { - auto m = static_cast(index.internalPointer()); + auto m = static_cast(index.internalPointer()); if(m == root) { return markers[index.row()]; } else { @@ -271,7 +360,7 @@ TraceMarker *TraceMarkerModel::markerFromIndex(const QModelIndex &index) const } } -nlohmann::json TraceMarkerModel::toJSON() +nlohmann::json MarkerModel::toJSON() { nlohmann::json j; for(auto m : markers) { @@ -280,14 +369,14 @@ nlohmann::json TraceMarkerModel::toJSON() return j; } -void TraceMarkerModel::fromJSON(nlohmann::json j) +void MarkerModel::fromJSON(nlohmann::json j) { // remove old markers while(markers.size() > 0) { removeMarker((unsigned int) 0); } for(auto jm : j) { - auto m = new TraceMarker(this); + auto m = new Marker(this); try { m->fromJSON(jm); addMarker(m); @@ -298,7 +387,7 @@ void TraceMarkerModel::fromJSON(nlohmann::json j) } // second pass to assign delta markers for(unsigned int i=0;igetType() == TraceMarker::Type::Delta) { + if(markers[i]->getType() == Marker::Type::Delta) { if(!j[i].contains("delta_marker")) { qWarning() << "JSON data does not contain assigned delta marker"; continue; @@ -329,7 +418,7 @@ QSize MarkerTraceDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIn QWidget *MarkerTraceDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const { - auto model = (TraceMarkerModel*) index.model(); + auto model = (MarkerModel*) index.model(); auto c = new QComboBox(parent); c->setMaximumHeight(rowHeight); connect(c, qOverload(&QComboBox::currentIndexChanged), [c](int) { @@ -346,7 +435,7 @@ QWidget *MarkerTraceDelegate::createEditor(QWidget *parent, const QStyleOptionVi void MarkerTraceDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { - auto marker = static_cast(index.model())->markerFromIndex(index); + auto marker = static_cast(index.model())->markerFromIndex(index); auto c = (QComboBox*) editor; MarkerWidgetTraceInfo markerInfo; markerInfo.trace = marker->trace(); @@ -361,7 +450,7 @@ void MarkerTraceDelegate::setEditorData(QWidget *editor, const QModelIndex &inde void MarkerTraceDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { - auto markerModel = (TraceMarkerModel*) model; + auto markerModel = (MarkerModel*) model; auto c = (QComboBox*) editor; markerModel->setData(index, c->itemData(c->currentIndex())); } @@ -373,7 +462,7 @@ QSize MarkerSettingsDelegate::sizeHint(const QStyleOptionViewItem &, const QMode QWidget *MarkerSettingsDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const { - auto marker = static_cast(index.model())->markerFromIndex(index); + auto marker = static_cast(index.model())->markerFromIndex(index); marker->editingFrequency = true; auto e = marker->getSettingsEditor(); if(e) { @@ -389,7 +478,7 @@ QWidget *MarkerSettingsDelegate::createEditor(QWidget *parent, const QStyleOptio void MarkerSettingsDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { - auto markerModel = (TraceMarkerModel*) model; + auto markerModel = (MarkerModel*) model; auto si = (SIUnitEdit*) editor; markerModel->setData(index, si->value()); } @@ -401,7 +490,7 @@ QSize MarkerTypeDelegate::sizeHint(const QStyleOptionViewItem &, const QModelInd QWidget *MarkerTypeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const { - auto marker = static_cast(index.model())->markerFromIndex(index); + auto marker = static_cast(index.model())->markerFromIndex(index); auto editor = marker->getTypeEditor(const_cast(this)); editor->setMaximumHeight(rowHeight); editor->setParent(parent); @@ -410,6 +499,6 @@ QWidget *MarkerTypeDelegate::createEditor(QWidget *parent, const QStyleOptionVie void MarkerTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *, const QModelIndex &index) const { - auto marker = static_cast(index.model())->markerFromIndex(index); + auto marker = static_cast(index.model())->markerFromIndex(index); marker->updateTypeFromEditor(editor); } diff --git a/Software/PC_Application/Traces/tracemarkermodel.h b/Software/PC_Application/Traces/Marker/markermodel.h similarity index 73% rename from Software/PC_Application/Traces/tracemarkermodel.h rename to Software/PC_Application/Traces/Marker/markermodel.h index 13937d2..7903a92 100644 --- a/Software/PC_Application/Traces/tracemarkermodel.h +++ b/Software/PC_Application/Traces/Marker/markermodel.h @@ -2,9 +2,9 @@ #define TRACEMARKERMODEL_H #include -#include "tracemarker.h" +#include "marker.h" #include -#include "tracemodel.h" +#include "../tracemodel.h" #include #include "savable.h" @@ -44,19 +44,20 @@ class MarkerSettingsDelegate : public QStyledItemDelegate void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override; }; -class TraceMarkerModel : public QAbstractItemModel, public Savable +class MarkerModel : public QAbstractItemModel, public Savable { Q_OBJECT public: - TraceMarkerModel(TraceModel &model, QObject *parent = 0); - ~TraceMarkerModel(); + MarkerModel(TraceModel &model, QObject *parent = 0); + ~MarkerModel(); enum { - ColIndexNumber = 0, - ColIndexTrace = 1, - ColIndexType = 2, - ColIndexSettings = 3, - ColIndexData = 4, + ColIndexNumber, + ColIndexGroup, + ColIndexTrace, + ColIndexType, + ColIndexSettings, + ColIndexData, ColIndexLast, }; @@ -69,33 +70,41 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex &index) const override; - TraceMarker* createDefaultMarker(); - TraceMarker *marker(int index); - std::vector getMarkers(); - std::vector getMarkers(Trace *t); + Marker* createDefaultMarker(); + Marker *marker(int index); + std::vector getMarkers(); + std::vector getMarkers(Trace *t); TraceModel& getModel(); void updateMarkers(); - TraceMarker *markerFromIndex(const QModelIndex &index) const; + Marker *markerFromIndex(const QModelIndex &index) const; + + MarkerGroup *createMarkerGroup(); + void addToGroupCreateIfNotExisting(Marker *m, unsigned int number); virtual nlohmann::json toJSON() override; virtual void fromJSON(nlohmann::json j) override; + std::set getGroups() const; + public slots: - void addMarker(TraceMarker *t); + void addMarker(Marker *t); void removeMarker(unsigned int index); - void removeMarker(TraceMarker *m); + void removeMarker(Marker *m); signals: - void markerAdded(TraceMarker *t); + void markerAdded(Marker *t); void setupLoadComplete(); private slots: - void markerDataChanged(TraceMarker *m); + void markerDataChanged(Marker *m); + void groupEmptied(MarkerGroup *g); private: - std::vector markers; + MarkerGroup* createMarkerGroup(unsigned int number); + std::vector markers; + std::set groups; TraceModel &model; - TraceMarker *root; + Marker *root; }; #endif // TRACEMARKERMODEL_H diff --git a/Software/PC_Application/Traces/Marker/markerwidget.cpp b/Software/PC_Application/Traces/Marker/markerwidget.cpp new file mode 100644 index 0000000..5d70a94 --- /dev/null +++ b/Software/PC_Application/Traces/Marker/markerwidget.cpp @@ -0,0 +1,153 @@ +#include "markerwidget.h" +#include "ui_markerwidget.h" +#include +#include +#include "markergroup.h" + +MarkerWidget::MarkerWidget(MarkerModel &model, QWidget *parent) : + QWidget(parent), + ui(new Ui::MarkerWidget), + model(model) +{ + ui->setupUi(this); + ui->treeView->setModel(&model); + ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexTrace, new MarkerTraceDelegate); + ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexType, new MarkerTypeDelegate); + ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexSettings, new MarkerSettingsDelegate); + + ui->treeView->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection); + ui->treeView->installEventFilter(this); + + ui->treeView->setColumnWidth(MarkerModel::ColIndexNumber, 60); + ui->treeView->setColumnWidth(MarkerModel::ColIndexGroup, 20); + ui->treeView->setColumnWidth(MarkerModel::ColIndexTrace, 60); + ui->treeView->setColumnWidth(MarkerModel::ColIndexType, 120); + + ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->treeView, &QTreeView::customContextMenuRequested, [&](const QPoint &p){ + if(ui->treeView->selectionModel()->selectedRows().size() <= 1) { + // only one marker selected, execute its context menu + auto index = ui->treeView->indexAt(p); + if(index.isValid()) { + auto marker = model.markerFromIndex(index); + auto menu = marker->getContextMenu(); + menu->exec(mapToGlobal(p)); + } + } else { + std::vector selected; + bool anyInGroup = false; + for(auto index : ui->treeView->selectionModel()->selectedRows()) { + auto marker = model.markerFromIndex(index); + selected.push_back(marker); + if(marker->getGroup()) { + anyInGroup = true; + } + } + // multiple markers selected, execute group context menu + QMenu menu; + auto createGroup = new QAction("Link selected"); + connect(createGroup, &QAction::triggered, [&](){ + auto g = model.createMarkerGroup(); + // assign markers to group + for(auto m : selected) { + g->add(m); + } + }); + menu.addAction(createGroup); + if(anyInGroup) { + auto removeGroup = new QAction("Break Links"); + connect(removeGroup, &QAction::triggered, [&](){ + // remove selected markers from groups if they are already assigned to one + for(auto m : selected) { + if(m->getGroup()) { + m->getGroup()->remove(m); + } + } + }); + menu.addAction(removeGroup); + } + menu.exec(mapToGlobal(p)); + } + }); + + connect(&model.getModel(), &TraceModel::traceAdded, this, &MarkerWidget::updatePersistentEditors); + connect(&model.getModel(), &TraceModel::traceRemoved, this, &MarkerWidget::updatePersistentEditors); + connect(&model.getModel(), &TraceModel::traceNameChanged, this, &MarkerWidget::updatePersistentEditors); + connect(&model, &MarkerModel::markerAdded, [=](Marker *m) { + connect(m, &Marker::typeChanged, this, &MarkerWidget::updatePersistentEditors); + connect(m, &Marker::traceChanged, this, &MarkerWidget::updatePersistentEditors); + connect(m, &Marker::assignedDeltaChanged, this, &MarkerWidget::updatePersistentEditors); + updatePersistentEditors(); + }); + connect(&model, &MarkerModel::setupLoadComplete, this, &MarkerWidget::updatePersistentEditors); +} + +MarkerWidget::~MarkerWidget() +{ + delete ui->treeView->itemDelegateForColumn(MarkerModel::ColIndexTrace); + delete ui->treeView->itemDelegateForColumn(MarkerModel::ColIndexType); + delete ui->treeView->itemDelegateForColumn(MarkerModel::ColIndexSettings); + delete ui; +} + +void MarkerWidget::on_bDelete_clicked() +{ + if (model.rowCount() <= 0) { + return; // there is nothing to delete (empty model) + } + + std::vector toDelete; + for(auto ind : ui->treeView->selectionModel()->selectedRows()) { + if ( ! ind.isValid() ) { + continue; // if no marker clicked/selected in treeView, the index is not valid + } + + auto marker = model.markerFromIndex(ind); + if(!marker || marker->getParent()) { + // can't delete child markers directly + continue; + } + toDelete.push_back(marker); + } + + for(auto m : toDelete) { + delete m; + } +} + +void MarkerWidget::on_bAdd_clicked() +{ + auto marker = model.createDefaultMarker(); + model.addMarker(marker); +} + +bool MarkerWidget::eventFilter(QObject *, QEvent *event) +{ + if (event->type() == QEvent::KeyPress) { + int key = static_cast(event)->key(); + if(key == Qt::Key_Escape) { + // deselect all + ui->treeView->selectionModel()->clearSelection(); + return true; + } + if(key == Qt::Key_Delete) { + // delete selected + on_bDelete_clicked(); + return true; + } + } + return false; +} + +void MarkerWidget::updatePersistentEditors() +{ + for(int i=0;itreeView->closePersistentEditor(index); + ui->treeView->openPersistentEditor(index); + } + } +} + diff --git a/Software/PC_Application/Traces/markerwidget.h b/Software/PC_Application/Traces/Marker/markerwidget.h similarity index 66% rename from Software/PC_Application/Traces/markerwidget.h rename to Software/PC_Application/Traces/Marker/markerwidget.h index 2732801..767889f 100644 --- a/Software/PC_Application/Traces/markerwidget.h +++ b/Software/PC_Application/Traces/Marker/markerwidget.h @@ -2,7 +2,7 @@ #define MARKERWIDGET_H #include -#include "tracemarkermodel.h" +#include "markermodel.h" namespace Ui { class MarkerWidget; @@ -13,7 +13,7 @@ class MarkerWidget : public QWidget Q_OBJECT public: - explicit MarkerWidget(TraceMarkerModel &model, QWidget *parent = nullptr); + explicit MarkerWidget(MarkerModel &model, QWidget *parent = nullptr); ~MarkerWidget(); private slots: @@ -22,8 +22,9 @@ private slots: void updatePersistentEditors(); private: + bool eventFilter(QObject *obj, QEvent *event) override; Ui::MarkerWidget *ui; - TraceMarkerModel &model; + MarkerModel &model; }; #endif // MARKERWIDGET_H diff --git a/Software/PC_Application/Traces/markerwidget.ui b/Software/PC_Application/Traces/Marker/markerwidget.ui similarity index 86% rename from Software/PC_Application/Traces/markerwidget.ui rename to Software/PC_Application/Traces/Marker/markerwidget.ui index 9874f09..e7265b2 100644 --- a/Software/PC_Application/Traces/markerwidget.ui +++ b/Software/PC_Application/Traces/Marker/markerwidget.ui @@ -16,6 +16,9 @@ + + QAbstractItemView::MultiSelection + true @@ -25,6 +28,9 @@ true + + 0 + @@ -44,7 +50,7 @@ - + :/icons/add.png:/icons/add.png @@ -64,7 +70,7 @@ - + :/icons/remove.png:/icons/remove.png @@ -87,7 +93,7 @@ - + diff --git a/Software/PC_Application/Traces/markerwidget.cpp b/Software/PC_Application/Traces/markerwidget.cpp deleted file mode 100644 index 8f68f68..0000000 --- a/Software/PC_Application/Traces/markerwidget.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "markerwidget.h" -#include "ui_markerwidget.h" - -MarkerWidget::MarkerWidget(TraceMarkerModel &model, QWidget *parent) : - QWidget(parent), - ui(new Ui::MarkerWidget), - model(model) -{ - ui->setupUi(this); - ui->treeView->setModel(&model); - ui->treeView->setItemDelegateForColumn(TraceMarkerModel::ColIndexTrace, new MarkerTraceDelegate); - ui->treeView->setItemDelegateForColumn(TraceMarkerModel::ColIndexType, new MarkerTypeDelegate); - ui->treeView->setItemDelegateForColumn(TraceMarkerModel::ColIndexSettings, new MarkerSettingsDelegate); - - ui->treeView->setColumnWidth(TraceMarkerModel::ColIndexNumber, 60); // reduced width to fit widget when App is not maximized - ui->treeView->setColumnWidth(TraceMarkerModel::ColIndexTrace, 60); // reduced width to fit widget when App is not maximized - ui->treeView->setColumnWidth(TraceMarkerModel::ColIndexType, 120); // reduced width to fit widget when App is not maximized - - connect(&model.getModel(), &TraceModel::traceAdded, this, &MarkerWidget::updatePersistentEditors); - connect(&model.getModel(), &TraceModel::traceRemoved, this, &MarkerWidget::updatePersistentEditors); - connect(&model.getModel(), &TraceModel::traceNameChanged, this, &MarkerWidget::updatePersistentEditors); - connect(&model, &TraceMarkerModel::markerAdded, [=](TraceMarker *m) { - connect(m, &TraceMarker::typeChanged, this, &MarkerWidget::updatePersistentEditors); - connect(m, &TraceMarker::traceChanged, this, &MarkerWidget::updatePersistentEditors); - connect(m, &TraceMarker::assignedDeltaChanged, this, &MarkerWidget::updatePersistentEditors); - updatePersistentEditors(); - }); - connect(&model, &TraceMarkerModel::setupLoadComplete, this, &MarkerWidget::updatePersistentEditors); -} - -MarkerWidget::~MarkerWidget() -{ - delete ui->treeView->itemDelegateForColumn(TraceMarkerModel::ColIndexTrace); - delete ui->treeView->itemDelegateForColumn(TraceMarkerModel::ColIndexType); - delete ui->treeView->itemDelegateForColumn(TraceMarkerModel::ColIndexSettings); - delete ui; -} - -void MarkerWidget::on_bDelete_clicked() -{ - if (model.rowCount() <= 0) { - return; // there is nothing to delete (empty model) - } - - QModelIndex ind = ui->treeView->currentIndex(); - if ( ! ind.isValid() ) { - return; // if no marker clicked/selected in treeView, the index is not valid - } - - auto marker = model.markerFromIndex(ind); - if(!marker || marker->getParent()) { - // can't delete child markers directly - return; - } - delete marker; -} - -void MarkerWidget::on_bAdd_clicked() -{ - auto marker = model.createDefaultMarker(); - model.addMarker(marker); -} - -void MarkerWidget::updatePersistentEditors() -{ - for(int i=0;itreeView->closePersistentEditor(index); - ui->treeView->openPersistentEditor(index); - } - } -} diff --git a/Software/PC_Application/Traces/trace.cpp b/Software/PC_Application/Traces/trace.cpp index e489d07..f2e6cf3 100644 --- a/Software/PC_Application/Traces/trace.cpp +++ b/Software/PC_Application/Traces/trace.cpp @@ -6,7 +6,7 @@ #include #include #include "unit.h" -#include "tracemarker.h" +#include "Marker/marker.h" using namespace std; @@ -261,16 +261,16 @@ void Trace::setColor(QColor color) { } } -void Trace::addMarker(TraceMarker *m) +void Trace::addMarker(Marker *m) { markers.insert(m); - connect(m, &TraceMarker::dataFormatChanged, this, &Trace::markerFormatChanged); + connect(m, &Marker::dataFormatChanged, this, &Trace::markerFormatChanged); emit markerAdded(m); } -void Trace::removeMarker(TraceMarker *m) +void Trace::removeMarker(Marker *m) { - disconnect(m, &TraceMarker::dataFormatChanged, this, &Trace::markerFormatChanged); + disconnect(m, &Marker::dataFormatChanged, this, &Trace::markerFormatChanged); markers.erase(m); emit markerRemoved(m); } @@ -652,7 +652,7 @@ void Trace::setCalibration(bool value) calibration = value; } -std::set Trace::getMarkers() const +std::set Trace::getMarkers() const { return markers; } diff --git a/Software/PC_Application/Traces/trace.h b/Software/PC_Application/Traces/trace.h index 65a8479..b1dcfb5 100644 --- a/Software/PC_Application/Traces/trace.h +++ b/Software/PC_Application/Traces/trace.h @@ -11,7 +11,7 @@ #include "Device/device.h" #include "Math/tracemath.h" -class TraceMarker; +class Marker; class Trace : public TraceMath { @@ -88,7 +88,7 @@ public: /* Returns the noise in dbm/Hz for spectrum analyzer measurements. May return NaN if calculation not possible */ double getNoise(double frequency); int index(double x); - std::set getMarkers() const; + std::set getMarkers() const; void setCalibration(bool value); void setReflection(bool value); @@ -146,8 +146,8 @@ public: public slots: void setVisible(bool visible); void setColor(QColor color); - void addMarker(TraceMarker *m); - void removeMarker(TraceMarker *m); + void addMarker(Marker *m); + void removeMarker(Marker *m); signals: void cleared(Trace *t); @@ -158,9 +158,9 @@ signals: void nameChanged(); void pauseChanged(); void colorChanged(Trace *t); - void markerAdded(TraceMarker *m); - void markerRemoved(TraceMarker *m); - void markerFormatChanged(TraceMarker *m); + void markerAdded(Marker *m); + void markerRemoved(Marker *m); + void markerFormatChanged(Marker *m); private: QString _name; @@ -176,7 +176,7 @@ private: bool timeDomain; QString filename; unsigned int fileParemeter; - std::set markers; + std::set markers; struct { union { Protocol::SweepSettings VNA; diff --git a/Software/PC_Application/Traces/tracemodel.cpp b/Software/PC_Application/Traces/tracemodel.cpp index 091f3d6..e82f67d 100644 --- a/Software/PC_Application/Traces/tracemodel.cpp +++ b/Software/PC_Application/Traces/tracemodel.cpp @@ -243,12 +243,12 @@ void TraceModel::addSAData(const Protocol::SpectrumAnalyzerResult& d, const Prot } } -TraceMarkerModel *TraceModel::getMarkerModel() const +MarkerModel *TraceModel::getMarkerModel() const { return markerModel; } -void TraceModel::setMarkerModel(TraceMarkerModel *value) +void TraceModel::setMarkerModel(MarkerModel *value) { markerModel = value; } diff --git a/Software/PC_Application/Traces/tracemodel.h b/Software/PC_Application/Traces/tracemodel.h index 3f30e47..4c41dde 100644 --- a/Software/PC_Application/Traces/tracemodel.h +++ b/Software/PC_Application/Traces/tracemodel.h @@ -7,7 +7,7 @@ #include "Device/device.h" #include "savable.h" -class TraceMarkerModel; +class MarkerModel; class TraceModel : public QAbstractTableModel, public Savable { @@ -42,8 +42,8 @@ public: virtual nlohmann::json toJSON() override; virtual void fromJSON(nlohmann::json j) override; - TraceMarkerModel *getMarkerModel() const; - void setMarkerModel(TraceMarkerModel *value); + MarkerModel *getMarkerModel() const; + void setMarkerModel(MarkerModel *value); signals: void SpanChanged(double fmin, double fmax); @@ -59,7 +59,7 @@ public slots: private: std::vector traces; - TraceMarkerModel *markerModel; + MarkerModel *markerModel; }; #endif // TRACEMODEL_H diff --git a/Software/PC_Application/Traces/traceplot.cpp b/Software/PC_Application/Traces/traceplot.cpp index e68fbc1..c07ae90 100644 --- a/Software/PC_Application/Traces/traceplot.cpp +++ b/Software/PC_Application/Traces/traceplot.cpp @@ -1,11 +1,11 @@ #include "traceplot.h" -#include "tracemarker.h" +#include "Marker/marker.h" #include "preferences.h" #include #include #include #include "unit.h" -#include "tracemarkermodel.h" +#include "Marker/markermodel.h" std::set TracePlot::plots; @@ -229,12 +229,12 @@ void TracePlot::leaveEvent(QEvent *event) selectedMarker = nullptr; } -TraceMarker *TracePlot::markerAtPosition(QPoint p, bool onlyMovable) +Marker *TracePlot::markerAtPosition(QPoint p, bool onlyMovable) { auto clickPoint = p - QPoint(marginLeft, marginTop); // check if click was near a marker unsigned int closestDistance = numeric_limits::max(); - TraceMarker *closestMarker = nullptr; + Marker *closestMarker = nullptr; for(auto t : traces) { if(!t.second) { // this trace is disabled, skip @@ -378,16 +378,16 @@ void TracePlot::checkIfStillSupported(Trace *t) } } -void TracePlot::markerAdded(TraceMarker *m) +void TracePlot::markerAdded(Marker *m) { - connect(m, &TraceMarker::dataChanged, this, &TracePlot::triggerReplot); - connect(m, &TraceMarker::symbolChanged, this, &TracePlot::triggerReplot); + connect(m, &Marker::dataChanged, this, &TracePlot::triggerReplot); + connect(m, &Marker::symbolChanged, this, &TracePlot::triggerReplot); triggerReplot(); } -void TracePlot::markerRemoved(TraceMarker *m) +void TracePlot::markerRemoved(Marker *m) { - disconnect(m, &TraceMarker::dataChanged, this, &TracePlot::triggerReplot); - disconnect(m, &TraceMarker::symbolChanged, this, &TracePlot::triggerReplot); + disconnect(m, &Marker::dataChanged, this, &TracePlot::triggerReplot); + disconnect(m, &Marker::symbolChanged, this, &TracePlot::triggerReplot); triggerReplot(); } diff --git a/Software/PC_Application/Traces/traceplot.h b/Software/PC_Application/Traces/traceplot.h index 27a66f7..081d76e 100644 --- a/Software/PC_Application/Traces/traceplot.h +++ b/Software/PC_Application/Traces/traceplot.h @@ -50,14 +50,14 @@ protected: bool markedForDeletion; static std::set plots; - virtual QPoint markerToPixel(TraceMarker *m) = 0; + virtual QPoint markerToPixel(Marker *m) = 0; virtual double nearestTracePoint(Trace *t, QPoint pixel, double *distance = nullptr) = 0; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void leaveEvent(QEvent *event) override; - TraceMarker *markerAtPosition(QPoint p, bool onlyMovable = false); + Marker *markerAtPosition(QPoint p, bool onlyMovable = false); void createMarkerAtPosition(QPoint p); @@ -74,8 +74,8 @@ protected slots: void traceDeleted(Trace *t); void triggerReplot(); void checkIfStillSupported(Trace *t); - virtual void markerAdded(TraceMarker *m); - virtual void markerRemoved(TraceMarker *m); + virtual void markerAdded(Marker *m); + virtual void markerRemoved(Marker *m); virtual bool xCoordinateVisible(double x) = 0; protected: static constexpr unsigned int marginTop = 20; @@ -87,7 +87,7 @@ protected: double sweep_fmin, sweep_fmax; TraceModel &model; - TraceMarker *selectedMarker; + Marker *selectedMarker; bool dropPending; QPoint dropPosition; diff --git a/Software/PC_Application/Traces/tracesmithchart.cpp b/Software/PC_Application/Traces/tracesmithchart.cpp index 420db83..49557ab 100644 --- a/Software/PC_Application/Traces/tracesmithchart.cpp +++ b/Software/PC_Application/Traces/tracesmithchart.cpp @@ -2,7 +2,7 @@ #include #include #include -#include "tracemarker.h" +#include "Marker/marker.h" #include #include "preferences.h" #include "ui_smithchartdialog.h" @@ -82,7 +82,7 @@ std::complex TraceSmithChart::pixelToData(QPoint p) return complex(data.x() / smithCoordMax, -data.y() / smithCoordMax); } -QPoint TraceSmithChart::markerToPixel(TraceMarker *m) +QPoint TraceSmithChart::markerToPixel(Marker *m) { QPoint ret = QPoint(); // if(!m->isTimeDomain()) { diff --git a/Software/PC_Application/Traces/tracesmithchart.h b/Software/PC_Application/Traces/tracesmithchart.h index e5944d7..c14faa3 100644 --- a/Software/PC_Application/Traces/tracesmithchart.h +++ b/Software/PC_Application/Traces/tracesmithchart.h @@ -25,7 +25,7 @@ protected: QPoint dataToPixel(Trace::Data d); std::complex pixelToData(QPoint p); - QPoint markerToPixel(TraceMarker *m) override; + QPoint markerToPixel(Marker *m) override; double nearestTracePoint(Trace *t, QPoint pixel, double *distance = nullptr) override; virtual bool xCoordinateVisible(double x); diff --git a/Software/PC_Application/Traces/tracexyplot.cpp b/Software/PC_Application/Traces/tracexyplot.cpp index 0668fc2..12304f8 100644 --- a/Software/PC_Application/Traces/tracexyplot.cpp +++ b/Software/PC_Application/Traces/tracexyplot.cpp @@ -3,7 +3,7 @@ #include "trace.h" #include #include -#include "tracemarker.h" +#include "Marker/marker.h" #include "xyplotaxisdialog.h" #include #include @@ -913,7 +913,7 @@ QPointF TraceXYPlot::pixelToPlotValue(QPoint pixel, int Yaxis) return p; } -QPoint TraceXYPlot::markerToPixel(TraceMarker *m) +QPoint TraceXYPlot::markerToPixel(Marker *m) { auto t = m->getTrace(); QPointF plotPoint = traceToCoordinate(t, t->index(m->getPosition()), YAxis[0].type); diff --git a/Software/PC_Application/Traces/tracexyplot.h b/Software/PC_Application/Traces/tracexyplot.h index fa353f6..eafec63 100644 --- a/Software/PC_Application/Traces/tracexyplot.h +++ b/Software/PC_Application/Traces/tracexyplot.h @@ -75,7 +75,7 @@ private: QPointF traceToCoordinate(Trace *t, unsigned int sample, YAxisType type); QPoint plotValueToPixel(QPointF plotValue, int Yaxis); QPointF pixelToPlotValue(QPoint pixel, int YAxis); - QPoint markerToPixel(TraceMarker *m) override; + QPoint markerToPixel(Marker *m) override; double nearestTracePoint(Trace *t, QPoint pixel, double *distance = nullptr) override; virtual bool xCoordinateVisible(double x); void traceDropped(Trace *t, QPoint position) override; diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index 9de5c4c..1999e3a 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -31,7 +31,7 @@ #include "CustomWidgets/tilewidget.h" #include "CustomWidgets/siunitedit.h" #include -#include "Traces/markerwidget.h" +#include "Traces/Marker/markerwidget.h" #include "Tools/impedancematchdialog.h" #include "Calibration/calibrationtracedialog.h" #include "ui_main.h" @@ -416,7 +416,7 @@ VNA::VNA(AppWindow *window) // toolbars.insert(tb_portExtension); - markerModel = new TraceMarkerModel(traceModel, this); + markerModel = new MarkerModel(traceModel, this); auto tracesDock = new QDockWidget("Traces"); traceWidget = new TraceWidgetVNA(traceModel, cal, deembedding); diff --git a/Software/PC_Application/VNA/vna.h b/Software/PC_Application/VNA/vna.h index 80a66d7..7f15a48 100644 --- a/Software/PC_Application/VNA/vna.h +++ b/Software/PC_Application/VNA/vna.h @@ -69,7 +69,7 @@ private: unsigned int averages; TraceModel traceModel; TraceWidget *traceWidget; - TraceMarkerModel *markerModel; + MarkerModel *markerModel; Averaging average; // Calibration diff --git a/Software/PC_Application/appwindow.cpp b/Software/PC_Application/appwindow.cpp index 5d96151..8c81c4b 100644 --- a/Software/PC_Application/appwindow.cpp +++ b/Software/PC_Application/appwindow.cpp @@ -30,7 +30,7 @@ #include "CustomWidgets/tilewidget.h" #include "CustomWidgets/siunitedit.h" #include -#include "Traces/markerwidget.h" +#include "Traces/Marker/markerwidget.h" #include "Tools/impedancematchdialog.h" #include "Calibration/calibrationtracedialog.h" #include "ui_main.h" diff --git a/Software/PC_Application/appwindow.h b/Software/PC_Application/appwindow.h index 0fcdc48..85c58c0 100644 --- a/Software/PC_Application/appwindow.h +++ b/Software/PC_Application/appwindow.h @@ -11,7 +11,7 @@ #include "Calibration/calibration.h" #include #include "Traces/tracemodel.h" -#include "Traces/tracemarkermodel.h" +#include "Traces/Marker/markermodel.h" #include "averaging.h" #include "Device/devicelog.h" #include "preferences.h" diff --git a/Software/PC_Application/icons.qrc b/Software/PC_Application/icons.qrc index 53c4752..b4b2c2f 100644 --- a/Software/PC_Application/icons.qrc +++ b/Software/PC_Application/icons.qrc @@ -49,5 +49,6 @@ icons/port2.svg icons/down.png icons/up.png + icons/chainlink.png diff --git a/Software/PC_Application/icons/chainlink.png b/Software/PC_Application/icons/chainlink.png new file mode 100644 index 0000000..0dce789 Binary files /dev/null and b/Software/PC_Application/icons/chainlink.png differ