diff --git a/mainsettingsdialog.cpp b/mainsettingsdialog.cpp index 2da44ed..7cd1230 100644 --- a/mainsettingsdialog.cpp +++ b/mainsettingsdialog.cpp @@ -48,6 +48,7 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) : ui->cbLoadConnections->setChecked(settings.value("Main/SaveRestoreConnections", false).toBool()); ui->spinFontSize->setValue(settings.value("Main/FontSize", ui->cbDisplayHex->font().pointSize()).toUInt()); + ui->cbFontFixedWidth->setChecked(settings.value("Main/FontFixedWidth", false).toBool()); bool secondsMode = settings.value("Main/TimeSeconds", false).toBool(); bool clockMode = settings.value("Main/TimeClock", false).toBool(); @@ -132,6 +133,7 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) : connect(ui->cbHexGraphInfo, SIGNAL(toggled(bool)), this, SLOT(updateSettings())); connect(ui->cbIgnoreDBCColors, SIGNAL(toggled(bool)), this, SLOT(updateSettings())); connect(ui->spinMaximumFrames, SIGNAL(valueChanged(int)), this, SLOT(updateSettings())); + connect(ui->cbFontFixedWidth, SIGNAL(toggled(bool)), this, SLOT(updateSettings())); installEventFilter(this); } @@ -199,6 +201,7 @@ void MainSettingsDialog::updateSettings() settings.setValue("Main/FilterLabeling", ui->cbFilterLabeling->isChecked()); settings.setValue("Main/IgnoreDBCColors", ui->cbIgnoreDBCColors->isChecked()); settings.setValue("Main/MaximumFrames", ui->spinMaximumFrames->value()); + settings.setValue("Main/FontFixedWidth", ui->cbFontFixedWidth->isChecked()); settings.sync(); emit updatedSettings(); diff --git a/mainwindow.cpp b/mainwindow.cpp index 2351670..e84da30 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -57,12 +57,18 @@ MainWindow::MainWindow(QWidget *parent) : verticalHeader->setSectionResizeMode(QHeaderView::Fixed); QSettings settings; int fontSize = settings.value("Main/FontSize", 9).toUInt(); - QFont sysFont = QFont(); //get default font + QFont sysFont; + 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); verticalHeader->setDefaultSectionSize(sysFont.pixelSize()); + verticalHeader->setFont(QFont()); ui->canFramesView->setFont(sysFont); QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader(); + HorzHdr->setFont(QFont()); HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview connect(HorzHdr, SIGNAL(sectionClicked(int)), this, SLOT(headerClicked(int))); @@ -1161,11 +1167,26 @@ void MainWindow::showTemporalGraphWindow() //only create an instance of the object if we dont have one. Otherwise just display the existing one. if (!temporalGraphWindow) { + const QVector *frames; if (!useFiltered) - temporalGraphWindow = new TemporalGraphWindow(model->getListReference()); + frames = model->getListReference(); else - temporalGraphWindow = new TemporalGraphWindow(model->getFilteredListReference()); + frames = model->getFilteredListReference(); + + if(frames->count() > 2000) + { + QMessageBox::StandardButton confirmDialog; + confirmDialog = QMessageBox::question(this, "Danger Will Robinson", "There are a lot of frames (>2000) to plot, this may take a while or crash the app. Crash likely with more than 10k frames. Continue?", + QMessageBox::Yes|QMessageBox::No); + if (confirmDialog == QMessageBox::No) + { + return; + } + } + + temporalGraphWindow = new TemporalGraphWindow(frames); } + temporalGraphWindow->show(); } diff --git a/signalviewerwindow.cpp b/signalviewerwindow.cpp index 9f926f6..c061074 100644 --- a/signalviewerwindow.cpp +++ b/signalviewerwindow.cpp @@ -4,6 +4,9 @@ #include "mainwindow.h" #include +#define MSG_COL 1 +#define VALUE_COL 2 + SignalViewerWindow::SignalViewerWindow(const QVector *frames, QWidget *parent) : QDialog(parent), ui(new Ui::SignalViewerWindow) @@ -14,21 +17,41 @@ SignalViewerWindow::SignalViewerWindow(const QVector *frames, QWidget modelFrames = frames; QStringList headers; - headers << "Signal" << "Value"; + headers << "Node" << "Signal" << "Value"; ui->tableViewer->setHorizontalHeaderLabels(headers); - ui->tableViewer->setColumnWidth(0, 150); - ui->tableViewer->setColumnWidth(1, 300); + 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(); + 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())); - loadMessages(); + loadNodes(); } SignalViewerWindow::~SignalViewerWindow() @@ -75,11 +98,11 @@ void SignalViewerWindow::processFrame(CANFrame &frame) { 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, 1); + QTableWidgetItem *item = ui->tableViewer->item(i, VALUE_COL); if (!item) { item = new QTableWidgetItem(sigString); - ui->tableViewer->setItem(i, 1, item); + ui->tableViewer->setItem(i, VALUE_COL, item); } else item->setText(sigString); } @@ -95,20 +118,67 @@ void SignalViewerWindow::removeSelectedSignal() ui->tableViewer->removeRow(selRow); } -void SignalViewerWindow::loadMessages() +void SetComboBoxItemEnabled(QComboBox * comboBox, int index, bool enabled) +{ + auto * model = qobject_cast(comboBox->model()); + assert(model); + if(!model) return; + + auto * item = model->item(index); + assert(item); + if(!item) return; + item->setEnabled(enabled); +} + +void SignalViewerWindow::loadNodes() { int numFiles; - ui->cbMessages->clear(); + ui->cbNodes->clear(); if (dbcHandler == nullptr) return; if ((numFiles = dbcHandler->getFileCount()) == 0) return; qDebug() << numFiles; + for (int f = 0; f < numFiles; f++) + { + qDebug() << dbcHandler->getFileByIdx(f)->messageHandler->getCount(); + + QList names; + + for (int x = 0; x < dbcHandler->getFileByIdx(f)->dbc_nodes.count(); x++) + { + QString name = dbcHandler->getFileByIdx(f)->dbc_nodes[x].name; + if(name != "Vector__XXX") + names.append(name); + } + + if(names.count() > 0) + { + names.sort(); + ui->cbNodes->addItem("----" + dbcHandler->getFileByIdx(f)->getFilename()); + SetComboBoxItemEnabled(ui->cbNodes, ui->cbNodes->count() -1, false); + for(int i=0; icbNodes->addItem(names[i]); + } + } +} + +void SignalViewerWindow::loadMessages(int idx) +{ + int numFiles; + ui->cbMessages->clear(); + if (dbcHandler == nullptr) return; + if ((numFiles = dbcHandler->getFileCount()) == 0) return; + qDebug() << numFiles; + + QString nodeName = 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++) { - ui->cbMessages->addItem(dbcHandler->getFileByIdx(f)->messageHandler->findMsgByIdx(x)->name); + if(dbcHandler->getFileByIdx(f)->messageHandler->findMsgByIdx(x)->sender->name == nodeName) + ui->cbMessages->addItem(dbcHandler->getFileByIdx(f)->messageHandler->findMsgByIdx(x)->name); } } } @@ -137,11 +207,181 @@ void SignalViewerWindow::addSignal() 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 *item = new QTableWidgetItem(msg->sender->name + " - " + sig->name); - ui->tableViewer->setItem(rowIdx, 0, item); + 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(msgName)) + { + sig = msg->sigHandler->findSignalByName(sigName); + loadedSignals.append(sig); + } + else if(msg = dbcHandler->findMessage(msgId)) + { + sig = msg->sigHandler->findSignalByName(sigName); + //fix anything up about the name? + loadedSignals.append(sig); + } + else + { + qDebug() << "Couldn't find the message by name! " << msgName << " " << sigName; + } + } + } + } + inFile->close(); + + if(loadedSignals.count() > 0) + { + if(append == false) + { + clearSignalsTable(false); + } + + for (int i=0; i0 0 965 - 678 + 713 @@ -191,9 +191,23 @@ - Font Size + Font + + + + Use fixed-width font in tables + + + + + + + Size + + + diff --git a/ui/signalviewerwindow.ui b/ui/signalviewerwindow.ui index b5b5d5d..8f1c75d 100644 --- a/ui/signalviewerwindow.ui +++ b/ui/signalviewerwindow.ui @@ -18,8 +18,11 @@ + + true + - 2 + 3 300 @@ -32,6 +35,7 @@ + @@ -45,6 +49,16 @@ + + + + Node + + + + + + @@ -85,6 +99,34 @@ + + + + Save View + + + + + + + Load View + + + + + + + Append to View + + + + + + + Clear View + + +