#include "signalviewerwindow.h" #include "ui_signalviewerwindow.h" #include "helpwindow.h" #include "mainwindow.h" #include "utility.h" #include #define MSG_COL 1 #define VALUE_COL 2 SignalViewerWindow::SignalViewerWindow(const QVector *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->isSignalInMessage(frame)) //filter out multiplexed signals that aren't in this message. { 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 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; icbNodes->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 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 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