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