Added ability to create multiple graphing windows that act separately.

Added ability to right check on signals in main view and graph them
directly.
This commit is contained in:
Collin Kidder
2021-05-02 12:48:47 -04:00
parent e7561878d7
commit 35c1ef5387
7 changed files with 185 additions and 40 deletions
+1 -1
View File
@@ -1944,7 +1944,7 @@ DBC_MESSAGE* DBCHandler::findMessageForFilter(uint32_t id, MatchingCriteria_t *
DBC_MESSAGE* msg = loadedFiles[i].messageHandler->findMsgByID(id);
if (msg != nullptr)
{
*matchingCriteria = loadedFiles[i].messageHandler->getMatchingCriteria();
if (matchingCriteria) *matchingCriteria = loadedFiles[i].messageHandler->getMatchingCriteria();
return msg;
}
}
+128 -30
View File
@@ -64,7 +64,7 @@ MainWindow::MainWindow(QWidget *parent) :
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
connect(HorzHdr, SIGNAL(sectionClicked(int)), this, SLOT(headerClicked(int)));
graphingWindow = nullptr;
lastGraphingWindow = nullptr;
frameInfoWindow = nullptr;
playbackWindow = nullptr;
flowViewWindow = nullptr;
@@ -95,11 +95,11 @@ MainWindow::MainWindow(QWidget *parent) :
continuousLogging = false;
continuousLogFlushCounter = 0;
//handlers for all menu entries
connect(ui->actionSetup, SIGNAL(triggered(bool)), SLOT(showConnectionSettingsWindow()));
connect(ui->actionOpen_Log_File, &QAction::triggered, this, &MainWindow::handleLoadFile);
connect(ui->actionGraph_Dta, &QAction::triggered, this, &MainWindow::showGraphingWindow);
connect(ui->actionFrame_Data_Analysis, &QAction::triggered, this, &MainWindow::showFrameDataAnalysis);
connect(ui->btnClearFrames, &QAbstractButton::clicked, this, &MainWindow::clearFrames);
connect(ui->actionSave_Log_File, &QAction::triggered, this, &MainWindow::handleSaveFile);
connect(ui->actionSave_Filtered_Log_File, &QAction::triggered, this, &MainWindow::handleSaveFilteredFile);
connect(ui->actionLoad_Filter_Definition, &QAction::triggered, this, &MainWindow::handleLoadFilters);
@@ -107,11 +107,6 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->action_Playback, &QAction::triggered, this, &MainWindow::showPlaybackWindow);
connect(ui->actionFlow_View, &QAction::triggered, this, &MainWindow::showFlowViewWindow);
connect(ui->action_Custom, &QAction::triggered, this, &MainWindow::showFrameSenderWindow);
connect(ui->canFramesView, &QAbstractItemView::pressed, this, &MainWindow::gridClicked);
connect(ui->canFramesView, &QAbstractItemView::doubleClicked, this, &MainWindow::gridDoubleClicked);
connect(ui->cbInterpret, &QAbstractButton::toggled, this, &MainWindow::interpretToggled);
connect(ui->cbOverwrite, &QAbstractButton::toggled, this, &MainWindow::overwriteToggled);
connect(ui->btnCaptureToggle, &QAbstractButton::clicked, this, &MainWindow::toggleCapture);
connect(ui->actionExit_Application, &QAction::triggered, this, &MainWindow::exitApp);
connect(ui->actionFuzzy_Scope, &QAction::triggered, this, &MainWindow::showFuzzyScopeWindow);
connect(ui->actionRange_State_2, &QAction::triggered, this, &MainWindow::showRangeWindow);
@@ -120,13 +115,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->actionFile_Comparison, &QAction::triggered, this, &MainWindow::showComparisonWindow);
connect(ui->actionDBC_Comparison, &QAction::triggered, this, &MainWindow::showDBCComparisonWindow);
connect(ui->actionScripting_INterface, &QAction::triggered, this, &MainWindow::showScriptingWindow);
connect(ui->btnNormalize, &QAbstractButton::clicked, this, &MainWindow::normalizeTiming);
connect(ui->actionPreferences, &QAction::triggered, this, &MainWindow::showSettingsDialog);
connect(model, &CANFrameModel::updatedFiltersList, this, &MainWindow::updateFilterList);
connect(ui->listFilters, &QListWidget::itemChanged, this, &MainWindow::filterListItemChanged);
connect(ui->listBusFilters, &QListWidget::itemChanged, this, &MainWindow::busFilterListItemChanged);
connect(ui->btnFilterAll, &QAbstractButton::clicked, this, &MainWindow::filterSetAll);
connect(ui->btnFilterNone, &QAbstractButton::clicked, this, &MainWindow::filterClearAll);
connect(ui->actionFirmware_Update, &QAction::triggered, this, &MainWindow::showFirmwareUploaderWindow);
connect(ui->actionDBC_File_Manager, &QAction::triggered, this, &MainWindow::showDBCFileWindow);
connect(ui->actionFuzzing, &QAction::triggered, this, &MainWindow::showFuzzingWindow);
@@ -138,14 +127,31 @@ MainWindow::MainWindow(QWidget *parent) :
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);
//handlers fror interactions with the main can frame view table
connect(ui->canFramesView, &QAbstractItemView::clicked, this, &MainWindow::gridClicked);
connect(ui->canFramesView, &QAbstractItemView::doubleClicked, this, &MainWindow::gridDoubleClicked);
ui->canFramesView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->canFramesView, &QAbstractItemView::customContextMenuRequested, this, &MainWindow::gridContextMenuRequest);
connect(model, &CANFrameModel::updatedFiltersList, this, &MainWindow::updateFilterList);
connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames);
//new implementation for continuous logging
connect(CANConManager::getInstance(), &CANConManager::framesReceived, this, &MainWindow::logReceivedFrame);
connect(ui->cbInterpret, &QAbstractButton::toggled, this, &MainWindow::interpretToggled);
connect(ui->cbOverwrite, &QAbstractButton::toggled, this, &MainWindow::overwriteToggled);
connect(ui->listFilters, &QListWidget::itemChanged, this, &MainWindow::filterListItemChanged);
connect(ui->listBusFilters, &QListWidget::itemChanged, this, &MainWindow::busFilterListItemChanged);
connect(ui->btnCaptureToggle, &QAbstractButton::clicked, this, &MainWindow::toggleCapture);
connect(ui->btnClearFrames, &QAbstractButton::clicked, this, &MainWindow::clearFrames);
connect(ui->btnNormalize, &QAbstractButton::clicked, this, &MainWindow::normalizeTiming);
connect(ui->btnFilterAll, &QAbstractButton::clicked, this, &MainWindow::filterSetAll);
connect(ui->btnFilterNone, &QAbstractButton::clicked, this, &MainWindow::filterClearAll);
connect(ui->btnExpandAll, &QAbstractButton::clicked, this, &MainWindow::expandAllRows);
connect(ui->btnCollapseAll, &QAbstractButton::clicked, this, &MainWindow::collapseAllRows);
connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames);
//new implementation for continuous logging:
connect(CANConManager::getInstance(), &CANConManager::framesReceived, this, &MainWindow::logReceivedFrame);
lbStatusConnected.setText(tr("Connected to 0 buses"));
lbHelp.setText(tr("Press F1 on any screen for help"));
lbHelp.setAlignment(Qt::AlignCenter);
@@ -223,7 +229,10 @@ MainWindow::~MainWindow()
//but eventually each window should be registered and be able to be iterated.
void MainWindow::killEmAll()
{
killWindow(graphingWindow);
foreach (GraphingWindow *win, graphWindows)
{
killWindow(win);
}
killWindow(frameInfoWindow);
killWindow(playbackWindow);
killWindow(flowViewWindow);
@@ -472,12 +481,87 @@ void MainWindow::gridClicked(QModelIndex idx)
void MainWindow::gridDoubleClicked(QModelIndex idx)
{
//qDebug() << "Grid double clicked";
qDebug() << "Grid double clicked";
//grab ID and timestamp and send them away
CANFrame frame = model->getListReference()->at(idx.row());
emit sendCenterTimeID(frame.frameId(), frame.timeStamp().microSeconds() / 1000000.0);
}
void MainWindow::gridContextMenuRequest(QPoint pos)
{
QModelIndex idx = ui->canFramesView->indexAt(pos); //figure out where in the view we clicked (row, column)
qDebug() << "Pos: " << pos << " Row :" << idx.row() << " Col: " << idx.column();
qDebug() << "Data: " << idx.data();
if (idx.column() == 8) //we're over the DATA column
{
contextMenuPosition = pos;
QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
menu->addAction(tr("Add to a new graphing window"), this, SLOT(setupAddToNewGraph()));
menu->addSeparator();
menu->addAction(tr("Add to latest graphing window"), this, SLOT(setupSendToLatestGraphWindow()));
menu->popup(ui->canFramesView->mapToGlobal(pos));
}
}
QString MainWindow::getSignalNameFromPosition(QPoint pos)
{
//there's a bit of an issue to solve. The data column is one big string even if there are a number
//of signals in there. So, the basic idea is to find out how tall the font is and where the user
//clicked within the cell. Then find out which line that puts us over.
QModelIndex idx = ui->canFramesView->indexAt(pos); //figure out where in the view we clicked (row, column)
int fontHeight = ui->canFramesView->fontMetrics().height();
int cellBaseY = ui->canFramesView->rowViewportPosition(idx.row());
int lineOffset = (pos.y() - cellBaseY) / fontHeight;
qDebug() << "Offset: " << lineOffset;
QString lineText = idx.data().toString().split("\n")[lineOffset];
qDebug() << "Line Text: " << lineText;
return lineText.split(":")[0];
}
uint32_t MainWindow::getMessageIDFromPosition(QPoint pos)
{
QModelIndex idx = ui->canFramesView->indexAt(pos); //figure out where in the view we clicked (row, column)
QString idText = ui->canFramesView->model()->index(idx.row(), 1).data().toString();
return Utility::ParseStringToNum(idText);
}
void MainWindow::setupAddToNewGraph()
{
showGraphingWindow(); //creates a new window and sets it as latest
setupSendToLatestGraphWindow(); //then call the other function to finish
}
void MainWindow::setupSendToLatestGraphWindow()
{
if (!lastGraphingWindow) showGraphingWindow();
GraphParams param;
QString signalName = getSignalNameFromPosition(contextMenuPosition);
param.ID = getMessageIDFromPosition(contextMenuPosition);
DBC_MESSAGE *msg = dbcHandler->findMessageForFilter(param.ID, nullptr);
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(signalName);
param.associatedSignal = sig;
param.bias = sig->bias;
param.intelFormat = sig->intelByteOrder;
param.isSigned = sig->valType == SIGNED_INT ? true : false;
param.numBits = sig->signalSize;
param.scale = sig->factor;
param.startBit = sig->startBit;
param.stride = 1;
param.graphName = sig->name;
param.lineColor = QColor(QRandomGenerator::global()->bounded(160), QRandomGenerator::global()->bounded(160), QRandomGenerator::global()->bounded(160));
param.lineWidth = 1;
param.fillColor = QColor(128, 128, 128, 0);
param.mask = 0xFFFFFFFFFFFFFFFFull;
param.drawOnlyPoints = false;
param.pointType = 0;
lastGraphingWindow->createGraph(param); //add the new graph to the window
}
void MainWindow::interpretToggled(bool state)
{
model->setInterpretMode(state);
@@ -954,20 +1038,34 @@ void MainWindow::showSettingsDialog()
}
//always gets unfiltered list. You ask for the graphs so there is no need to send filtered frames
//now always creates a new window. This allows for multiple independent graphing windows
void MainWindow::showGraphingWindow()
{
if (!graphingWindow) {
graphingWindow = new GraphingWindow(model->getListReference());
connect(graphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), this, SLOT(gotCenterTimeID(int32_t,double)));
connect(this, SIGNAL(sendCenterTimeID(uint32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
/* could only allow the latest window to have these centering signals.
if (lastGraphingWindow)
{
disconnect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), this, SLOT(gotCenterTimeID(int32_t,double)));
disconnect(this, SIGNAL(sendCenterTimeID(uint32_t,double)), lastGraphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
if (flowViewWindow)
{
disconnect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
disconnect(flowViewWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), lastGraphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
}
}
*/
lastGraphingWindow = new GraphingWindow(model->getListReference());
graphWindows.append(lastGraphingWindow);
connect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), this, SLOT(gotCenterTimeID(int32_t,double)));
connect(this, SIGNAL(sendCenterTimeID(uint32_t,double)), lastGraphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
if (flowViewWindow) //connect the two external windows together
{
connect(graphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
connect(flowViewWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
connect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
connect(flowViewWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), lastGraphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
}
graphingWindow->show();
lastGraphingWindow->show();
}
void MainWindow::showTemporalGraphWindow()
@@ -1148,10 +1246,10 @@ void MainWindow::showFlowViewWindow()
connect(this, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
}
if (graphingWindow)
if (lastGraphingWindow)
{
connect(graphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
connect(flowViewWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
connect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
connect(flowViewWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), lastGraphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
}
flowViewWindow->show();
+11 -1
View File
@@ -92,6 +92,9 @@ private slots:
void connectionStatusUpdated(int conns);
void gridClicked(QModelIndex);
void gridDoubleClicked(QModelIndex);
void gridContextMenuRequest(QPoint pos);
void setupAddToNewGraph();
void setupSendToLatestGraphWindow();
void interpretToggled(bool);
void overwriteToggled(bool);
void logReceivedFrame(CANConnection*, QVector<CANFrame>);
@@ -147,7 +150,11 @@ private:
int continuousLogFlushCounter;
//References to other windows we can display
GraphingWindow *graphingWindow;
//Graph window is allowed to instantiate more than once. All the rest are not (yet).
GraphingWindow *lastGraphingWindow;
QList<GraphingWindow *> graphWindows;
FrameInfoWindow *frameInfoWindow;
FramePlaybackWindow *playbackWindow;
FlowViewWindow *flowViewWindow;
@@ -178,8 +185,11 @@ private:
QLabel lbHelp;
int normalRowHeight;
bool isConnected;
QPoint contextMenuPosition;
//private methods
QString getSignalNameFromPosition(QPoint pos);
uint32_t getMessageIDFromPosition(QPoint pos);
void saveDecodedTextFile(QString);
void addFrameToDisplay(CANFrame &, bool);
void updateFileStatus();
+36 -2
View File
@@ -120,6 +120,26 @@ void GraphingWindow::closeEvent(QCloseEvent *event)
writeSettings();
}
void GraphingWindow::changeEvent(QEvent *event)
{
QWidget::changeEvent(event);
if (event->type() == QEvent::ActivationChange)
{
if(this->isActiveWindow())
{
setWindowOpacity(1);
ui->graphingView->repaint();
qDebug() << "Show";
}
else
{
setWindowOpacity(0.25);
// widget is now inactive
qDebug() << "Hide";
}
}
}
void GraphingWindow::readSettings()
{
QSettings settings;
@@ -268,6 +288,8 @@ void GraphingWindow::gotCenterTimeID(int32_t ID, double timestamp)
//{
//}
qDebug() << "Trying to center graph on timestamp: " << timestamp;
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
@@ -1312,6 +1334,17 @@ void GraphingWindow::createGraph(GraphParams &params, bool createGraphParam)
ui->graphingView->graph()->setBrush(fillBrush);
}
double xRange = (xmaxval - xminval);
double yRange = (ymaxval - yminval);
double xMid = xminval + (xRange / 2.0);
double yMid = yminval + (yRange / 2.0);
//creates a slightly larger view than the actual boundary values to give some padding
xminval = xMid - (xRange / 1.95);
xmaxval = xMid + (xRange / 1.95);
yminval = yMid - (yRange / 1.85);
ymaxval = yMid + (yRange / 1.85);
qDebug() << "xmin: " << xminval;
qDebug() << "xmax: " << xmaxval;
qDebug() << "ymin: " << yminval;
@@ -1320,10 +1353,11 @@ void GraphingWindow::createGraph(GraphParams &params, bool createGraphParam)
if (needScaleSetup)
{
needScaleSetup = false;
ui->graphingView->xAxis->setRange(xminval, xmaxval);
ui->graphingView->yAxis->setRange(yminval, ymaxval);
ui->graphingView->xAxis->setRange(xminval, xmaxval);
ui->graphingView->axisRect()->setupFullAxesBox();
}
//always recalculate Y range so that new graphs actually show up in view
ui->graphingView->yAxis->setRange(yminval, ymaxval);
ui->graphingView->replot();
}
+5 -2
View File
@@ -45,6 +45,9 @@ public:
~GraphingWindow();
void showEvent(QShowEvent*);
public slots:
void createGraph(GraphParams &params, bool createGraphParam = true);
private slots:
void titleDoubleClick(QMouseEvent *event, QCPTextElement *title);
void axisDoubleClick(QCPAxis* axis, QCPAxis::SelectablePart part);
@@ -66,8 +69,7 @@ private slots:
void rescaleAxis(QCPAxis* axis);
void rescaleToData();
void toggleFollowMode();
void addNewGraph();
void createGraph(GraphParams &params, bool createGraphParam = true);
void addNewGraph();
void appendToGraph(GraphParams &params, CANFrame &frame, QVector<double> &x, QVector<double> &y);
void editSelectedGraph();
void updatedFrames(int);
@@ -99,6 +101,7 @@ private:
void readSettings();
void writeSettings();
bool eventFilter(QObject *obj, QEvent *event);
void changeEvent(QEvent *event);
};
#endif // GRAPHINGWINDOW_H
+2 -2
View File
@@ -18,8 +18,8 @@
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
<width>700</width>
<height>300</height>
</size>
</property>
<property name="windowTitle">
+2 -2
View File
@@ -361,7 +361,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menu_RE_Tools">
@@ -447,7 +447,7 @@
</action>
<action name="actionGraph_Dta">
<property name="text">
<string>Graph Data</string>
<string>New Graphing Window</string>
</property>
</action>
<action name="actionOpen_Log_File">