Add markers by right-clicking a graph
This commit is contained in:
parent
93f5eba6a8
commit
ba3527d7b6
@ -6,6 +6,7 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
|
#include "tracemarker.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -263,11 +264,13 @@ void Trace::setColor(QColor color) {
|
|||||||
void Trace::addMarker(TraceMarker *m)
|
void Trace::addMarker(TraceMarker *m)
|
||||||
{
|
{
|
||||||
markers.insert(m);
|
markers.insert(m);
|
||||||
|
connect(m, &TraceMarker::dataFormatChanged, this, &Trace::markerFormatChanged);
|
||||||
emit markerAdded(m);
|
emit markerAdded(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Trace::removeMarker(TraceMarker *m)
|
void Trace::removeMarker(TraceMarker *m)
|
||||||
{
|
{
|
||||||
|
disconnect(m, &TraceMarker::dataFormatChanged, this, &Trace::markerFormatChanged);
|
||||||
markers.erase(m);
|
markers.erase(m);
|
||||||
emit markerRemoved(m);
|
emit markerRemoved(m);
|
||||||
}
|
}
|
||||||
|
@ -160,6 +160,7 @@ signals:
|
|||||||
void colorChanged(Trace *t);
|
void colorChanged(Trace *t);
|
||||||
void markerAdded(TraceMarker *m);
|
void markerAdded(TraceMarker *m);
|
||||||
void markerRemoved(TraceMarker *m);
|
void markerRemoved(TraceMarker *m);
|
||||||
|
void markerFormatChanged(TraceMarker *m);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString _name;
|
QString _name;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include "preferences.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -46,10 +47,13 @@ TraceMarker::~TraceMarker()
|
|||||||
|
|
||||||
void TraceMarker::assignTrace(Trace *t)
|
void TraceMarker::assignTrace(Trace *t)
|
||||||
{
|
{
|
||||||
|
bool firstAssignment = false;
|
||||||
if(parentTrace) {
|
if(parentTrace) {
|
||||||
// remove connection from previous parent trace
|
// remove connection from previous parent trace
|
||||||
parentTrace->removeMarker(this);
|
parentTrace->removeMarker(this);
|
||||||
disconnect(parentTrace, &Trace::deleted, this, nullptr);
|
disconnect(parentTrace, &Trace::deleted, this, nullptr);
|
||||||
|
} else {
|
||||||
|
firstAssignment = true;
|
||||||
}
|
}
|
||||||
parentTrace = t;
|
parentTrace = t;
|
||||||
if(!getSupportedTypes().count(type)) {
|
if(!getSupportedTypes().count(type)) {
|
||||||
@ -63,16 +67,29 @@ void TraceMarker::assignTrace(Trace *t)
|
|||||||
connect(parentTrace, &Trace::deleted, this, &TraceMarker::parentTraceDeleted);
|
connect(parentTrace, &Trace::deleted, this, &TraceMarker::parentTraceDeleted);
|
||||||
connect(parentTrace, &Trace::dataChanged, this, &TraceMarker::traceDataChanged);
|
connect(parentTrace, &Trace::dataChanged, this, &TraceMarker::traceDataChanged);
|
||||||
connect(parentTrace, &Trace::colorChanged, this, &TraceMarker::updateSymbol);
|
connect(parentTrace, &Trace::colorChanged, this, &TraceMarker::updateSymbol);
|
||||||
connect(parentTrace, &Trace::typeChanged, [=](){
|
connect(parentTrace, &Trace::typeChanged, this, &TraceMarker::domainChanged);
|
||||||
emit domainChanged();
|
connect(parentTrace, &Trace::typeChanged, this, &TraceMarker::checkDeltaMarker);
|
||||||
checkDeltaMarker();
|
|
||||||
});
|
|
||||||
constrainPosition();
|
constrainPosition();
|
||||||
updateSymbol();
|
updateSymbol();
|
||||||
parentTrace->addMarker(this);
|
parentTrace->addMarker(this);
|
||||||
for(auto m : helperMarkers) {
|
for(auto m : helperMarkers) {
|
||||||
m->assignTrace(t);
|
m->assignTrace(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(firstAssignment) {
|
||||||
|
// Marker was just created and this is the first assignment to a trace.
|
||||||
|
// Use display format on graph from preferences
|
||||||
|
auto p = Preferences::getInstance();
|
||||||
|
if(p.General.markerDefault.showDataOnGraphs) {
|
||||||
|
if(p.General.markerDefault.showAllData) {
|
||||||
|
for(auto f : applicableFormats()) {
|
||||||
|
formatGraph.insert(f);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formatGraph.insert(applicableFormats().front());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
constrainFormat();
|
constrainFormat();
|
||||||
update();
|
update();
|
||||||
emit traceChanged(this);
|
emit traceChanged(this);
|
||||||
@ -122,19 +139,19 @@ std::vector<TraceMarker::Format> TraceMarker::formats()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<TraceMarker::Format> TraceMarker::applicableFormats()
|
std::vector<TraceMarker::Format> TraceMarker::applicableFormats()
|
||||||
{
|
{
|
||||||
std::set<Format> ret;
|
std::vector<Format> ret;
|
||||||
if(isTimeDomain()) {
|
if(isTimeDomain()) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case Type::Manual:
|
case Type::Manual:
|
||||||
case Type::Delta:
|
case Type::Delta:
|
||||||
ret.insert(Format::dB);
|
ret.push_back(Format::dB);
|
||||||
ret.insert(Format::RealImag);
|
ret.push_back(Format::RealImag);
|
||||||
if(parentTrace) {
|
if(parentTrace) {
|
||||||
auto step = parentTrace->sample(parentTrace->index(position), Trace::SampleType::TimeStep).y.real();
|
auto step = parentTrace->sample(parentTrace->index(position), Trace::SampleType::TimeStep).y.real();
|
||||||
if(!isnan(step)) {
|
if(!isnan(step)) {
|
||||||
ret.insert(Format::Impedance);
|
ret.push_back(Format::Impedance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -148,36 +165,36 @@ std::set<TraceMarker::Format> TraceMarker::applicableFormats()
|
|||||||
case Type::Maximum:
|
case Type::Maximum:
|
||||||
case Type::Minimum:
|
case Type::Minimum:
|
||||||
case Type::PeakTable:
|
case Type::PeakTable:
|
||||||
ret.insert(Format::dB);
|
ret.push_back(Format::dB);
|
||||||
ret.insert(Format::dBAngle);
|
ret.push_back(Format::dBAngle);
|
||||||
ret.insert(Format::RealImag);
|
ret.push_back(Format::RealImag);
|
||||||
if(parentTrace) {
|
if(parentTrace) {
|
||||||
if(parentTrace->isReflection()) {
|
if(parentTrace->isReflection()) {
|
||||||
ret.insert(Format::Impedance);
|
ret.push_back(Format::Impedance);
|
||||||
}
|
}
|
||||||
if(!isnan(parentTrace->getNoise(parentTrace->minX()))) {
|
if(!isnan(parentTrace->getNoise(parentTrace->minX()))) {
|
||||||
ret.insert(Format::Noise);
|
ret.push_back(Format::Noise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case Type::Bandpass:
|
case Type::Bandpass:
|
||||||
ret.insert(Format::CenterBandwidth);
|
ret.push_back(Format::CenterBandwidth);
|
||||||
ret.insert(Format::InsertionLoss);
|
ret.push_back(Format::InsertionLoss);
|
||||||
break;
|
break;
|
||||||
case Type::Lowpass:
|
case Type::Lowpass:
|
||||||
case Type::Highpass:
|
case Type::Highpass:
|
||||||
ret.insert(Format::Cutoff);
|
ret.push_back(Format::Cutoff);
|
||||||
ret.insert(Format::InsertionLoss);
|
ret.push_back(Format::InsertionLoss);
|
||||||
break;
|
break;
|
||||||
case Type::PhaseNoise:
|
case Type::PhaseNoise:
|
||||||
ret.insert(Format::PhaseNoise);
|
ret.push_back(Format::PhaseNoise);
|
||||||
ret.insert(Format::dB);
|
ret.push_back(Format::dB);
|
||||||
break;
|
break;
|
||||||
case Type::TOI:
|
case Type::TOI:
|
||||||
ret.insert(Format::TOI);
|
ret.push_back(Format::TOI);
|
||||||
ret.insert(Format::AvgTone);
|
ret.push_back(Format::AvgTone);
|
||||||
ret.insert(Format::AvgModulationProduct);
|
ret.push_back(Format::AvgModulationProduct);
|
||||||
break;
|
break;
|
||||||
case Type::Last:
|
case Type::Last:
|
||||||
break;
|
break;
|
||||||
@ -490,6 +507,7 @@ void TraceMarker::updateContextmenu()
|
|||||||
}
|
}
|
||||||
|
|
||||||
contextmenu.clear();
|
contextmenu.clear();
|
||||||
|
contextmenu.addSection("Marker");
|
||||||
|
|
||||||
auto typemenu = contextmenu.addMenu("Type");
|
auto typemenu = contextmenu.addMenu("Type");
|
||||||
auto typegroup = new QActionGroup(&contextmenu);
|
auto typegroup = new QActionGroup(&contextmenu);
|
||||||
@ -534,9 +552,14 @@ void TraceMarker::updateContextmenu()
|
|||||||
} else {
|
} else {
|
||||||
formatGraph.erase(f);
|
formatGraph.erase(f);
|
||||||
}
|
}
|
||||||
|
emit dataFormatChanged(this);
|
||||||
});
|
});
|
||||||
graph->addAction(setFormatAction);
|
graph->addAction(setFormatAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto deleteAction = new QAction("Delete");
|
||||||
|
connect(deleteAction, &QAction::triggered, this, &TraceMarker::deleteLater);
|
||||||
|
contextmenu.addAction(deleteAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<TraceMarker::Type> TraceMarker::getSupportedTypes()
|
std::set<TraceMarker::Type> TraceMarker::getSupportedTypes()
|
||||||
@ -554,16 +577,18 @@ std::set<TraceMarker::Type> TraceMarker::getSupportedTypes()
|
|||||||
supported.insert(Type::Minimum);
|
supported.insert(Type::Minimum);
|
||||||
supported.insert(Type::Delta);
|
supported.insert(Type::Delta);
|
||||||
supported.insert(Type::PeakTable);
|
supported.insert(Type::PeakTable);
|
||||||
|
if(!parentTrace->isReflection()) {
|
||||||
|
supported.insert(Type::Lowpass);
|
||||||
|
supported.insert(Type::Highpass);
|
||||||
|
supported.insert(Type::Bandpass);
|
||||||
|
}
|
||||||
if(parentTrace->isLive()) {
|
if(parentTrace->isLive()) {
|
||||||
switch(parentTrace->liveParameter()) {
|
switch(parentTrace->liveParameter()) {
|
||||||
case Trace::LiveParameter::S11:
|
case Trace::LiveParameter::S11:
|
||||||
case Trace::LiveParameter::S12:
|
case Trace::LiveParameter::S12:
|
||||||
case Trace::LiveParameter::S21:
|
case Trace::LiveParameter::S21:
|
||||||
case Trace::LiveParameter::S22:
|
case Trace::LiveParameter::S22:
|
||||||
// special VNA marker types
|
// no special marker types for VNA yet
|
||||||
supported.insert(Type::Lowpass);
|
|
||||||
supported.insert(Type::Highpass);
|
|
||||||
supported.insert(Type::Bandpass);
|
|
||||||
break;
|
break;
|
||||||
case Trace::LiveParameter::Port1:
|
case Trace::LiveParameter::Port1:
|
||||||
case Trace::LiveParameter::Port2:
|
case Trace::LiveParameter::Port2:
|
||||||
@ -595,15 +620,20 @@ void TraceMarker::constrainPosition()
|
|||||||
|
|
||||||
void TraceMarker::constrainFormat()
|
void TraceMarker::constrainFormat()
|
||||||
{
|
{
|
||||||
|
auto vec = applicableFormats();
|
||||||
// check format
|
// check format
|
||||||
if(!applicableFormats().count(formatTable)) {
|
if(std::find(vec.begin(), vec.end(), formatTable) == vec.end()) {
|
||||||
setTableFormat(*applicableFormats().begin());
|
setTableFormat(vec.front());
|
||||||
}
|
}
|
||||||
|
std::set<Format> toErase;
|
||||||
for(auto f : formatGraph) {
|
for(auto f : formatGraph) {
|
||||||
if(!applicableFormats().count(f)) {
|
if(std::find(vec.begin(), vec.end(), f) == vec.end()) {
|
||||||
formatGraph.erase(f);
|
toErase.insert(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(auto f : toErase) {
|
||||||
|
formatGraph.erase(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceMarker *TraceMarker::bestDeltaCandidate()
|
TraceMarker *TraceMarker::bestDeltaCandidate()
|
||||||
@ -741,14 +771,15 @@ void TraceMarker::setTableFormat(TraceMarker::Format f)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!applicableFormats().count(f)) {
|
auto vec = applicableFormats();
|
||||||
|
if(std::find(vec.begin(), vec.end(), f) == vec.end()) {
|
||||||
// can't use requested format for this type of marker
|
// can't use requested format for this type of marker
|
||||||
qWarning() << "Requested marker format" << formatToString(f) << "(not applicable for type" << typeToString(type) <<")";
|
qWarning() << "Requested marker format" << formatToString(f) << "(not applicable for type" << typeToString(type) <<")";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatTable = f;
|
formatTable = f;
|
||||||
emit dataChanged(this);
|
emit dataFormatChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<TraceMarker::Format> TraceMarker::getGraphDisplayFormats() const
|
std::set<TraceMarker::Format> TraceMarker::getGraphDisplayFormats() const
|
||||||
|
@ -43,7 +43,7 @@ public:
|
|||||||
static QString formatToString(Format f);
|
static QString formatToString(Format f);
|
||||||
static Format formatFromString(QString s);
|
static Format formatFromString(QString s);
|
||||||
static std::vector<Format> formats();
|
static std::vector<Format> formats();
|
||||||
std::set<Format> applicableFormats();
|
std::vector<Format> applicableFormats();
|
||||||
|
|
||||||
QString readableData(Format format = Format::Last);
|
QString readableData(Format format = Format::Last);
|
||||||
QString readableSettings();
|
QString readableSettings();
|
||||||
@ -116,6 +116,7 @@ signals:
|
|||||||
void traceChanged(TraceMarker *m);
|
void traceChanged(TraceMarker *m);
|
||||||
void beginRemoveHelperMarkers(TraceMarker *m);
|
void beginRemoveHelperMarkers(TraceMarker *m);
|
||||||
void endRemoveHelperMarkers(TraceMarker *m);
|
void endRemoveHelperMarkers(TraceMarker *m);
|
||||||
|
void dataFormatChanged(TraceMarker *m);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void parentTraceDeleted(Trace *t);
|
void parentTraceDeleted(Trace *t);
|
||||||
|
@ -13,6 +13,7 @@ TraceMarkerModel::TraceMarkerModel(TraceModel &model, QObject *parent)
|
|||||||
: QAbstractItemModel(parent),
|
: QAbstractItemModel(parent),
|
||||||
model(model)
|
model(model)
|
||||||
{
|
{
|
||||||
|
model.setMarkerModel(this);
|
||||||
markers.clear();
|
markers.clear();
|
||||||
root = new TraceMarker(this);
|
root = new TraceMarker(this);
|
||||||
}
|
}
|
||||||
|
@ -242,3 +242,13 @@ void TraceModel::addSAData(const Protocol::SpectrumAnalyzerResult& d, const Prot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TraceMarkerModel *TraceModel::getMarkerModel() const
|
||||||
|
{
|
||||||
|
return markerModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceModel::setMarkerModel(TraceMarkerModel *value)
|
||||||
|
{
|
||||||
|
markerModel = value;
|
||||||
|
}
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include "Device/device.h"
|
#include "Device/device.h"
|
||||||
#include "savable.h"
|
#include "savable.h"
|
||||||
|
|
||||||
|
class TraceMarkerModel;
|
||||||
|
|
||||||
class TraceModel : public QAbstractTableModel, public Savable
|
class TraceModel : public QAbstractTableModel, public Savable
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -40,6 +42,9 @@ public:
|
|||||||
virtual nlohmann::json toJSON() override;
|
virtual nlohmann::json toJSON() override;
|
||||||
virtual void fromJSON(nlohmann::json j) override;
|
virtual void fromJSON(nlohmann::json j) override;
|
||||||
|
|
||||||
|
TraceMarkerModel *getMarkerModel() const;
|
||||||
|
void setMarkerModel(TraceMarkerModel *value);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void SpanChanged(double fmin, double fmax);
|
void SpanChanged(double fmin, double fmax);
|
||||||
void traceAdded(Trace *t);
|
void traceAdded(Trace *t);
|
||||||
@ -54,6 +59,7 @@ public slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Trace*> traces;
|
std::vector<Trace*> traces;
|
||||||
|
TraceMarkerModel *markerModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRACEMODEL_H
|
#endif // TRACEMODEL_H
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
|
#include "tracemarkermodel.h"
|
||||||
|
|
||||||
std::set<TracePlot*> TracePlot::plots;
|
std::set<TracePlot*> TracePlot::plots;
|
||||||
|
|
||||||
@ -21,6 +22,8 @@ TracePlot::TracePlot(TraceModel &model, QWidget *parent)
|
|||||||
markedForDeletion = false;
|
markedForDeletion = false;
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
lastUpdate = QTime::currentTime();
|
lastUpdate = QTime::currentTime();
|
||||||
|
replotTimer.setSingleShot(true);
|
||||||
|
connect(&replotTimer, &QTimer::timeout, this, qOverload<>(&TracePlot::update));
|
||||||
sweep_fmin = std::numeric_limits<double>::lowest();
|
sweep_fmin = std::numeric_limits<double>::lowest();
|
||||||
sweep_fmax = std::numeric_limits<double>::max();
|
sweep_fmax = std::numeric_limits<double>::max();
|
||||||
// get notified when the span changes
|
// get notified when the span changes
|
||||||
@ -52,6 +55,7 @@ void TracePlot::enableTrace(Trace *t, bool enabled)
|
|||||||
// connect signals
|
// connect signals
|
||||||
connect(t, &Trace::dataChanged, this, &TracePlot::triggerReplot);
|
connect(t, &Trace::dataChanged, this, &TracePlot::triggerReplot);
|
||||||
connect(t, &Trace::visibilityChanged, this, &TracePlot::triggerReplot);
|
connect(t, &Trace::visibilityChanged, this, &TracePlot::triggerReplot);
|
||||||
|
connect(t, &Trace::markerFormatChanged, this, &TracePlot::triggerReplot);
|
||||||
connect(t, &Trace::markerAdded, this, &TracePlot::markerAdded);
|
connect(t, &Trace::markerAdded, this, &TracePlot::markerAdded);
|
||||||
connect(t, &Trace::markerRemoved, this, &TracePlot::markerRemoved);
|
connect(t, &Trace::markerRemoved, this, &TracePlot::markerRemoved);
|
||||||
connect(t, &Trace::typeChanged, this, &TracePlot::checkIfStillSupported);
|
connect(t, &Trace::typeChanged, this, &TracePlot::checkIfStillSupported);
|
||||||
@ -59,6 +63,7 @@ void TracePlot::enableTrace(Trace *t, bool enabled)
|
|||||||
// disconnect from notifications
|
// disconnect from notifications
|
||||||
disconnect(t, &Trace::dataChanged, this, &TracePlot::triggerReplot);
|
disconnect(t, &Trace::dataChanged, this, &TracePlot::triggerReplot);
|
||||||
disconnect(t, &Trace::visibilityChanged, this, &TracePlot::triggerReplot);
|
disconnect(t, &Trace::visibilityChanged, this, &TracePlot::triggerReplot);
|
||||||
|
disconnect(t, &Trace::markerFormatChanged, this, &TracePlot::triggerReplot);
|
||||||
disconnect(t, &Trace::markerAdded, this, &TracePlot::markerAdded);
|
disconnect(t, &Trace::markerAdded, this, &TracePlot::markerAdded);
|
||||||
disconnect(t, &Trace::markerRemoved, this, &TracePlot::markerRemoved);
|
disconnect(t, &Trace::markerRemoved, this, &TracePlot::markerRemoved);
|
||||||
disconnect(t, &Trace::typeChanged, this, &TracePlot::checkIfStillSupported);
|
disconnect(t, &Trace::typeChanged, this, &TracePlot::checkIfStillSupported);
|
||||||
@ -101,6 +106,7 @@ void TracePlot::contextMenuEvent(QContextMenuEvent *event)
|
|||||||
} else {
|
} else {
|
||||||
// no marker, contextmenu of graph
|
// no marker, contextmenu of graph
|
||||||
menu = contextmenu;
|
menu = contextmenu;
|
||||||
|
contextmenuClickpoint = event->pos();
|
||||||
}
|
}
|
||||||
menu->exec(event->globalPos());
|
menu->exec(event->globalPos());
|
||||||
if(markedForDeletion) {
|
if(markedForDeletion) {
|
||||||
@ -183,7 +189,11 @@ void TracePlot::paintEvent(QPaintEvent *event)
|
|||||||
|
|
||||||
void TracePlot::mousePressEvent(QMouseEvent *event)
|
void TracePlot::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
selectedMarker = markerAtPosition(event->pos(), true);
|
if(event->buttons() == Qt::LeftButton) {
|
||||||
|
selectedMarker = markerAtPosition(event->pos(), true);
|
||||||
|
} else {
|
||||||
|
selectedMarker = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TracePlot::mouseReleaseEvent(QMouseEvent *event)
|
void TracePlot::mouseReleaseEvent(QMouseEvent *event)
|
||||||
@ -259,6 +269,39 @@ TraceMarker *TracePlot::markerAtPosition(QPoint p, bool onlyMovable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TracePlot::createMarkerAtPosition(QPoint p)
|
||||||
|
{
|
||||||
|
// transate from point in absolute coordinates to this widget
|
||||||
|
p -= QPoint(marginLeft, marginTop);
|
||||||
|
|
||||||
|
double closestDistance = std::numeric_limits<double>::max();
|
||||||
|
Trace *trace = nullptr;
|
||||||
|
double xpos;
|
||||||
|
for(auto t : traces) {
|
||||||
|
if(!t.second) {
|
||||||
|
// trace not enabled, skip
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double distance;
|
||||||
|
auto x = nearestTracePoint(t.first, p, &distance);
|
||||||
|
if(distance < closestDistance) {
|
||||||
|
trace = t.first;
|
||||||
|
xpos = x;
|
||||||
|
closestDistance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!trace) {
|
||||||
|
// failed to find trace (should not happen)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto markerModel = model.getMarkerModel();
|
||||||
|
auto marker = markerModel->createDefaultMarker();
|
||||||
|
marker->assignTrace(trace);
|
||||||
|
marker->setPosition(xpos);
|
||||||
|
markerModel->addMarker(marker);
|
||||||
|
}
|
||||||
|
|
||||||
void TracePlot::dragEnterEvent(QDragEnterEvent *event)
|
void TracePlot::dragEnterEvent(QDragEnterEvent *event)
|
||||||
{
|
{
|
||||||
if (event->mimeData()->hasFormat("trace/pointer")) {
|
if (event->mimeData()->hasFormat("trace/pointer")) {
|
||||||
@ -322,6 +365,8 @@ void TracePlot::triggerReplot()
|
|||||||
if (lastUpdate.msecsTo(now) >= MinUpdateInterval) {
|
if (lastUpdate.msecsTo(now) >= MinUpdateInterval) {
|
||||||
lastUpdate = now;
|
lastUpdate = now;
|
||||||
replot();
|
replot();
|
||||||
|
} else {
|
||||||
|
replotTimer.start(MinUpdateInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,12 +44,14 @@ protected:
|
|||||||
virtual bool supported(Trace *t) = 0;
|
virtual bool supported(Trace *t) = 0;
|
||||||
std::map<Trace*, bool> traces;
|
std::map<Trace*, bool> traces;
|
||||||
QMenu *contextmenu;
|
QMenu *contextmenu;
|
||||||
|
QPoint contextmenuClickpoint; // mouse coordinates when the contextmenu was invoked
|
||||||
QTime lastUpdate;
|
QTime lastUpdate;
|
||||||
|
QTimer replotTimer;
|
||||||
bool markedForDeletion;
|
bool markedForDeletion;
|
||||||
static std::set<TracePlot*> plots;
|
static std::set<TracePlot*> plots;
|
||||||
|
|
||||||
virtual QPoint markerToPixel(TraceMarker *m) = 0;
|
virtual QPoint markerToPixel(TraceMarker *m) = 0;
|
||||||
virtual double nearestTracePoint(Trace *t, QPoint pixel) = 0;
|
virtual double nearestTracePoint(Trace *t, QPoint pixel, double *distance = nullptr) = 0;
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
void mouseMoveEvent(QMouseEvent *event) override;
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
@ -57,6 +59,8 @@ protected:
|
|||||||
|
|
||||||
TraceMarker *markerAtPosition(QPoint p, bool onlyMovable = false);
|
TraceMarker *markerAtPosition(QPoint p, bool onlyMovable = false);
|
||||||
|
|
||||||
|
void createMarkerAtPosition(QPoint p);
|
||||||
|
|
||||||
// handle trace drops
|
// handle trace drops
|
||||||
virtual bool dropSupported(Trace *t) = 0;
|
virtual bool dropSupported(Trace *t) = 0;
|
||||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||||
|
@ -94,7 +94,7 @@ QPoint TraceSmithChart::markerToPixel(TraceMarker *m)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
double TraceSmithChart::nearestTracePoint(Trace *t, QPoint pixel)
|
double TraceSmithChart::nearestTracePoint(Trace *t, QPoint pixel, double *distance)
|
||||||
{
|
{
|
||||||
double closestDistance = numeric_limits<double>::max();
|
double closestDistance = numeric_limits<double>::max();
|
||||||
unsigned int closestIndex = 0;
|
unsigned int closestIndex = 0;
|
||||||
@ -112,6 +112,9 @@ double TraceSmithChart::nearestTracePoint(Trace *t, QPoint pixel)
|
|||||||
closestIndex = i;
|
closestIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(distance) {
|
||||||
|
*distance = closestDistance;
|
||||||
|
}
|
||||||
return t->sample(closestIndex).x;
|
return t->sample(closestIndex).x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,47 +267,13 @@ QString TraceSmithChart::mouseText(QPoint pos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//void TraceSmithChart::paintEvent(QPaintEvent * /* the event */)
|
|
||||||
//{
|
|
||||||
// auto pref = Preferences::getInstance();
|
|
||||||
// QPainter painter(this);
|
|
||||||
// painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
// painter.setBackground(QBrush(pref.General.graphColors.background));
|
|
||||||
// painter.fillRect(0, 0, width(), height(), QBrush(pref.General.graphColors.background));
|
|
||||||
|
|
||||||
// double side = qMin(width(), height()) * screenUsage;
|
|
||||||
|
|
||||||
// //painter.setViewport((width()-side)/2, (height()-side)/2, side, side);
|
|
||||||
// //painter.setWindow(-smithCoordMax, -smithCoordMax, 2*smithCoordMax, 2*smithCoordMax);
|
|
||||||
|
|
||||||
// plotToPixelXOffset = width()/2;
|
|
||||||
// plotToPixelYOffset = height()/2;
|
|
||||||
// plotToPixelXScale = side/2;
|
|
||||||
// plotToPixelYScale = -side/2;
|
|
||||||
|
|
||||||
// draw(painter, 2*smithCoordMax/side);
|
|
||||||
//}
|
|
||||||
|
|
||||||
void TraceSmithChart::updateContextMenu()
|
void TraceSmithChart::updateContextMenu()
|
||||||
{
|
{
|
||||||
contextmenu->clear();
|
|
||||||
contextmenu->clear();
|
contextmenu->clear();
|
||||||
auto setup = new QAction("Setup...", contextmenu);
|
auto setup = new QAction("Setup...", contextmenu);
|
||||||
connect(setup, &QAction::triggered, this, &TraceSmithChart::axisSetupDialog);
|
connect(setup, &QAction::triggered, this, &TraceSmithChart::axisSetupDialog);
|
||||||
contextmenu->addAction(setup);
|
contextmenu->addAction(setup);
|
||||||
contextmenu->addSection("Traces");
|
|
||||||
// Populate context menu
|
|
||||||
for(auto t : traces) {
|
|
||||||
auto action = new QAction(t.first->name(), contextmenu);
|
|
||||||
action->setCheckable(true);
|
|
||||||
if(t.second) {
|
|
||||||
action->setChecked(true);
|
|
||||||
}
|
|
||||||
connect(action, &QAction::toggled, [=](bool active) {
|
|
||||||
enableTrace(t.first, active);
|
|
||||||
});
|
|
||||||
contextmenu->addAction(action);
|
|
||||||
}
|
|
||||||
contextmenu->addSeparator();
|
contextmenu->addSeparator();
|
||||||
auto image = new QAction("Save image...", contextmenu);
|
auto image = new QAction("Save image...", contextmenu);
|
||||||
contextmenu->addAction(image);
|
contextmenu->addAction(image);
|
||||||
@ -320,6 +289,39 @@ void TraceSmithChart::updateContextMenu()
|
|||||||
filename += ".png";
|
filename += ".png";
|
||||||
grab().save(filename);
|
grab().save(filename);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto createMarker = contextmenu->addAction("Add marker here");
|
||||||
|
bool activeTraces = false;
|
||||||
|
for(auto t : traces) {
|
||||||
|
if(t.second) {
|
||||||
|
activeTraces = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!activeTraces) {
|
||||||
|
createMarker->setEnabled(false);
|
||||||
|
}
|
||||||
|
connect(createMarker, &QAction::triggered, [=](){
|
||||||
|
createMarkerAtPosition(contextmenuClickpoint);
|
||||||
|
});
|
||||||
|
|
||||||
|
contextmenu->addSection("Traces");
|
||||||
|
// Populate context menu
|
||||||
|
for(auto t : traces) {
|
||||||
|
if(!supported(t.first)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto action = new QAction(t.first->name(), contextmenu);
|
||||||
|
action->setCheckable(true);
|
||||||
|
if(t.second) {
|
||||||
|
action->setChecked(true);
|
||||||
|
}
|
||||||
|
connect(action, &QAction::toggled, [=](bool active) {
|
||||||
|
enableTrace(t.first, active);
|
||||||
|
});
|
||||||
|
contextmenu->addAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
contextmenu->addSeparator();
|
contextmenu->addSeparator();
|
||||||
auto close = new QAction("Close", contextmenu);
|
auto close = new QAction("Close", contextmenu);
|
||||||
contextmenu->addAction(close);
|
contextmenu->addAction(close);
|
||||||
|
@ -26,7 +26,7 @@ protected:
|
|||||||
QPoint dataToPixel(Trace::Data d);
|
QPoint dataToPixel(Trace::Data d);
|
||||||
std::complex<double> pixelToData(QPoint p);
|
std::complex<double> pixelToData(QPoint p);
|
||||||
QPoint markerToPixel(TraceMarker *m) override;
|
QPoint markerToPixel(TraceMarker *m) override;
|
||||||
double nearestTracePoint(Trace *t, QPoint pixel) override;
|
double nearestTracePoint(Trace *t, QPoint pixel, double *distance = nullptr) override;
|
||||||
virtual bool xCoordinateVisible(double x);
|
virtual bool xCoordinateVisible(double x);
|
||||||
|
|
||||||
//void paintEvent(QPaintEvent *event) override;
|
//void paintEvent(QPaintEvent *event) override;
|
||||||
|
@ -229,6 +229,38 @@ void TraceXYPlot::updateContextMenu()
|
|||||||
auto setup = new QAction("Axis setup...", contextmenu);
|
auto setup = new QAction("Axis setup...", contextmenu);
|
||||||
connect(setup, &QAction::triggered, this, &TraceXYPlot::axisSetupDialog);
|
connect(setup, &QAction::triggered, this, &TraceXYPlot::axisSetupDialog);
|
||||||
contextmenu->addAction(setup);
|
contextmenu->addAction(setup);
|
||||||
|
|
||||||
|
contextmenu->addSeparator();
|
||||||
|
auto image = new QAction("Save image...", contextmenu);
|
||||||
|
contextmenu->addAction(image);
|
||||||
|
connect(image, &QAction::triggered, [=]() {
|
||||||
|
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", "", "PNG image files (*.png)", nullptr, QFileDialog::DontUseNativeDialog);
|
||||||
|
if(filename.isEmpty()) {
|
||||||
|
// aborted selection
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(filename.endsWith(".png")) {
|
||||||
|
filename.chop(4);
|
||||||
|
}
|
||||||
|
filename += ".png";
|
||||||
|
grab().save(filename);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto createMarker = contextmenu->addAction("Add marker here");
|
||||||
|
bool activeTraces = false;
|
||||||
|
for(auto t : traces) {
|
||||||
|
if(t.second) {
|
||||||
|
activeTraces = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!activeTraces) {
|
||||||
|
createMarker->setEnabled(false);
|
||||||
|
}
|
||||||
|
connect(createMarker, &QAction::triggered, [=](){
|
||||||
|
createMarkerAtPosition(contextmenuClickpoint);
|
||||||
|
});
|
||||||
|
|
||||||
for(int axis = 0;axis < 2;axis++) {
|
for(int axis = 0;axis < 2;axis++) {
|
||||||
if(YAxis[axis].type == YAxisType::Disabled) {
|
if(YAxis[axis].type == YAxisType::Disabled) {
|
||||||
continue;
|
continue;
|
||||||
@ -255,21 +287,7 @@ void TraceXYPlot::updateContextMenu()
|
|||||||
contextmenu->addAction(action);
|
contextmenu->addAction(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contextmenu->addSeparator();
|
|
||||||
auto image = new QAction("Save image...", contextmenu);
|
|
||||||
contextmenu->addAction(image);
|
|
||||||
connect(image, &QAction::triggered, [=]() {
|
|
||||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", "", "PNG image files (*.png)", nullptr, QFileDialog::DontUseNativeDialog);
|
|
||||||
if(filename.isEmpty()) {
|
|
||||||
// aborted selection
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(filename.endsWith(".png")) {
|
|
||||||
filename.chop(4);
|
|
||||||
}
|
|
||||||
filename += ".png";
|
|
||||||
grab().save(filename);
|
|
||||||
});
|
|
||||||
contextmenu->addSeparator();
|
contextmenu->addSeparator();
|
||||||
auto close = new QAction("Close", contextmenu);
|
auto close = new QAction("Close", contextmenu);
|
||||||
contextmenu->addAction(close);
|
contextmenu->addAction(close);
|
||||||
@ -902,7 +920,7 @@ QPoint TraceXYPlot::markerToPixel(TraceMarker *m)
|
|||||||
return plotValueToPixel(plotPoint, 0);
|
return plotValueToPixel(plotPoint, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double TraceXYPlot::nearestTracePoint(Trace *t, QPoint pixel)
|
double TraceXYPlot::nearestTracePoint(Trace *t, QPoint pixel, double *distance)
|
||||||
{
|
{
|
||||||
if(!tracesAxis[0].count(t)) {
|
if(!tracesAxis[0].count(t)) {
|
||||||
// trace not enabled
|
// trace not enabled
|
||||||
@ -927,6 +945,9 @@ double TraceXYPlot::nearestTracePoint(Trace *t, QPoint pixel)
|
|||||||
if(XAxis.type == XAxisType::Distance) {
|
if(XAxis.type == XAxisType::Distance) {
|
||||||
closestXpos = t->distanceToTime(closestXpos);
|
closestXpos = t->distanceToTime(closestXpos);
|
||||||
}
|
}
|
||||||
|
if(distance) {
|
||||||
|
*distance = closestDistance;
|
||||||
|
}
|
||||||
return closestXpos;
|
return closestXpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ private:
|
|||||||
QPoint plotValueToPixel(QPointF plotValue, int Yaxis);
|
QPoint plotValueToPixel(QPointF plotValue, int Yaxis);
|
||||||
QPointF pixelToPlotValue(QPoint pixel, int YAxis);
|
QPointF pixelToPlotValue(QPoint pixel, int YAxis);
|
||||||
QPoint markerToPixel(TraceMarker *m) override;
|
QPoint markerToPixel(TraceMarker *m) override;
|
||||||
double nearestTracePoint(Trace *t, QPoint pixel) override;
|
double nearestTracePoint(Trace *t, QPoint pixel, double *distance = nullptr) override;
|
||||||
virtual bool xCoordinateVisible(double x);
|
virtual bool xCoordinateVisible(double x);
|
||||||
void traceDropped(Trace *t, QPoint position) override;
|
void traceDropped(Trace *t, QPoint position) override;
|
||||||
QString mouseText(QPoint pos) override;
|
QString mouseText(QPoint pos) override;
|
||||||
|
@ -82,6 +82,10 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||||||
ui->GeneralSCPIEnabled->setEnabled(false);
|
ui->GeneralSCPIEnabled->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(ui->GeneralMarkerDataGraph, &QCheckBox::toggled, [=](bool enabled) {
|
||||||
|
ui->GeneralMarkerDataGraphAll->setEnabled(enabled);
|
||||||
|
});
|
||||||
|
|
||||||
// Page selection
|
// Page selection
|
||||||
connect(ui->treeWidget, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *current, QTreeWidgetItem *) {
|
connect(ui->treeWidget, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *current, QTreeWidgetItem *) {
|
||||||
auto name = current->text(0);
|
auto name = current->text(0);
|
||||||
@ -128,6 +132,8 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||||||
p->General.graphColors.background = ui->GeneralGraphBackground->getColor();
|
p->General.graphColors.background = ui->GeneralGraphBackground->getColor();
|
||||||
p->General.graphColors.axis = ui->GeneralGraphAxis->getColor();
|
p->General.graphColors.axis = ui->GeneralGraphAxis->getColor();
|
||||||
p->General.graphColors.divisions = ui->GeneralGraphDivisions->getColor();
|
p->General.graphColors.divisions = ui->GeneralGraphDivisions->getColor();
|
||||||
|
p->General.markerDefault.showDataOnGraphs = ui->GeneralMarkerDataGraph->isChecked();
|
||||||
|
p->General.markerDefault.showAllData = ui->GeneralMarkerDataGraphAll->isChecked();
|
||||||
p->General.SCPI.enabled = ui->GeneralSCPIEnabled->isChecked();
|
p->General.SCPI.enabled = ui->GeneralSCPIEnabled->isChecked();
|
||||||
p->General.SCPI.port = ui->GeneralSCPIPort->value();
|
p->General.SCPI.port = ui->GeneralSCPIPort->value();
|
||||||
accept();
|
accept();
|
||||||
@ -184,6 +190,8 @@ void PreferencesDialog::setInitialGUIState()
|
|||||||
ui->GeneralGraphBackground->setColor(p->General.graphColors.background);
|
ui->GeneralGraphBackground->setColor(p->General.graphColors.background);
|
||||||
ui->GeneralGraphAxis->setColor(p->General.graphColors.axis);
|
ui->GeneralGraphAxis->setColor(p->General.graphColors.axis);
|
||||||
ui->GeneralGraphDivisions->setColor(p->General.graphColors.divisions);
|
ui->GeneralGraphDivisions->setColor(p->General.graphColors.divisions);
|
||||||
|
ui->GeneralMarkerDataGraph->setChecked(p->General.markerDefault.showDataOnGraphs);
|
||||||
|
ui->GeneralMarkerDataGraphAll->setChecked(p->General.markerDefault.showAllData);
|
||||||
ui->GeneralSCPIEnabled->setChecked(p->General.SCPI.enabled);
|
ui->GeneralSCPIEnabled->setChecked(p->General.SCPI.enabled);
|
||||||
ui->GeneralSCPIPort->setValue(p->General.SCPI.port);
|
ui->GeneralSCPIPort->setValue(p->General.SCPI.port);
|
||||||
|
|
||||||
|
@ -56,6 +56,10 @@ public:
|
|||||||
QColor axis;
|
QColor axis;
|
||||||
QColor divisions;
|
QColor divisions;
|
||||||
} graphColors;
|
} graphColors;
|
||||||
|
struct {
|
||||||
|
bool showDataOnGraphs;
|
||||||
|
bool showAllData;
|
||||||
|
} markerDefault;
|
||||||
struct {
|
struct {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
int port;
|
int port;
|
||||||
@ -72,7 +76,7 @@ private:
|
|||||||
QString name;
|
QString name;
|
||||||
QVariant def;
|
QVariant def;
|
||||||
};
|
};
|
||||||
const std::array<SettingDescription, 27> descr = {{
|
const std::array<SettingDescription, 29> descr = {{
|
||||||
{&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true},
|
{&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true},
|
||||||
{&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false},
|
{&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false},
|
||||||
{&Startup.DefaultSweep.start, "Startup.DefaultSweep.start", 1000000.0},
|
{&Startup.DefaultSweep.start, "Startup.DefaultSweep.start", 1000000.0},
|
||||||
@ -98,6 +102,8 @@ private:
|
|||||||
{&General.graphColors.background, "General.graphColors.background", QColor(Qt::black)},
|
{&General.graphColors.background, "General.graphColors.background", QColor(Qt::black)},
|
||||||
{&General.graphColors.axis, "General.graphColors.axis", QColor(Qt::white)},
|
{&General.graphColors.axis, "General.graphColors.axis", QColor(Qt::white)},
|
||||||
{&General.graphColors.divisions, "General.graphColors.divisions", QColor(Qt::gray)},
|
{&General.graphColors.divisions, "General.graphColors.divisions", QColor(Qt::gray)},
|
||||||
|
{&General.markerDefault.showDataOnGraphs, "General.MarkerDefault.ShowDataOnGraphs", true},
|
||||||
|
{&General.markerDefault.showAllData, "General.MarkerDefault.ShowAllData", false},
|
||||||
{&General.SCPI.enabled, "General.SCPI.enabled", true},
|
{&General.SCPI.enabled, "General.SCPI.enabled", true},
|
||||||
{&General.SCPI.port, "General.SCPI.port", 19542},
|
{&General.SCPI.port, "General.SCPI.port", 19542},
|
||||||
}};
|
}};
|
||||||
|
@ -587,6 +587,29 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_9">
|
||||||
|
<property name="title">
|
||||||
|
<string>Marker Default Behavior</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="GeneralMarkerDataGraph">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show data on graphs</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="GeneralMarkerDataGraphAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show data in all available formats</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_8">
|
<widget class="QGroupBox" name="groupBox_8">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
Loading…
Reference in New Issue
Block a user