Added a new window - Temporal Graph which shows all frame IDs and the
time stamp when they came in. Shows the temporal relationship between all frames.
This commit is contained in:
+6
-3
@@ -67,7 +67,8 @@ SOURCES += main.cpp\
|
||||
helpwindow.cpp \
|
||||
blfhandler.cpp \
|
||||
re/sniffer/SnifferDelegate.cpp \
|
||||
connections/newconnectiondialog.cpp
|
||||
connections/newconnectiondialog.cpp \
|
||||
re/temporalgraphwindow.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
can_structs.h \
|
||||
@@ -125,7 +126,8 @@ HEADERS += mainwindow.h \
|
||||
helpwindow.h \
|
||||
blfhandler.h \
|
||||
re/sniffer/SnifferDelegate.h \
|
||||
connections/newconnectiondialog.h
|
||||
connections/newconnectiondialog.h \
|
||||
re/temporalgraphwindow.h
|
||||
|
||||
FORMS += ui/candatagrid.ui \
|
||||
ui/connectionwindow.ui \
|
||||
@@ -153,7 +155,8 @@ FORMS += ui/candatagrid.ui \
|
||||
ui/bisectwindow.ui \
|
||||
ui/signalviewerwindow.ui \
|
||||
helpwindow.ui \
|
||||
ui/newconnectiondialog.ui
|
||||
ui/newconnectiondialog.ui \
|
||||
ui/temporalgraphwindow.ui
|
||||
|
||||
DISTFILES +=
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
snifferWindow = nullptr;
|
||||
bisectWindow = nullptr;
|
||||
signalViewerWindow = nullptr;
|
||||
temporalGraphWindow = nullptr;
|
||||
dbcHandler = DBCHandler::getReference();
|
||||
bDirty = false;
|
||||
inhibitFilterUpdate = false;
|
||||
@@ -131,6 +132,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
connect(ui->actionCapture_Bisector, &QAction::triggered, this, &MainWindow::showBisectWindow);
|
||||
connect(ui->actionSignal_Viewer, &QAction::triggered, this, &MainWindow::showSignalViewer);
|
||||
connect(ui->actionSave_Continuous_Logfile, &QAction::triggered, this, &MainWindow::handleContinousLogging);
|
||||
connect(ui->actionTemporal_Graph, &QAction::triggered, this, &MainWindow::showTemporalGraphWindow);
|
||||
|
||||
connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames);
|
||||
|
||||
@@ -226,6 +228,7 @@ void MainWindow::killEmAll()
|
||||
killWindow(motorctrlConfigWindow);
|
||||
killWindow(signalViewerWindow);
|
||||
killWindow(connectionWindow);
|
||||
killWindow(temporalGraphWindow);
|
||||
}
|
||||
|
||||
//forcefully close the window, kill it, and salt the earth
|
||||
@@ -837,6 +840,19 @@ void MainWindow::showGraphingWindow()
|
||||
graphingWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::showTemporalGraphWindow()
|
||||
{
|
||||
//only create an instance of the object if we dont have one. Otherwise just display the existing one.
|
||||
if (!temporalGraphWindow)
|
||||
{
|
||||
if (!useFiltered)
|
||||
temporalGraphWindow = new TemporalGraphWindow(model->getListReference());
|
||||
else
|
||||
temporalGraphWindow = new TemporalGraphWindow(model->getFilteredListReference());
|
||||
}
|
||||
temporalGraphWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::showFrameDataAnalysis()
|
||||
{
|
||||
//only create an instance of the object if we dont have one. Otherwise just display the existing one.
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "re/isotp_interpreterwindow.h"
|
||||
#include "motorcontrollerconfigwindow.h"
|
||||
#include "signalviewerwindow.h"
|
||||
#include "re/temporalgraphwindow.h"
|
||||
|
||||
class CANConnection;
|
||||
class ConnectionWindow;
|
||||
@@ -81,6 +82,7 @@ private slots:
|
||||
void showSnifferWindow();
|
||||
void showBisectWindow();
|
||||
void showSignalViewer();
|
||||
void showTemporalGraphWindow();
|
||||
void exitApp();
|
||||
void handleSaveDecoded();
|
||||
void connectionStatusUpdated(int conns);
|
||||
@@ -159,6 +161,7 @@ private:
|
||||
MotorControllerConfigWindow *motorctrlConfigWindow;
|
||||
BisectWindow* bisectWindow;
|
||||
SignalViewerWindow *signalViewerWindow;
|
||||
TemporalGraphWindow *temporalGraphWindow;
|
||||
|
||||
//various private storage
|
||||
QLabel lbStatusConnected;
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
#include "temporalgraphwindow.h"
|
||||
#include "ui_temporalgraphwindow.h"
|
||||
#include "helpwindow.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
QString HexTicker::getTickLabel (double tick, const QLocale& locale, QChar formatChar, int precision)
|
||||
{
|
||||
int valu = static_cast<int>(tick);
|
||||
//qDebug() << valu;
|
||||
return "0x" + QString::number(valu, 16).toUpper().rightJustified(3,'0');
|
||||
}
|
||||
|
||||
TemporalGraphWindow::TemporalGraphWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::TemporalGraphWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowFlags(Qt::Window);
|
||||
|
||||
readSettings();
|
||||
|
||||
modelFrames = frames;
|
||||
|
||||
ui->graphingView->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes);
|
||||
|
||||
ui->graphingView->xAxis->setRange(0, 8);
|
||||
ui->graphingView->yAxis->setRange(0, 255);
|
||||
ui->graphingView->axisRect()->setupFullAxesBox();
|
||||
|
||||
|
||||
ui->graphingView->xAxis->setLabel("Elapsed Time");
|
||||
ui->graphingView->yAxis->setLabel("ID");
|
||||
ui->graphingView->xAxis->setNumberFormat("f");
|
||||
ui->graphingView->xAxis->setNumberPrecision(6);
|
||||
|
||||
HexTicker *tick = new HexTicker;
|
||||
QSharedPointer<QCPAxisTicker> sharedTicker(tick);
|
||||
tick->setTickCount(10);
|
||||
ui->graphingView->yAxis->setTicker(sharedTicker);
|
||||
|
||||
// connect slot that ties some axis selections together (especially opposite axes):
|
||||
connect(ui->graphingView, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
|
||||
connect(ui->graphingView, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress()));
|
||||
connect(ui->graphingView, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheel()));
|
||||
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
|
||||
// make bottom and left axes transfer their ranges to top and right axes:
|
||||
connect(ui->graphingView->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->graphingView->xAxis2, SLOT(setRange(QCPRange)));
|
||||
connect(ui->graphingView->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->graphingView->yAxis2, SLOT(setRange(QCPRange)));
|
||||
|
||||
if (useOpenGL)
|
||||
{
|
||||
ui->graphingView->setAntialiasedElements(QCP::aeAll);
|
||||
//ui->graphingView->setNoAntialiasingOnDrag(true);
|
||||
ui->graphingView->setOpenGl(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->graphingView->setOpenGl(false);
|
||||
ui->graphingView->setAntialiasedElements(QCP::aeNone);
|
||||
}
|
||||
}
|
||||
|
||||
TemporalGraphWindow::~TemporalGraphWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::showEvent(QShowEvent* event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
installEventFilter(this);
|
||||
readSettings();
|
||||
generateGraph();
|
||||
ui->graphingView->replot();
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
removeEventFilter(this);
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::readSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||
{
|
||||
resize(settings.value("Temporal/WindowSize", QSize(800, 600)).toSize());
|
||||
move(settings.value("Temporal/WindowPos", QPoint(50, 50)).toPoint());
|
||||
}
|
||||
useOpenGL = settings.value("Main/UseOpenGL", false).toBool();
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::writeSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||
{
|
||||
settings.setValue("Temporal/WindowSize", size());
|
||||
settings.setValue("Temporal/WindowPos", pos());
|
||||
}
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::updatedFrames(int numFrames)
|
||||
{
|
||||
CANFrame thisFrame;
|
||||
QVector<double> x, y;
|
||||
bool appendedToGraph = false;
|
||||
bool needReplot = false;
|
||||
|
||||
if (numFrames == -1) //all frames deleted. Kill the display
|
||||
{
|
||||
//removeAllGraphs();
|
||||
//now instead of removing the graphs regenerate them which will blank them out but leave them there in case
|
||||
//more traffic that matches comes in or someone otherwise loads more data
|
||||
ui->graphingView->clearGraphs(); //temporarily remove the graphs from the graph view
|
||||
ui->graphingView->replot(); //now, redisplay them all
|
||||
|
||||
}
|
||||
else if (numFrames == -2) //all new set of frames. Reset
|
||||
{
|
||||
//there shouldn't be any need to actually remove the graphs.
|
||||
//regenerate them instead
|
||||
ui->graphingView->clearGraphs(); //temporarily remove the graphs from the graph view
|
||||
//needScaleSetup = true;
|
||||
generateGraph();
|
||||
//ui->graphingView->replot(); //now, redisplay them all
|
||||
}
|
||||
else //just got some new frames. See if they are relevant.
|
||||
{
|
||||
if (numFrames > modelFrames->count()) return;
|
||||
|
||||
appendedToGraph = false;
|
||||
x.clear();
|
||||
y.clear();
|
||||
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
|
||||
{
|
||||
thisFrame = modelFrames->at(i);
|
||||
/*
|
||||
if (graphParams[j].ID == thisFrame.ID)
|
||||
{
|
||||
appendToGraph(graphParams[j], thisFrame, x, y);
|
||||
appendedToGraph = true;
|
||||
}*/
|
||||
}
|
||||
if (appendedToGraph)
|
||||
{
|
||||
//graphParams[j].ref->addData(x, y);
|
||||
needReplot = true;
|
||||
}
|
||||
|
||||
if (needReplot)
|
||||
{
|
||||
if (followGraphEnd)
|
||||
{
|
||||
//find the current X span and maintain that span but move the end of it over to match the new end
|
||||
//of the actual graph. This causes the view to move with the data to always show the end
|
||||
QCPRange range = ui->graphingView->xAxis->range();
|
||||
double size = range.size();
|
||||
bool foundRange;
|
||||
QCPRange keyRange = ui->graphingView->graph()->getKeyRange(foundRange);
|
||||
if (foundRange)
|
||||
{
|
||||
double end, start;
|
||||
end = keyRange.upper;
|
||||
start = end - size;
|
||||
ui->graphingView->xAxis->setRange(start, end);
|
||||
}
|
||||
}
|
||||
ui->graphingView->replot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::generateGraph()
|
||||
{
|
||||
if (modelFrames->count() == 0) return;
|
||||
qDebug() << "Regenerating the graph";
|
||||
ui->graphingView->addGraph();
|
||||
graph = ui->graphingView->graph();
|
||||
|
||||
QVector<double> x, y;
|
||||
double xminval = 0, xmaxval = 0, yminval = 0, ymaxval = 0;
|
||||
int frameCount = modelFrames->count();
|
||||
|
||||
x.reserve(frameCount);
|
||||
y.reserve(frameCount);
|
||||
|
||||
xminval = xmaxval = modelFrames->at(0).timestamp / 1000000.0;
|
||||
yminval = ymaxval = modelFrames->at(0).ID;
|
||||
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
{
|
||||
x.append(modelFrames->at(i).timestamp / 1000000.0);
|
||||
y.append(modelFrames->at(i).ID);
|
||||
if (x[i] > xmaxval) xmaxval = x[i];
|
||||
if (x[i] < xminval) xminval = x[i];
|
||||
if (y[i] > ymaxval) ymaxval = y[i];
|
||||
if (y[i] < yminval) yminval = y[i];
|
||||
}
|
||||
|
||||
ui->graphingView->graph()->setData(x,y);
|
||||
ui->graphingView->graph()->setLineStyle(QCPGraph::lsNone); //no lines
|
||||
ui->graphingView->graph()->setScatterStyle(QCPScatterStyle::ssPlus);
|
||||
QPen graphPen;
|
||||
graphPen.setColor(Qt::blue);
|
||||
graphPen.setWidth(1);
|
||||
ui->graphingView->graph()->setPen(graphPen);
|
||||
|
||||
qDebug() << "xmin: " << xminval;
|
||||
qDebug() << "xmax: " << xmaxval;
|
||||
qDebug() << "ymin: " << yminval;
|
||||
qDebug() << "ymax: " << ymaxval;
|
||||
|
||||
ui->graphingView->xAxis->setRange(xminval, xmaxval);
|
||||
ui->graphingView->yAxis->setRange(yminval, ymaxval);
|
||||
ui->graphingView->axisRect()->setupFullAxesBox();
|
||||
|
||||
ui->graphingView->replot();
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::selectionChanged()
|
||||
{
|
||||
/*
|
||||
normally, axis base line, axis tick labels and axis labels are selectable separately, but we want
|
||||
the user only to be able to select the axis as a whole, so we tie the selected states of the tick labels
|
||||
and the axis base line together. However, the axis label shall be selectable individually.
|
||||
|
||||
The selection state of the left and right axes shall be synchronized as well as the state of the
|
||||
bottom and top axes.
|
||||
|
||||
Further, we want to synchronize the selection of the graphs with the selection state of the respective
|
||||
legend item belonging to that graph. So the user can select a graph by either clicking on the graph itself
|
||||
or on its legend item.
|
||||
*/
|
||||
|
||||
qDebug() << "SelectionChanged";
|
||||
|
||||
// make top and bottom axes be selected synchronously, and handle axis and tick labels as one selectable object:
|
||||
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
|
||||
ui->graphingView->xAxis2->selectedParts().testFlag(QCPAxis::spAxis) || ui->graphingView->xAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
|
||||
{
|
||||
ui->graphingView->xAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
|
||||
ui->graphingView->xAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
|
||||
}
|
||||
// make left and right axes be selected synchronously, and handle axis and tick labels as one selectable object:
|
||||
if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis) || ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
|
||||
ui->graphingView->yAxis2->selectedParts().testFlag(QCPAxis::spAxis) || ui->graphingView->yAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
|
||||
{
|
||||
ui->graphingView->yAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
|
||||
ui->graphingView->yAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
|
||||
}
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::mousePress()
|
||||
{
|
||||
// if an axis is selected, only allow the direction of that axis to be dragged
|
||||
// if no axis is selected, both directions may be dragged
|
||||
|
||||
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
|
||||
{
|
||||
ui->graphingView->axisRect()->setRangeDrag(ui->graphingView->xAxis->orientation());
|
||||
}
|
||||
else if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
|
||||
{
|
||||
ui->graphingView->axisRect()->setRangeDrag(ui->graphingView->yAxis->orientation());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->graphingView->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical);
|
||||
}
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::mouseWheel()
|
||||
{
|
||||
qDebug() << "Mouse WHeel";
|
||||
// if an axis is selected, only allow the direction of that axis to be zoomed
|
||||
// if no axis is selected, both directions may be zoomed
|
||||
|
||||
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
|
||||
ui->graphingView->axisRect()->setRangeZoom(ui->graphingView->xAxis->orientation());
|
||||
else if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
|
||||
ui->graphingView->axisRect()->setRangeZoom(ui->graphingView->yAxis->orientation());
|
||||
else
|
||||
ui->graphingView->axisRect()->setRangeZoom(Qt::Horizontal|Qt::Vertical);
|
||||
}
|
||||
|
||||
bool TemporalGraphWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyRelease) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Plus:
|
||||
zoomIn();
|
||||
break;
|
||||
case Qt::Key_Minus:
|
||||
zoomOut();
|
||||
break;
|
||||
case Qt::Key_F1:
|
||||
HelpWindow::getRef()->showHelp("temporalwindow.html");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// standard event processing
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::resetView()
|
||||
{
|
||||
double yminval=10000000.0, ymaxval = -1000000.0;
|
||||
double xminval=100000000000, xmaxval = -10000000000.0;
|
||||
/*
|
||||
for (int i = 0; i < graphParams.count(); i++)
|
||||
{
|
||||
for (int j = 0; j < graphParams[i].x.count(); j++)
|
||||
{
|
||||
if (graphParams[i].x[j] < xminval) xminval = graphParams[i].x[j];
|
||||
if (graphParams[i].x[j] > xmaxval) xmaxval = graphParams[i].x[j];
|
||||
if (graphParams[i].y[j] < yminval) yminval = graphParams[i].y[j];
|
||||
if (graphParams[i].y[j] > ymaxval) ymaxval = graphParams[i].y[j];
|
||||
}
|
||||
}
|
||||
|
||||
ui->graphingView->xAxis->setRange(xminval, xmaxval);
|
||||
ui->graphingView->yAxis->setRange(yminval, ymaxval);
|
||||
ui->graphingView->axisRect()->setupFullAxesBox();
|
||||
|
||||
ui->graphingView->replot();
|
||||
*/
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::zoomIn()
|
||||
{
|
||||
QCPRange xrange = ui->graphingView->xAxis->range();
|
||||
QCPRange yrange = ui->graphingView->yAxis->range();
|
||||
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
|
||||
{
|
||||
ui->graphingView->xAxis->scaleRange(0.666, xrange.center());
|
||||
}
|
||||
|
||||
else if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
|
||||
{
|
||||
ui->graphingView->yAxis->scaleRange(0.666, yrange.center());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->graphingView->xAxis->scaleRange(0.666, xrange.center());
|
||||
ui->graphingView->yAxis->scaleRange(0.666, yrange.center());
|
||||
}
|
||||
ui->graphingView->replot();
|
||||
}
|
||||
|
||||
void TemporalGraphWindow::zoomOut()
|
||||
{
|
||||
QCPRange xrange = ui->graphingView->xAxis->range();
|
||||
QCPRange yrange = ui->graphingView->yAxis->range();
|
||||
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
|
||||
{
|
||||
ui->graphingView->xAxis->scaleRange(1.5, xrange.center());
|
||||
}
|
||||
|
||||
else if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
|
||||
{
|
||||
ui->graphingView->yAxis->scaleRange(1.5, yrange.center());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->graphingView->xAxis->scaleRange(1.5, xrange.center());
|
||||
ui->graphingView->yAxis->scaleRange(1.5, yrange.center());
|
||||
}
|
||||
ui->graphingView->replot();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef TEMPORALGRAPHWINDOW_H
|
||||
#define TEMPORALGRAPHWINDOW_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "qcustomplot.h"
|
||||
#include "can_structs.h"
|
||||
|
||||
namespace Ui {
|
||||
class TemporalGraphWindow;
|
||||
}
|
||||
|
||||
class HexTicker : public QCPAxisTicker
|
||||
{
|
||||
QString getTickLabel (double tick, const QLocale& locale, QChar formatChar, int precision);
|
||||
};
|
||||
|
||||
class TemporalGraphWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TemporalGraphWindow(const QVector<CANFrame> *, QWidget *parent = nullptr);
|
||||
~TemporalGraphWindow();
|
||||
void showEvent(QShowEvent*);
|
||||
|
||||
private slots:
|
||||
void updatedFrames(int);
|
||||
void mousePress();
|
||||
void mouseWheel();
|
||||
void resetView();
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
Ui::TemporalGraphWindow *ui;
|
||||
const QVector<CANFrame> *modelFrames;
|
||||
bool useOpenGL;
|
||||
bool followGraphEnd;
|
||||
QCPGraph *graph;
|
||||
|
||||
void closeEvent(QCloseEvent *event);
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
void generateGraph();
|
||||
|
||||
};
|
||||
|
||||
#endif // TEMPORALGRAPHWINDOW_H
|
||||
@@ -282,6 +282,7 @@
|
||||
<addaction name="actionSniffer"/>
|
||||
<addaction name="actionCapture_Bisector"/>
|
||||
<addaction name="actionSignal_Viewer"/>
|
||||
<addaction name="actionTemporal_Graph"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuSend_Frames">
|
||||
<property name="title">
|
||||
@@ -497,6 +498,11 @@
|
||||
<string>Start Continuous Logging</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTemporal_Graph">
|
||||
<property name="text">
|
||||
<string>Temporal Graph</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TemporalGraphWindow</class>
|
||||
<widget class="QDialog" name="TemporalGraphWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>886</width>
|
||||
<height>683</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Temporal Graph</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCustomPlot" name="graphingView" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QCustomPlot</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qcustomplot.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user