...to graphing window and signal viewer so complex systems with message name duplication (eg "Status") works well. DBCHandler class has a new function to find a msg by fully qualified node name...Utility class defines the qualified name seperator, right now it is :: and is used thusly filenameNoExtension::nodeName for display in the node dropdown (because nodes can be common between dbc files). To get the message from the system you use the findMessage function in dbchandler and pass the msgName and the fully qualified node name. This is about as unique as we can get, second only to message ID. Added node comboBox to graph signal editor for easier data filtering (took the same implementation that was in signal viewer, and tuned up both of them)
399 lines
12 KiB
C++
399 lines
12 KiB
C++
#include "signalviewerwindow.h"
|
|
#include "ui_signalviewerwindow.h"
|
|
#include "helpwindow.h"
|
|
#include "mainwindow.h"
|
|
#include "utility.h"
|
|
#include <QDebug>
|
|
|
|
#define MSG_COL 1
|
|
#define VALUE_COL 2
|
|
|
|
SignalViewerWindow::SignalViewerWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
|
QDialog(parent),
|
|
ui(new Ui::SignalViewerWindow)
|
|
{
|
|
ui->setupUi(this);
|
|
setWindowFlags(Qt::Window);
|
|
|
|
modelFrames = frames;
|
|
|
|
QStringList headers;
|
|
headers << "Node" << "Signal" << "Value";
|
|
ui->tableViewer->setHorizontalHeaderLabels(headers);
|
|
ui->tableViewer->setColumnWidth(0, 100);
|
|
ui->tableViewer->setColumnWidth(1, 150);
|
|
|
|
QSettings settings;
|
|
QFont sysFont;
|
|
int fontSize = settings.value("Main/FontSize", 9).toUInt();
|
|
if(settings.value("Main/FontFixedWidth", false).toBool())
|
|
sysFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); //get default fixed width font
|
|
else
|
|
sysFont = QFont(); //get default font
|
|
sysFont.setPointSize(fontSize);
|
|
ui->tableViewer->setFont(sysFont);
|
|
|
|
QHeaderView *HorzHdr = ui->tableViewer->horizontalHeader();
|
|
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
|
|
HorzHdr->setFont(QFont());
|
|
|
|
QHeaderView *verticalHeader = ui->tableViewer->verticalHeader();
|
|
verticalHeader->setFont(QFont());
|
|
|
|
dbcHandler = DBCHandler::getReference();
|
|
currentlySelectedMsg = nullptr;
|
|
|
|
connect(ui->cbNodes, SIGNAL(currentIndexChanged(int)), this, SLOT(loadMessages(int)));
|
|
connect(ui->cbMessages, SIGNAL(currentIndexChanged(int)), this, SLOT(loadSignals(int)));
|
|
connect(ui->btnAdd, SIGNAL(clicked(bool)), this, SLOT(addSignal()));
|
|
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
|
|
connect(ui->btnRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedSignal()));
|
|
connect(ui->btnSave, SIGNAL(clicked(bool)), this, SLOT(saveSignalsFile()));
|
|
connect(ui->btnLoad, SIGNAL(clicked(bool)), this, SLOT(loadSignalsFile()));
|
|
connect(ui->btnAppend, SIGNAL(clicked(bool)), this, SLOT(appendSignalsFile()));
|
|
connect(ui->btnClear, SIGNAL(clicked(bool)), this, SLOT(clearSignalsTable()));
|
|
|
|
loadNodes();
|
|
}
|
|
|
|
SignalViewerWindow::~SignalViewerWindow()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void SignalViewerWindow::updatedFrames(int numFrames)
|
|
{
|
|
CANFrame thisFrame;
|
|
|
|
if (numFrames == -1) //all frames deleted. Don't care
|
|
{
|
|
}
|
|
else if (numFrames == -2) //all new set of frames. Reset
|
|
{
|
|
for (int i = 0; i < modelFrames->count(); i++)
|
|
{
|
|
thisFrame = modelFrames->at(i);
|
|
processFrame(thisFrame);
|
|
}
|
|
}
|
|
else //just got some new frames. See if they are relevant.
|
|
{
|
|
if (numFrames > modelFrames->count()) return;
|
|
|
|
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
|
|
{
|
|
thisFrame = modelFrames->at(i);
|
|
processFrame(thisFrame);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SignalViewerWindow::processFrame(CANFrame &frame)
|
|
{
|
|
QString sigString;
|
|
DBC_SIGNAL *sig;
|
|
for (int i = 0; i < signalList.count(); i++)
|
|
{
|
|
sig = signalList.at(i);
|
|
if (!sig) return;
|
|
if (sig->parentMessage->ID == frame.frameId())
|
|
{
|
|
if (sig->processAsText(frame, sigString, false)) //if true we could interpret the signal so update it in the list
|
|
{
|
|
QTableWidgetItem *item = ui->tableViewer->item(i, VALUE_COL);
|
|
if (!item)
|
|
{
|
|
item = new QTableWidgetItem(sigString);
|
|
ui->tableViewer->setItem(i, VALUE_COL, item);
|
|
}
|
|
else item->setText(sigString);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SignalViewerWindow::removeSelectedSignal()
|
|
{
|
|
int selRow = ui->tableViewer->currentRow();
|
|
if (selRow < 0) return; //no selected row
|
|
signalList.removeAt(selRow);
|
|
ui->tableViewer->removeRow(selRow);
|
|
}
|
|
|
|
void SignalViewerWindow::loadNodes()
|
|
{
|
|
int numFiles;
|
|
ui->cbNodes->clear();
|
|
if (dbcHandler == nullptr) return;
|
|
if ((numFiles = dbcHandler->getFileCount()) == 0) return;
|
|
qDebug() << numFiles;
|
|
for (int f = 0; f < numFiles; f++)
|
|
{
|
|
DBCFile* thisFile = dbcHandler->getFileByIdx(f);
|
|
qDebug() << thisFile->messageHandler->getCount();
|
|
|
|
QList<QString> names;
|
|
|
|
for (int x = 0; x < thisFile->dbc_nodes.count(); x++)
|
|
{
|
|
bool messagesInNode = false;
|
|
for (int m = 0; m < thisFile->messageHandler->getCount(); m++)
|
|
{
|
|
if(thisFile->messageHandler->findMsgByIdx(m)->sender->name == thisFile->dbc_nodes[x].name)
|
|
{
|
|
messagesInNode = true;
|
|
break;
|
|
}
|
|
}
|
|
if(messagesInNode)
|
|
{
|
|
QString fullyQualifiedNodeName = thisFile->getFilenameNoExt() + Utility::fullyQualifiedNameSeperator + thisFile->dbc_nodes[x].name;
|
|
names.append(fullyQualifiedNodeName);
|
|
}
|
|
}
|
|
|
|
if(names.count() > 0)
|
|
{
|
|
names.sort();
|
|
ui->cbNodes->addItem("----" + thisFile->getFilename());
|
|
Utility::SetComboBoxItemEnabled(ui->cbNodes, ui->cbNodes->count() -1, false);
|
|
for(int i=0; i<names.count(); i++)
|
|
ui->cbNodes->addItem(names[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SignalViewerWindow::loadMessages(int idx)
|
|
{
|
|
int numFiles = 0;
|
|
ui->cbMessages->clear();
|
|
if (dbcHandler == nullptr) return;
|
|
if ((numFiles = dbcHandler->getFileCount()) == 0) return;
|
|
qDebug() << numFiles;
|
|
|
|
QString displayedNodeName = ui->cbNodes->itemText(idx);
|
|
|
|
for (int f = 0; f < numFiles; f++)
|
|
{
|
|
qDebug() << dbcHandler->getFileByIdx(f)->messageHandler->getCount();
|
|
|
|
for (int x = 0; x < dbcHandler->getFileByIdx(f)->messageHandler->getCount(); x++)
|
|
{
|
|
QString fullyQualifiedNodeName = dbcHandler->getFileByIdx(f)->getFilenameNoExt() + Utility::fullyQualifiedNameSeperator + dbcHandler->getFileByIdx(f)->messageHandler->findMsgByIdx(x)->sender->name;
|
|
if(fullyQualifiedNodeName == displayedNodeName)
|
|
ui->cbMessages->addItem(dbcHandler->getFileByIdx(f)->messageHandler->findMsgByIdx(x)->name);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SignalViewerWindow::loadSignals(int idx)
|
|
{
|
|
Q_UNUSED(idx);
|
|
|
|
ui->cbSignals->clear();
|
|
|
|
QString fullyQualifiedNodeName = ui->cbNodes->itemText(ui->cbNodes->currentIndex());
|
|
QString msgName = ui->cbMessages->itemText(ui->cbMessages->currentIndex());
|
|
|
|
DBC_MESSAGE *msg = dbcHandler->findMessage(msgName, fullyQualifiedNodeName);
|
|
if (msg == nullptr) return;
|
|
for (int x = 0; x < msg->sigHandler->getCount(); x++)
|
|
{
|
|
ui->cbSignals->addItem(msg->sigHandler->findSignalByIdx(x)->name);
|
|
}
|
|
}
|
|
|
|
void SignalViewerWindow::addSignal()
|
|
{
|
|
DBC_MESSAGE *msg = nullptr;
|
|
|
|
QString fullyQualifiedNodeName = ui->cbNodes->itemText(ui->cbNodes->currentIndex());
|
|
QString msgName = ui->cbMessages->itemText(ui->cbMessages->currentIndex());
|
|
|
|
msg = dbcHandler->findMessage(msgName, fullyQualifiedNodeName);
|
|
|
|
if (!msg) return;
|
|
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(ui->cbSignals->currentText());
|
|
if (!sig) return;
|
|
|
|
addSignal(sig);
|
|
}
|
|
|
|
void SignalViewerWindow::addSignal(DBC_SIGNAL *sig)
|
|
{
|
|
signalList.append(sig);
|
|
|
|
int rowIdx = ui->tableViewer->rowCount();
|
|
ui->tableViewer->insertRow(rowIdx);
|
|
QTableWidgetItem *nodeitem = new QTableWidgetItem(sig->parentMessage->sender->name);
|
|
ui->tableViewer->setItem(rowIdx, 0, nodeitem);
|
|
QTableWidgetItem *msgitem = new QTableWidgetItem(sig->name);
|
|
ui->tableViewer->setItem(rowIdx, 1, msgitem);
|
|
}
|
|
|
|
void SignalViewerWindow::saveSignalsFile()
|
|
{
|
|
saveDefinitions();
|
|
}
|
|
|
|
void SignalViewerWindow::loadSignalsFile()
|
|
{
|
|
loadDefinitions(false);
|
|
}
|
|
|
|
void SignalViewerWindow::appendSignalsFile()
|
|
{
|
|
loadDefinitions(true);
|
|
}
|
|
|
|
void SignalViewerWindow::clearSignalsTable()
|
|
{
|
|
clearSignalsTable(true);
|
|
}
|
|
|
|
void SignalViewerWindow::clearSignalsTable(bool askForConfirmation)
|
|
{
|
|
if(askForConfirmation)
|
|
{
|
|
QMessageBox::StandardButton confirmDialog;
|
|
confirmDialog = QMessageBox::question(this, "Danger Will Robinson", "Are you sure you want to clear all of your signals?",
|
|
QMessageBox::Yes|QMessageBox::No);
|
|
if (confirmDialog == QMessageBox::No)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
signalList.clear();
|
|
ui->tableViewer->setRowCount(0);
|
|
}
|
|
|
|
void SignalViewerWindow::saveDefinitions()
|
|
{
|
|
QString filename;
|
|
QFileDialog dialog(this);
|
|
QSettings settings;
|
|
|
|
QStringList filters;
|
|
filters.append(QString(tr("SignalViewer definition (*.sdf)")));
|
|
|
|
dialog.setFileMode(QFileDialog::AnyFile);
|
|
dialog.setNameFilters(filters);
|
|
dialog.setViewMode(QFileDialog::Detail);
|
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
dialog.setDirectory(settings.value("SignalViewer/LoadSaveDirectory", dialog.directory().path()).toString());
|
|
|
|
if (dialog.exec() == QDialog::Accepted)
|
|
{
|
|
filename = dialog.selectedFiles()[0];
|
|
settings.setValue("SignalViewer/LoadSaveDirectory", dialog.directory().path());
|
|
|
|
if (!filename.contains('.')) filename += ".sdf";
|
|
|
|
QFile *outFile = new QFile(filename);
|
|
|
|
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
|
return;
|
|
|
|
DBC_SIGNAL *sig;
|
|
for (int i = 0; i < signalList.count(); i++)
|
|
{
|
|
sig = signalList.at(i);
|
|
|
|
outFile->write("SV1");
|
|
outFile->putChar(',');
|
|
outFile->write(QString::number(sig->parentMessage->ID, 16).toUtf8());
|
|
outFile->putChar(',');
|
|
outFile->write(sig->parentMessage->name.toUtf8());
|
|
outFile->putChar(',');
|
|
outFile->write(sig->name.toUtf8());
|
|
|
|
outFile->write("\n");
|
|
}
|
|
outFile->close();
|
|
}
|
|
}
|
|
|
|
void SignalViewerWindow::loadDefinitions(bool append)
|
|
{
|
|
QString filename;
|
|
QFileDialog dialog;
|
|
QSettings settings;
|
|
|
|
QStringList filters;
|
|
filters.append(QString(tr("SignalViewer definition (*.sdf)")));
|
|
|
|
QList<DBC_SIGNAL *> loadedSignals;
|
|
|
|
if (dbcHandler == nullptr) return;
|
|
if (dbcHandler->getFileCount() == 0) dbcHandler->createBlankFile();
|
|
|
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
|
dialog.setNameFilters(filters);
|
|
dialog.setViewMode(QFileDialog::Detail);
|
|
dialog.setDirectory(settings.value("SignalViewer/LoadSaveDirectory", dialog.directory().path()).toString());
|
|
|
|
if (dialog.exec() == QDialog::Accepted)
|
|
{
|
|
filename = dialog.selectedFiles()[0];
|
|
settings.setValue("SignalViewer/LoadSaveDirectory", dialog.directory().path());
|
|
|
|
QFile *inFile = new QFile(filename);
|
|
QByteArray line;
|
|
|
|
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
|
|
return;
|
|
|
|
while (!inFile->atEnd()) {
|
|
line = inFile->readLine().simplified();
|
|
if (line.length() > 2)
|
|
{
|
|
QList<QByteArray> tokens = line.split(',');
|
|
|
|
DBC_SIGNAL *sig;
|
|
|
|
if (tokens[0] == "SV1") //signal viewer save format v1
|
|
{
|
|
// = tokens[1].toUInt(nullptr, 16);
|
|
|
|
int msgId = tokens[1].toUInt(nullptr, 16);
|
|
QString msgName = QString(tokens[2]);
|
|
QString sigName = QString(tokens[3]);
|
|
DBC_MESSAGE *msg;;
|
|
if( (msg = dbcHandler->findMessage(msgId)) )
|
|
{
|
|
sig = msg->sigHandler->findSignalByName(sigName);
|
|
if(sig)
|
|
loadedSignals.append(sig);
|
|
}
|
|
else if ( (msg = dbcHandler->findMessage(msgName)) )
|
|
{
|
|
//this is not a very safe way to match since messages names can be duplicated
|
|
sig = msg->sigHandler->findSignalByName(sigName);
|
|
if(sig)
|
|
loadedSignals.append(sig);
|
|
}
|
|
else
|
|
{
|
|
qDebug() << "Couldn't find the message by ID or name! " << msgName << " " << sigName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
inFile->close();
|
|
|
|
if(loadedSignals.count() > 0)
|
|
{
|
|
if(append == false)
|
|
{
|
|
clearSignalsTable(false);
|
|
}
|
|
|
|
for (int i=0; i<loadedSignals.count(); i++)
|
|
{
|
|
addSignal(loadedSignals[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|