The main screen, flowview, and graphing screens are now linked. If you double click a frame on the main window or a graph in flowview or the graphing window the other two windows will update to show that data as well.
This commit is contained in:
@@ -398,6 +398,21 @@ void CANFrameModel::insertFrames(const QVector<CANFrame> &newFrames)
|
||||
if (needFilterRefresh) emit updatedFiltersList();
|
||||
}
|
||||
|
||||
int CANFrameModel::getIndexFromTimeID(int ID, double timestamp)
|
||||
{
|
||||
int bestIndex = -1;
|
||||
uint64_t intTimeStamp = timestamp * 1000000l;
|
||||
for (int i = 0; i < frames.count(); i++)
|
||||
{
|
||||
if ((frames[i].ID == ID))
|
||||
{
|
||||
if (frames[i].timestamp <= intTimeStamp) bestIndex = i;
|
||||
else break; //drop out of loop as soon as we pass the proper timestamp
|
||||
}
|
||||
}
|
||||
return bestIndex;
|
||||
}
|
||||
|
||||
void CANFrameModel::loadFilterFile(QString filename)
|
||||
{
|
||||
QFile *inFile = new QFile(filename);
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
void recalcOverwrite();
|
||||
bool needsFilterRefresh();
|
||||
void insertFrames(const QVector<CANFrame> &newFrames);
|
||||
int getIndexFromTimeID(int ID, double timestamp);
|
||||
const QVector<CANFrame> *getListReference() const; //thou shalt not modify these frames externally!
|
||||
const QVector<CANFrame> *getFilteredListReference() const; //Thus saith the Lord, NO.
|
||||
const QMap<int, bool> *getFiltersReference() const; //this neither
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef CONFIG
|
||||
#define CONFIG
|
||||
|
||||
#define VERSION 135
|
||||
#define VERSION 136
|
||||
|
||||
//try to keep this in sync.
|
||||
//SavvyCAN will complain if you connect a GVRET board with a revision
|
||||
|
||||
+54
-1
@@ -67,7 +67,8 @@ FlowViewWindow::FlowViewWindow(const QVector<CANFrame> *frames, QWidget *parent)
|
||||
connect(ui->spinPlayback, SIGNAL(valueChanged(int)), this, SLOT(changePlaybackSpeed(int)));
|
||||
connect(ui->cbLoopPlayback, SIGNAL(clicked(bool)), this, SLOT(changeLooping(bool)));
|
||||
connect(ui->listFrameID, SIGNAL(currentTextChanged(QString)), this, SLOT(changeID(QString)));
|
||||
connect(playbackTimer, SIGNAL(timeout()), this, SLOT(timerTriggered()));
|
||||
connect(playbackTimer, SIGNAL(timeout()), this, SLOT(timerTriggered()));
|
||||
connect(ui->graphView, SIGNAL(plottableDoubleClick(QCPAbstractPlottable*,QMouseEvent*)), this, SLOT(plottableDoubleClick(QCPAbstractPlottable*,QMouseEvent*)));
|
||||
|
||||
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
|
||||
|
||||
@@ -143,6 +144,58 @@ void FlowViewWindow::writeSettings()
|
||||
}
|
||||
}
|
||||
|
||||
void FlowViewWindow::plottableDoubleClick(QCPAbstractPlottable* plottable, QMouseEvent* event)
|
||||
{
|
||||
int id = 0;
|
||||
//apply transforms to get the X axis value where we double clicked
|
||||
double coord = plottable->keyAxis()->pixelToCoord(event->localPos().x());
|
||||
if (frameCache.count() > 0) id = frameCache[0].ID;
|
||||
if (secondsMode) emit sendCenterTimeID(id, coord);
|
||||
else emit sendCenterTimeID(id, coord / 1000000.0);
|
||||
}
|
||||
|
||||
void FlowViewWindow::gotCenterTimeID(int32_t ID, double timestamp)
|
||||
{
|
||||
if (secondsMode) timestamp *= 1000000.0; //frames always store timestamp in microseconds
|
||||
|
||||
qDebug() << "timestamp: " << timestamp;
|
||||
|
||||
changeID(QString::number(ID)); //to be sure we're focused on the proper ID
|
||||
|
||||
for (int j = 0; j < ui->listFrameID->count(); j++)
|
||||
{
|
||||
int thisNum = Utility::ParseStringToNum(ui->listFrameID->item(j)->text());
|
||||
if (thisNum == ID)
|
||||
{
|
||||
ui->listFrameID->setCurrentRow(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int bestIdx = -1;
|
||||
for (int i = 0; i < frameCache.count(); i++)
|
||||
{
|
||||
if (frameCache[i].timestamp > timestamp)
|
||||
{
|
||||
bestIdx = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qDebug() << "Best index " << bestIdx;
|
||||
if (bestIdx > -1)
|
||||
{
|
||||
currentPosition = bestIdx;
|
||||
if (ui->cbAutoRef->isChecked())
|
||||
{
|
||||
memcpy(refBytes, currBytes, 8);
|
||||
}
|
||||
|
||||
memcpy(currBytes, frameCache.at(currentPosition).data, 8);
|
||||
|
||||
updateDataView();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowViewWindow::contextMenuRequestFlow(QPoint pos)
|
||||
{
|
||||
QMenu *menu = new QMenu(this);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define FLOWVIEWWINDOW_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "qcustomplot.h"
|
||||
#include "can_structs.h"
|
||||
|
||||
namespace Ui {
|
||||
@@ -33,6 +34,11 @@ private slots:
|
||||
void contextMenuRequestGraph(QPoint pos);
|
||||
void saveFileFlow();
|
||||
void saveFileGraph();
|
||||
void plottableDoubleClick(QCPAbstractPlottable* plottable, QMouseEvent* event);
|
||||
void gotCenterTimeID(int32_t ID, double timestamp);
|
||||
|
||||
signals:
|
||||
void sendCenterTimeID(int32_t ID, double timestamp);
|
||||
|
||||
private:
|
||||
Ui::FlowViewWindow *ui;
|
||||
|
||||
+33
-1
@@ -45,6 +45,7 @@ GraphingWindow::GraphingWindow(DBCHandler *handler, const QVector<CANFrame> *fra
|
||||
connect(ui->graphingView, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
|
||||
//connect up the mouse controls
|
||||
connect(ui->graphingView, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress()));
|
||||
connect(ui->graphingView, SIGNAL(plottableDoubleClick(QCPAbstractPlottable*,QMouseEvent*)), this, SLOT(plottableDoubleClick(QCPAbstractPlottable*,QMouseEvent*)));
|
||||
connect(ui->graphingView, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheel()));
|
||||
|
||||
// make bottom and left axes transfer their ranges to top and right axes:
|
||||
@@ -152,6 +153,32 @@ void GraphingWindow::updatedFrames(int numFrames)
|
||||
}
|
||||
}
|
||||
|
||||
void GraphingWindow::plottableDoubleClick(QCPAbstractPlottable* plottable, QMouseEvent* event)
|
||||
{
|
||||
int id = 0;
|
||||
//apply transforms to get the X axis value where we double clicked
|
||||
double coord = plottable->keyAxis()->pixelToCoord(event->localPos().x());
|
||||
id = plottable->property("id").toInt();
|
||||
if (secondsMode) emit sendCenterTimeID(id, coord);
|
||||
else emit sendCenterTimeID(id, coord / 1000000.0);
|
||||
}
|
||||
|
||||
void GraphingWindow::gotCenterTimeID(int32_t ID, double timestamp)
|
||||
{
|
||||
//its problematic to try to highlight a graph since we get the ID
|
||||
//and timestamp not the signal in question so there is no real way
|
||||
//to know which graph. But, if that changes here is a stub
|
||||
//for (int i = 0; i < graphParams.count(); i++)
|
||||
//{
|
||||
//}
|
||||
|
||||
QCPRange range = ui->graphingView->xAxis->range();
|
||||
double offset = range.size() / 2.0;
|
||||
if (!secondsMode) timestamp *= 1000000.0; //timestamp is always in seconds when being passed so convert if necessary
|
||||
ui->graphingView->xAxis->setRange(timestamp - offset, timestamp + offset);
|
||||
ui->graphingView->replot();
|
||||
}
|
||||
|
||||
void GraphingWindow::titleDoubleClick(QMouseEvent* event, QCPPlotTitle* title)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
@@ -802,6 +829,9 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
||||
}
|
||||
}
|
||||
|
||||
params.xbias = 0;
|
||||
|
||||
/*
|
||||
for (int ct = 0; ct < params.x.count(); ct++)
|
||||
{
|
||||
params.x[ct] -= xminval;
|
||||
@@ -809,9 +839,10 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
||||
params.xbias = xminval;
|
||||
xmaxval -= xminval;
|
||||
xminval = 0;
|
||||
*/
|
||||
|
||||
ui->graphingView->addGraph();
|
||||
params.ref = ui->graphingView->graph();
|
||||
params.ref = ui->graphingView->graph();
|
||||
if (createGraphParam)
|
||||
{
|
||||
graphParams.append(params);
|
||||
@@ -826,6 +857,7 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam)
|
||||
if ((params.endByte != -1) && (params.endByte != params.startByte)) params.graphName += "-" + QString::number(params.endByte);
|
||||
}
|
||||
ui->graphingView->graph()->setName(params.graphName);
|
||||
ui->graphingView->graph()->setProperty("id", params.ID);
|
||||
|
||||
ui->graphingView->graph()->setData(refParam->x,refParam->y);
|
||||
ui->graphingView->graph()->setLineStyle(QCPGraph::lsLine); //connect points with lines
|
||||
|
||||
@@ -42,6 +42,7 @@ private slots:
|
||||
void titleDoubleClick(QMouseEvent *event, QCPPlotTitle *title);
|
||||
void axisLabelDoubleClick(QCPAxis* axis, QCPAxis::SelectablePart part);
|
||||
void legendDoubleClick(QCPLegend* legend, QCPAbstractLegendItem* item);
|
||||
void plottableDoubleClick(QCPAbstractPlottable* plottable,QMouseEvent* event);
|
||||
void selectionChanged();
|
||||
void mousePress();
|
||||
void mouseWheel();
|
||||
@@ -57,6 +58,10 @@ private slots:
|
||||
void appendToGraph(GraphParams ¶ms, CANFrame &frame);
|
||||
void editSelectedGraph();
|
||||
void updatedFrames(int);
|
||||
void gotCenterTimeID(int32_t ID, double timestamp);
|
||||
|
||||
signals:
|
||||
void sendCenterTimeID(int32_t ID, double timestamp);
|
||||
|
||||
private:
|
||||
Ui::GraphingWindow *ui;
|
||||
|
||||
+39
-2
@@ -126,6 +126,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
connect(ui->actionLoad_DBC_File, SIGNAL(triggered(bool)), this, SLOT(handleLoadDBC()));
|
||||
connect(ui->actionSave_DBC_File, SIGNAL(triggered(bool)), this, SLOT(handleSaveDBC()));
|
||||
connect(ui->canFramesView, SIGNAL(clicked(QModelIndex)), this, SLOT(gridClicked(QModelIndex)));
|
||||
connect(ui->canFramesView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(gridDoubleClicked(QModelIndex)));
|
||||
connect(ui->cbInterpret, SIGNAL(toggled(bool)), this, SLOT(interpretToggled(bool)));
|
||||
connect(ui->cbOverwrite, SIGNAL(toggled(bool)), this, SLOT(overwriteToggled(bool)));
|
||||
connect(ui->actionEdit_Messages_Signals, SIGNAL(triggered(bool)), this, SLOT(showDBCEditor()));
|
||||
@@ -263,7 +264,8 @@ void MainWindow::readUpdateableSettings()
|
||||
useHex = settings.value("Main/UseHex", true).toBool();
|
||||
model->setHexMode(useHex);
|
||||
Utility::decimalMode = !useHex;
|
||||
model->setSecondsMode(settings.value("Main/TimeSeconds", false).toBool());
|
||||
secondsMode = settings.value("Main/TimeSeconds", false).toBool();
|
||||
model->setSecondsMode(secondsMode);
|
||||
useFiltered = settings.value("Main/UseFiltered", false).toBool();
|
||||
}
|
||||
|
||||
@@ -289,6 +291,13 @@ void MainWindow::gridClicked(QModelIndex idx)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::gridDoubleClicked(QModelIndex idx)
|
||||
{
|
||||
//grab ID and timestamp and send them away
|
||||
CANFrame frame = model->getListReference()->at(idx.row());
|
||||
emit sendCenterTimeID(frame.ID, frame.timestamp / 1000000.0);
|
||||
}
|
||||
|
||||
void MainWindow::interpretToggled(bool state)
|
||||
{
|
||||
model->setInterpetMode(state);
|
||||
@@ -383,6 +392,17 @@ void MainWindow::addFrameToDisplay(CANFrame &frame, bool autoRefresh = false)
|
||||
}
|
||||
}
|
||||
|
||||
//A sub-window is sending us a center on timestamp and ID signal
|
||||
//try to find the relevant frame in the list and focus on it.
|
||||
void MainWindow::gotCenterTimeID(int32_t ID, double timestamp)
|
||||
{
|
||||
int idx = model->getIndexFromTimeID(ID, timestamp);
|
||||
if (idx > -1)
|
||||
{
|
||||
ui->canFramesView->selectRow(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::clearFrames()
|
||||
{
|
||||
ui->canFramesView->scrollToTop();
|
||||
@@ -397,6 +417,7 @@ void MainWindow::clearFrames()
|
||||
void MainWindow::normalizeTiming()
|
||||
{
|
||||
model->normalizeTiming();
|
||||
emit framesUpdated(-2); //claim an all new set of frames because every frame was updated.
|
||||
}
|
||||
|
||||
void MainWindow::changeBaudRates()
|
||||
@@ -900,6 +921,14 @@ void MainWindow::showGraphingWindow()
|
||||
{
|
||||
if (!graphingWindow) {
|
||||
graphingWindow = new GraphingWindow(dbcHandler, model->getListReference());
|
||||
connect(graphingWindow, SIGNAL(sendCenterTimeID(int32_t,double)), this, SLOT(gotCenterTimeID(int32_t,double)));
|
||||
connect(this, SIGNAL(sendCenterTimeID(int32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
|
||||
}
|
||||
|
||||
if (flowViewWindow) //connect the two external windows together
|
||||
{
|
||||
connect(graphingWindow, SIGNAL(sendCenterTimeID(int32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
|
||||
connect(flowViewWindow, SIGNAL(sendCenterTimeID(int32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
|
||||
}
|
||||
graphingWindow->show();
|
||||
}
|
||||
@@ -987,11 +1016,19 @@ void MainWindow::showFlowViewWindow()
|
||||
flowViewWindow = new FlowViewWindow(model->getListReference());
|
||||
else
|
||||
flowViewWindow = new FlowViewWindow(model->getFilteredListReference());
|
||||
connect(flowViewWindow, SIGNAL(sendCenterTimeID(int32_t,double)), this, SLOT(gotCenterTimeID(int32_t,double)));
|
||||
connect(this, SIGNAL(sendCenterTimeID(int32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
|
||||
}
|
||||
|
||||
if (graphingWindow)
|
||||
{
|
||||
connect(graphingWindow, SIGNAL(sendCenterTimeID(int32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
|
||||
connect(flowViewWindow, SIGNAL(sendCenterTimeID(int32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
|
||||
}
|
||||
|
||||
flowViewWindow->show();
|
||||
}
|
||||
|
||||
|
||||
//this one always gets the unfiltered list intentionally.
|
||||
void MainWindow::showDBCEditor()
|
||||
{
|
||||
|
||||
+4
-1
@@ -59,6 +59,7 @@ private slots:
|
||||
void gotDeviceInfo(int, int);
|
||||
void connectionSucceeded(int, int);
|
||||
void gridClicked(QModelIndex);
|
||||
void gridDoubleClicked(QModelIndex);
|
||||
void interpretToggled(bool);
|
||||
void overwriteToggled(bool);
|
||||
void showDBCEditor();
|
||||
@@ -72,7 +73,7 @@ private slots:
|
||||
public slots:
|
||||
void gotFrames(int, int);
|
||||
void updateSettings();
|
||||
|
||||
void gotCenterTimeID(int32_t ID, double timestamp);
|
||||
|
||||
signals:
|
||||
void sendSerialPort(QSerialPortInfo *port);
|
||||
@@ -85,6 +86,7 @@ signals:
|
||||
//-1 = frames cleared, -2 = a new file has been loaded (so all frames are different), otherwise # of new frames
|
||||
void framesUpdated(int numFrames); //something has updated the frame list
|
||||
void settingsUpdated();
|
||||
void sendCenterTimeID(int32_t ID, double timestamp);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
@@ -100,6 +102,7 @@ private:
|
||||
bool inhibitFilterUpdate;
|
||||
bool useHex;
|
||||
bool allowCapture;
|
||||
bool secondsMode;
|
||||
bool bDirty; //have frames been added or subtracted since the last save/load?
|
||||
bool useFiltered; //should sub-windows use the unfiltered or filtered frames list?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user