diff --git a/SavvyCAN.pro b/SavvyCAN.pro index f954497..c67f63c 100644 --- a/SavvyCAN.pro +++ b/SavvyCAN.pro @@ -68,7 +68,8 @@ SOURCES += main.cpp\ blfhandler.cpp \ re/sniffer/SnifferDelegate.cpp \ connections/newconnectiondialog.cpp \ - re/temporalgraphwindow.cpp + re/temporalgraphwindow.cpp \ + filterutility.cpp HEADERS += mainwindow.h \ can_structs.h \ @@ -127,7 +128,8 @@ HEADERS += mainwindow.h \ blfhandler.h \ re/sniffer/SnifferDelegate.h \ connections/newconnectiondialog.h \ - re/temporalgraphwindow.h + re/temporalgraphwindow.h \ + filterutility.h FORMS += ui/candatagrid.ui \ ui/connectionwindow.ui \ diff --git a/canframemodel.cpp b/canframemodel.cpp index 031318e..4e35555 100644 --- a/canframemodel.cpp +++ b/canframemodel.cpp @@ -102,7 +102,7 @@ void CANFrameModel::setSysTimeMode(bool mode) } } -void CANFrameModel::setInterpetMode(bool mode) +void CANFrameModel::setInterpretMode(bool mode) { //if the state of interpretFrames changes then we need to reset the model //so that QT will refresh the view properly @@ -114,6 +114,11 @@ void CANFrameModel::setInterpetMode(bool mode) } } +bool CANFrameModel::getInterpretMode() +{ + return interpretFrames; +} + void CANFrameModel::setTimeFormat(QString format) { Utility::timeFormat = format; diff --git a/canframemodel.h b/canframemodel.h index 011bf8f..d01f03b 100644 --- a/canframemodel.h +++ b/canframemodel.h @@ -42,7 +42,8 @@ public: void sendRefresh(int); int sendBulkRefresh(); void clearFrames(); - void setInterpetMode(bool); + void setInterpretMode(bool); + bool getInterpretMode(); void setOverwriteMode(bool); void setHexMode(bool); void setSysTimeMode(bool); diff --git a/dbc/dbchandler.cpp b/dbc/dbchandler.cpp index d873ae3..e9ac4c0 100644 --- a/dbc/dbchandler.cpp +++ b/dbc/dbchandler.cpp @@ -87,7 +87,7 @@ DBC_MESSAGE* DBCMessageHandler::findMsgByID(uint32_t id) if (messages.count() == 0) return nullptr; for (int i = 0; i < messages.count(); i++) { - if (isJ1939Handler) + if (matchingCriteria == J1939) { // include data page and extended data page in the pgn uint32_t pgn = (id & 0x3FFFF00) >> 8; @@ -109,6 +109,13 @@ DBC_MESSAGE* DBCMessageHandler::findMsgByID(uint32_t id) } } } + else if (matchingCriteria == GMLAN) + { + // Match the bits 14-26 (Arbitration Id) of GMLAN 29bit header + uint32_t arbId = id &0x3FFE000; + if ( (arbId != 0) && (messages[i].ID & 0x3FFE000) == arbId ) + return &messages[i]; + } else { if ( messages[i].ID == id ) @@ -203,20 +210,31 @@ int DBCMessageHandler::getCount() return messages.count(); } -bool DBCMessageHandler::isJ1939() +bool DBCMessageHandler::filterLabeling() { - return isJ1939Handler; + return filterLabelingEnabled; } -void DBCMessageHandler::setJ1939(bool j1939) +void DBCMessageHandler::setFilterLabeling(bool filterLabeling) { - isJ1939Handler = j1939; + filterLabelingEnabled = filterLabeling; +} + +MatchingCriteria_t DBCMessageHandler::getMatchingCriteria() +{ + return matchingCriteria; +} + +void DBCMessageHandler::setMatchingCriteria(MatchingCriteria_t _matchingCriteria) +{ + matchingCriteria = _matchingCriteria; } DBCFile::DBCFile() { messageHandler = new DBCMessageHandler; - messageHandler->setJ1939(false); + messageHandler->setMatchingCriteria(EXACT); + messageHandler->setFilterLabeling(false); } DBCFile::DBCFile(const DBCFile& cpy) : QObject() @@ -225,7 +243,8 @@ DBCFile::DBCFile(const DBCFile& cpy) : QObject() for (int i = 0 ; i < cpy.messageHandler->getCount() ; i++) messageHandler->addMessage(*cpy.messageHandler->findMsgByIdx(i)); - messageHandler->setJ1939(cpy.messageHandler->isJ1939()); + messageHandler->setMatchingCriteria(cpy.messageHandler->getMatchingCriteria()); + messageHandler->setFilterLabeling(cpy.messageHandler->filterLabeling()); fileName = cpy.fileName; filePath = cpy.filePath; assocBuses = cpy.assocBuses; @@ -293,9 +312,10 @@ int DBCFile::getAssocBus() void DBCFile::setAssocBus(int bus) { - int numBuses = CANConManager::getInstance()->getNumBuses(); if (bus < -1) return; - if (bus >= numBuses) return; + // To allow setting bus numbers even before connection is configured, do not enforce "valid" bus numbers + //int numBuses = CANConManager::getInstance()->getNumBuses(); + //if (bus >= numBuses) return; assocBuses = bus; } @@ -690,7 +710,8 @@ void DBCFile::loadFile(QString fileName) qDebug() << "Starting DBC load"; dbc_nodes.clear(); messageHandler->removeAllMessages(); - messageHandler->setJ1939(false); + messageHandler->setMatchingCriteria(EXACT); + messageHandler->setFilterLabeling(false); DBC_NODE falseNode; falseNode.name = "Vector__XXX"; @@ -884,14 +905,24 @@ void DBCFile::loadFile(QString fileName) fgAttr = findAttributeByName("GenMsgForegroundColor"); } - DBC_ATTRIBUTE *j1939attr = findAttributeByName("isj1939dbc"); - if (j1939attr) + DBC_ATTRIBUTE *mc_attr = findAttributeByName("matchingcriteria"); + if (mc_attr) { - messageHandler->setJ1939(j1939attr->defaultValue > 0); + messageHandler->setMatchingCriteria((MatchingCriteria_t)mc_attr->defaultValue.toInt()); } else { - messageHandler->setJ1939(false); + messageHandler->setMatchingCriteria(EXACT); + } + + DBC_ATTRIBUTE *fl_attr = findAttributeByName("filterlabeling"); + if (fl_attr) + { + messageHandler->setFilterLabeling(fl_attr->defaultValue.toInt()); + } + else + { + messageHandler->setFilterLabeling(false); } QColor DefaultBG = QColor(bgAttr->defaultValue.toString()); @@ -1397,7 +1428,16 @@ int DBCHandler::createBlankFile() attr.enumVals.clear(); attr.lower = 0; attr.upper = 0; - attr.name = "isj1939dbc"; + attr.name = "matchingcriteria"; + attr.valType = QINT; + newFile.dbc_attributes.append(attr); + + attr.attrType = MESSAGE; + attr.defaultValue = 0; + attr.enumVals.clear(); + attr.lower = 0; + attr.upper = 0; + attr.name = "filterlabeling"; attr.valType = QINT; newFile.dbc_attributes.append(attr); @@ -1405,6 +1445,14 @@ int DBCHandler::createBlankFile() return loadedFiles.count(); } +DBCFile* DBCHandler::loadDBCFile(QString filename) +{ + DBCFile newFile; + newFile.loadFile(filename); + loadedFiles.append(newFile); + return &loadedFiles.last(); +} + //the only reason to even bother sending the index is to see if //the user wants to replace an already loaded DBC. //Otherwise add a new one. Well, always add a new one. @@ -1430,11 +1478,8 @@ DBCFile* DBCHandler::loadDBCFile(int idx) { filename = dialog.selectedFiles()[0]; //right now there is only one file type that can be loaded here so just do it. - DBCFile newFile; - newFile.loadFile(filename); - loadedFiles.append(newFile); settings.setValue("DBC/LoadSaveDirectory", dialog.directory().path()); - return &loadedFiles.last(); + return loadDBCFile(filename); } return nullptr; @@ -1483,6 +1528,29 @@ DBC_MESSAGE* DBCHandler::findMessage(const CANFrame &frame) return nullptr; } + +// This function won't care which bus the DBC file is associated, but will return any message as long as ID matches and the file +// has filter labeling enabled. +// Returns the found message as well as the matching criteria (exact/J1939/GMLAN) +// Used for quickly populating the Frame Filtering section with interpreted values +DBC_MESSAGE* DBCHandler::findMessageForFilter(uint32_t id, MatchingCriteria_t * matchingCriteria) +{ + for(int i = 0; i < loadedFiles.count(); i++) + { + if (loadedFiles[i].messageHandler->filterLabeling()) + { + DBC_MESSAGE* msg = loadedFiles[i].messageHandler->findMsgByID(id); + if (msg != nullptr) + { + *matchingCriteria = loadedFiles[i].messageHandler->getMatchingCriteria(); + return msg; + } + } + } + return nullptr; +} + + /* * As above, a real shortcut function that searches all files in order to try to find a message with the given name */ @@ -1526,7 +1594,44 @@ DBCFile* DBCHandler::getFileByName(QString name) DBCHandler::DBCHandler() { + // Load previously saved DBC file settings + QSettings settings; + int filecount = settings.value("DBC/FileCount", 0).toInt(); + for (int i=0; isetAssocBus(bus); + MatchingCriteria_t matchingCriteria = (MatchingCriteria_t)settings.value("DBC/MatchingCriteria_" + QString(i),0).toInt(); + + DBC_ATTRIBUTE attr; + + attr.attrType = MESSAGE; + attr.defaultValue = matchingCriteria; + attr.enumVals.clear(); + attr.lower = 0; + attr.upper = 0; + attr.name = "matchingcriteria"; + attr.valType = QINT; + file->dbc_attributes.append(attr); + file->messageHandler->setMatchingCriteria(matchingCriteria); + + bool filterLabeling = settings.value("DBC/FilterLabeling_" + QString(i),0).toBool(); + attr.attrType = MESSAGE; + attr.defaultValue = filterLabeling; + attr.enumVals.clear(); + attr.lower = 0; + attr.upper = 0; + attr.name = "filterlabeling"; + attr.valType = QINT; + file->dbc_attributes.append(attr); + file->messageHandler->setFilterLabeling(filterLabeling); + + qInfo() << "Loaded DBC file" << filename << " (bus:" << bus + << ", Matching Criteria:" << (int)matchingCriteria << "Filter labeling: " << (filterLabeling?"enabled":"disabled") << ")"; + } } DBCHandler* DBCHandler::getReference() diff --git a/dbc/dbchandler.h b/dbc/dbchandler.h index ebe48e1..9435ede 100644 --- a/dbc/dbchandler.h +++ b/dbc/dbchandler.h @@ -5,6 +5,13 @@ #include "dbc_classes.h" #include "can_structs.h" + typedef enum + { + EXACT, + J1939, + GMLAN + } MatchingCriteria_t; + /* * TODO: * Finish coding up the decoupled design @@ -40,11 +47,14 @@ public: bool removeMessage(QString name); void removeAllMessages(); int getCount(); - bool isJ1939(); - void setJ1939(bool j1939); + MatchingCriteria_t getMatchingCriteria(); + void setMatchingCriteria(MatchingCriteria_t mc); + void setFilterLabeling( bool labelFiltering ); + bool filterLabeling(); private: QList messages; - bool isJ1939Handler; + MatchingCriteria_t matchingCriteria; + bool filterLabelingEnabled; }; //technically there should be a node handler too but I'm sort of treating nodes as second class @@ -90,6 +100,7 @@ class DBCHandler: public QObject { Q_OBJECT public: + DBCFile* loadDBCFile(QString filename); DBCFile* loadDBCFile(int); void saveDBCFile(int); void removeDBCFile(int); @@ -97,6 +108,7 @@ public: void swapFiles(int pos1, int pos2); DBC_MESSAGE* findMessage(const CANFrame &frame); DBC_MESSAGE* findMessage(const QString msgName); + DBC_MESSAGE* findMessageForFilter(uint32_t id, MatchingCriteria_t * matchingCriteria); int getFileCount(); DBCFile* getFileByIdx(int idx); DBCFile* getFileByName(QString name); diff --git a/dbc/dbcloadsavewindow.cpp b/dbc/dbcloadsavewindow.cpp index 327252b..83f2927 100644 --- a/dbc/dbcloadsavewindow.cpp +++ b/dbc/dbcloadsavewindow.cpp @@ -1,6 +1,6 @@ #include "dbcloadsavewindow.h" #include "ui_dbcloadsavewindow.h" -#include +#include #include "helpwindow.h" #include "connections/canconmanager.h" @@ -18,14 +18,44 @@ DBCLoadSaveWindow::DBCLoadSaveWindow(const QVector *frames, QWidget *p inhibitCellProcessing = false; QStringList header; - header << "Filename" << "Associated Bus" << "J1939"; - ui->tableFiles->setColumnCount(3); + header << "Filename" << "Associated Bus" << "Matching criteria" << "Label filters"; + ui->tableFiles->setColumnCount(4); ui->tableFiles->setHorizontalHeaderLabels(header); ui->tableFiles->setColumnWidth(0, 265); ui->tableFiles->setColumnWidth(1, 125); - ui->tableFiles->setColumnWidth(2, 80); + ui->tableFiles->setColumnWidth(2, 120); + ui->tableFiles->setColumnWidth(3, 90); ui->tableFiles->horizontalHeader()->setStretchLastSection(true); + // Populate table + for (int idx=0; idxgetFileCount(); idx++) + { + DBCFile * file = dbcHandler->getFileByIdx(idx); + ui->tableFiles->insertRow(ui->tableFiles->rowCount()); + ui->tableFiles->setItem(idx, 0, new QTableWidgetItem(file->getFullFilename())); + QString bus = QString::number(file->getAssocBus() ); + ui->tableFiles->setItem(idx, 1, new QTableWidgetItem(bus)); + + QComboBox * mc_item = addMatchingCriteriaCombobox(idx); + int mc = (int)file->messageHandler->getMatchingCriteria(); + mc_item->setCurrentIndex(mc); + + QTableWidgetItem *item = new QTableWidgetItem(""); + ui->tableFiles->setItem(idx, 3, item); + bool filterLabeling = file->messageHandler->filterLabeling(); + if (filterLabeling) + { + item->setCheckState(Qt::Checked); + } + else + { + item->setCheckState(Qt::Unchecked); + } + + qDebug() << "Populate DBC table:" << file->getFullFilename() << " (bus:" << bus << " - Matching Criteria:" << mc + << "Filter labeling: " << (filterLabeling?"enabled":"disabled") << ")"; + } + connect(ui->btnEdit, &QAbstractButton::clicked, this, &DBCLoadSaveWindow::editFile); connect(ui->btnLoad, &QAbstractButton::clicked, this, &DBCLoadSaveWindow::loadFile); connect(ui->btnMoveDown, &QAbstractButton::clicked, this, &DBCLoadSaveWindow::moveDown); @@ -42,12 +72,42 @@ DBCLoadSaveWindow::DBCLoadSaveWindow(const QVector *frames, QWidget *p installEventFilter(this); } +QComboBox * DBCLoadSaveWindow::addMatchingCriteriaCombobox(int row) +{ + QComboBox *item = new QComboBox(); + item->addItem("Exact"); + item->addItem("J1939"); + item->addItem("GMLAN"); + ui->tableFiles->setCellWidget(row, 2, item); + connect(item, static_cast(&QComboBox::currentIndexChanged), + [this](int box_idx) { matchingCriteriaChanged(box_idx); } ); + return item; +} + DBCLoadSaveWindow::~DBCLoadSaveWindow() { removeEventFilter(this); delete ui; } +void DBCLoadSaveWindow::updateSettings() +{ + QSettings settings; + int filecount = ui->tableFiles->rowCount(); + settings.setValue("DBC/FileCount", filecount); + for (int i=0; igetFileByIdx(i); + if (file) + { + settings.setValue("DBC/Filename_" + QString(i), file->getFullFilename()); + settings.setValue("DBC/AssocBus_" + QString(i), file->getAssocBus()); + settings.setValue("DBC/MatchingCriteria_" + QString(i), file->messageHandler->getMatchingCriteria()); + settings.setValue("DBC/FilterLabeling_" + QString(i), file->messageHandler->filterLabeling()); + } + } +} + bool DBCLoadSaveWindow::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyRelease) { @@ -74,9 +134,12 @@ void DBCLoadSaveWindow::newFile() ui->tableFiles->setItem(idx, 0, new QTableWidgetItem("UNNAMEDFILE")); ui->tableFiles->setItem(idx, 1, new QTableWidgetItem("-1")); + QComboBox * mc_item = addMatchingCriteriaCombobox(idx); + mc_item->setCurrentIndex(EXACT); + QTableWidgetItem *item = new QTableWidgetItem(""); - item->setCheckState(Qt::Unchecked); - ui->tableFiles->setItem(idx, 2, item); + item->setCheckState(Qt::Checked); + ui->tableFiles->setItem(idx, 3, item); } void DBCLoadSaveWindow::loadFile() @@ -87,9 +150,17 @@ void DBCLoadSaveWindow::loadFile() ui->tableFiles->insertRow(ui->tableFiles->rowCount()); ui->tableFiles->setItem(idx, 0, new QTableWidgetItem(file->getFullFilename())); ui->tableFiles->setItem(idx, 1, new QTableWidgetItem("-1")); - DBC_ATTRIBUTE *attr = file->findAttributeByName("isj1939dbc"); + + DBC_ATTRIBUTE *attr = file->findAttributeByName("matchingcriteria"); + QComboBox * mc_item = addMatchingCriteriaCombobox(idx); + if (attr && attr->defaultValue > 0) + { + mc_item->setCurrentIndex(attr->defaultValue.toInt()); + } + + attr = file->findAttributeByName("filterlabeling"); QTableWidgetItem *item = new QTableWidgetItem(""); - ui->tableFiles->setItem(idx, 2, item); + ui->tableFiles->setItem(idx, 3, item); if (attr && attr->defaultValue > 0) { item->setCheckState(Qt::Checked); @@ -98,6 +169,8 @@ void DBCLoadSaveWindow::loadFile() { item->setCheckState(Qt::Unchecked); } + + updateSettings(); } } @@ -131,6 +204,7 @@ void DBCLoadSaveWindow::removeFile() dbcHandler->removeDBCFile(idx); ui->tableFiles->removeRow(idx); } + updateSettings(); } void DBCLoadSaveWindow::moveUp() @@ -139,6 +213,7 @@ void DBCLoadSaveWindow::moveUp() if (idx < 1) return; dbcHandler->swapFiles(idx - 1, idx); swapTableRows(true); + updateSettings(); } void DBCLoadSaveWindow::moveDown() @@ -148,6 +223,7 @@ void DBCLoadSaveWindow::moveDown() if (idx > (dbcHandler->getFileCount() - 2)) return; dbcHandler->swapFiles(idx, idx + 1); swapTableRows(false); + updateSettings(); } void DBCLoadSaveWindow::editFile() @@ -159,6 +235,42 @@ void DBCLoadSaveWindow::editFile() editorWindow->show(); } +void DBCLoadSaveWindow::matchingCriteriaChanged(int index) +{ + // We don't know which combobox changed, so we just update all of them + for (int row=0; rowtableFiles->rowCount(); row++) + { + DBCFile *file = dbcHandler->getFileByIdx(row); + if (file) + { + QComboBox *item = (QComboBox*)ui->tableFiles->cellWidget(row, 2); + MatchingCriteria_t matchingCriteria = (MatchingCriteria_t) item->currentIndex(); + DBC_ATTRIBUTE *attr = file->findAttributeByName("matchingcriteria"); + if (attr) + { + attr->defaultValue = matchingCriteria; + file->messageHandler->setMatchingCriteria(matchingCriteria); + } + else + { + DBC_ATTRIBUTE attr; + + attr.attrType = MESSAGE; + attr.defaultValue = matchingCriteria; + attr.enumVals.clear(); + attr.lower = 0; + attr.upper = 0; + attr.name = "matchingcriteria"; + attr.valType = QINT; + file->dbc_attributes.append(attr); + file->messageHandler->setMatchingCriteria(matchingCriteria); + } + } + } + updateSettings(); +} + + void DBCLoadSaveWindow::cellChanged(int row, int col) { if (inhibitCellProcessing) return; @@ -167,39 +279,40 @@ void DBCLoadSaveWindow::cellChanged(int row, int col) DBCFile *file = dbcHandler->getFileByIdx(row); int bus = ui->tableFiles->item(row, col)->text().toInt(); int numBuses = CANConManager::getInstance()->getNumBuses(); - if (bus > -2 && bus < numBuses) + if (bus > -2) { file->setAssocBus(bus); } - } - else if (col == 2) + updateSettings(); + } + else if (col == 3) // labelfilters { DBCFile *file = dbcHandler->getFileByIdx(row); if (file) { - //int isj1939dbc = ui->tableFiles->item(row, col)->text().toInt(); - bool isj1939dbc = ui->tableFiles->item(row, col)->checkState() == Qt::Checked; - DBC_ATTRIBUTE *attr = file->findAttributeByName("isj1939dbc"); + bool labelFilters = ui->tableFiles->item(row, col)->checkState() == Qt::Checked; + DBC_ATTRIBUTE *attr = file->findAttributeByName("filterlabeling"); if (attr) { - attr->defaultValue = isj1939dbc ? 1 : 0; - file->messageHandler->setJ1939(isj1939dbc); + attr->defaultValue = labelFilters ? 1 : 0; + file->messageHandler->setFilterLabeling(labelFilters); } else { DBC_ATTRIBUTE attr; attr.attrType = MESSAGE; - attr.defaultValue = isj1939dbc ? 1 : 0; + attr.defaultValue = labelFilters ? 1 : 0; attr.enumVals.clear(); attr.lower = 0; attr.upper = 0; - attr.name = "isj1939dbc"; + attr.name = "labelfilters"; attr.valType = QINT; file->dbc_attributes.append(attr); - file->messageHandler->setJ1939(isj1939dbc); + file->messageHandler->setFilterLabeling(labelFilters); } - } + updateSettings(); + } } } @@ -222,10 +335,17 @@ void DBCLoadSaveWindow::swapTableRows(bool up) QList sourceItems = takeRow(idx); QList destItems = takeRow(destIdx); + // QCombobox needs separate handling + int sourceMC = ((QComboBox*)ui->tableFiles->cellWidget(idx,2))->currentIndex(); + int destMC = ((QComboBox*)ui->tableFiles->cellWidget(destIdx,2))->currentIndex(); + // set back in reverse order setRow(idx, destItems); setRow(destIdx, sourceItems); + ((QComboBox*)ui->tableFiles->cellWidget(idx,2))->setCurrentIndex(destMC); + ((QComboBox*)ui->tableFiles->cellWidget(destIdx,2))->setCurrentIndex(sourceMC); + inhibitCellProcessing = false; } diff --git a/dbc/dbcloadsavewindow.h b/dbc/dbcloadsavewindow.h index d724fc1..3ac94e4 100644 --- a/dbc/dbcloadsavewindow.h +++ b/dbc/dbcloadsavewindow.h @@ -3,6 +3,7 @@ #include #include +#include #include "dbchandler.h" #include "dbcmaineditor.h" @@ -27,6 +28,7 @@ private slots: void editFile(); void cellChanged(int row, int col); void cellDoubleClicked(int row, int col); + void matchingCriteriaChanged(int index); void newFile(); private: @@ -41,6 +43,8 @@ private: QList takeRow(int row); void setRow(int row, const QList& rowItems); bool eventFilter(QObject *obj, QEvent *event); + void updateSettings(); + QComboBox * addMatchingCriteriaCombobox(int row); }; #endif // DBCLOADSAVEWINDOW_H diff --git a/filterutility.cpp b/filterutility.cpp new file mode 100644 index 0000000..a085993 --- /dev/null +++ b/filterutility.cpp @@ -0,0 +1,80 @@ +#include "utility.h" +#include "filterutility.h" +#include "dbc/dbchandler.h" +#include + +uint32_t FilterUtility::getIdAsInt( QListWidgetItem * item ) +{ + return Utility::ParseStringToNum(getId(item)); +} + +QString FilterUtility::getId( QString itemText ) +{ + if (itemText.contains(" ")) + // Strip away the filter label + return itemText.left(itemText.indexOf(" ")); + else + return itemText; +} + +QString FilterUtility::getId( QListWidgetItem * item ) +{ + return getId(item->text()); +} + +uint32_t FilterUtility::getGMLanArbitrationId(uint32_t id) +{ + return (id >> 13) & 0x1FFF; +} + +uint32_t FilterUtility::getGMLanPriorityBits(uint32_t id) +{ + return (id >> 26) & 0x7; +} + +uint32_t FilterUtility::getGMLanSenderId(uint32_t id) +{ + return id & 0x1FFF; +} + +QListWidgetItem * FilterUtility::createCheckableFilterItem(uint32_t id, bool checked, QListWidget* parent) +{ + QListWidgetItem * thisItem = createFilterItem(id,parent); + thisItem->setFlags(thisItem->flags() | Qt::ItemIsUserCheckable); + if (checked) + thisItem->setCheckState(Qt::Checked); + else + thisItem->setCheckState(Qt::Unchecked); + return thisItem; +} + +QListWidgetItem * FilterUtility::createFilterItem(uint32_t id, QListWidget* parent) +{ + QSettings settings; + DBCHandler * dbcHandler = DBCHandler::getReference(); + QListWidgetItem *thisItem = new QListWidgetItem(parent); + QString filterItemName = Utility::formatCANID(id); + + if (settings.value("Main/FilterLabeling", false).toBool()) + { + // Filter labeling (show interpreted frame names next to the CAN addr ID) + MatchingCriteria_t matchingCriteria; + DBC_MESSAGE *msg = dbcHandler->findMessageForFilter(id,&matchingCriteria); + if (msg != NULL) + { + filterItemName.append(" "); + filterItemName.append(msg->name); + + // Create tooltip to show the whole name just in case it's too long to fit in the filter window. + // Also if the matching criteria is set to GMLAN, show the Arbitration ID as well + QString tooltip; + if (matchingCriteria == GMLAN) + tooltip.append("0x" + QString::number(FilterUtility::getGMLanArbitrationId(id), 16).toUpper().rightJustified(4,'0') + ": "); + tooltip.append(msg->name); + thisItem->setToolTip(tooltip); + } + } + + thisItem->setText(filterItemName); + return thisItem; +} \ No newline at end of file diff --git a/filterutility.h b/filterutility.h new file mode 100644 index 0000000..3e0eeaa --- /dev/null +++ b/filterutility.h @@ -0,0 +1,23 @@ +#ifndef FILTERUTILITY_H +#define FILTERUTILITY_H + +#include + + +class FilterUtility +{ + +public: + static QListWidgetItem * createFilterItem(uint32_t id, QListWidget* parent=NULL); // if parent is given, add item automatically to listwidget + static QListWidgetItem * createCheckableFilterItem(uint32_t id, bool checked, QListWidget* parent=NULL); + + static uint32_t getIdAsInt( QListWidgetItem * item ); + static QString getId( QListWidgetItem * item ); + static QString getId( QString itemText ); + + static uint32_t getGMLanArbitrationId(uint32_t id); + static uint32_t getGMLanSenderId(uint32_t id); + static uint32_t getGMLanPriorityBits(uint32_t id); +}; + +#endif // DBCLOADSAVEWINDOW_H \ No newline at end of file diff --git a/frameplaybackwindow.cpp b/frameplaybackwindow.cpp index 09f2bbb..dcc2c2f 100644 --- a/frameplaybackwindow.cpp +++ b/frameplaybackwindow.cpp @@ -6,6 +6,7 @@ #include #include "connections/canconmanager.h" #include "helpwindow.h" +#include "filterutility.h" /* * Notes about new functionality: @@ -78,6 +79,9 @@ FramePlaybackWindow::FramePlaybackWindow(const QVector *frames, QWidge playbackObject.setPlaybackInterval(ui->spinPlaySpeed->value()); + // Prevent annoying accidental horizontal scrolling when filter list is populated with long interpreted message names + ui->listID->horizontalScrollBar()->setEnabled(false); + QStringList headers; headers << "Source" << "Loops"; ui->tblSequence->setColumnCount(2); @@ -197,7 +201,7 @@ void FramePlaybackWindow::saveFilters() for (int c = 0; c < ui->listID->count(); c++) { - outFile->write(QString::number(ui->listID->item(c)->text().toInt(nullptr, 16), 16).toUtf8()); + outFile->write(QString::number(FilterUtility::getId(ui->listID->item(c)).toInt(nullptr, 16), 16).toUtf8()); outFile->putChar(','); if (ui->listID->item(c)->checkState() == Qt::Checked) outFile->putChar('T'); else outFile->putChar('F'); @@ -260,7 +264,7 @@ void FramePlaybackWindow::loadFilters() for (int c = 0; c < ui->listID->count(); c++) { QListWidgetItem *item = ui->listID->item(c); - if (item->text().toInt(nullptr, 16) == ID) + if (FilterUtility::getId(item).toInt(nullptr, 16) == ID) { item->setCheckState(Qt::Checked); } @@ -291,10 +295,7 @@ void FramePlaybackWindow::refreshIDList() QHash::Iterator filterIter; for (filterIter = currentSeqItem->idFilters.begin(); filterIter != currentSeqItem->idFilters.end(); ++filterIter) { - QListWidgetItem* listItem = new QListWidgetItem(Utility::formatCANID(filterIter.key()), ui->listID); - listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable); // set checkable flag - if (filterIter.value()) listItem->setCheckState(Qt::Checked); - else listItem->setCheckState(Qt::Unchecked); + QListWidgetItem* listItem = FilterUtility::createCheckableFilterItem(filterIter.key(), filterIter.value(), ui->listID); } //default is to sort in ascending order ui->listID->sortItems(); @@ -611,7 +612,7 @@ void FramePlaybackWindow::changeSendingBus(int newIdx) void FramePlaybackWindow::changeIDFiltering(QListWidgetItem *item) { qDebug() << "Changed ID filter " << item->text() << " : " << item->checkState(); - int ID = Utility::ParseStringToNum(item->text()); + int ID = FilterUtility::getIdAsInt(item); currentSeqItem->idFilters[ID] = (item->checkState() == Qt::Checked) ? true : false; } diff --git a/mainsettingsdialog.cpp b/mainsettingsdialog.cpp index 71246fb..77f1ec4 100644 --- a/mainsettingsdialog.cpp +++ b/mainsettingsdialog.cpp @@ -61,6 +61,7 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) : ui->comboSendingBus->setCurrentIndex(settings.value("Playback/SendingBus", 4).toInt()); ui->cbUseFiltered->setChecked(settings.value("Main/UseFiltered", false).toBool()); ui->cbUseOpenGL->setChecked(settings.value("Main/UseOpenGL", false).toBool()); + ui->cbFilterLabeling->setChecked(settings.value("Main/FilterLabeling", false).toBool()); //just for simplicity they all call the same function and that function updates all settings at once connect(ui->cbDisplayHex, SIGNAL(toggled(bool)), this, SLOT(updateSettings())); @@ -83,6 +84,7 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) : connect(ui->lineRemoteHost, SIGNAL(editingFinished()), this, SLOT(updateSettings())); connect(ui->lineRemotePort, SIGNAL(editingFinished()), this, SLOT(updateSettings())); connect(ui->cbLoadConnections, SIGNAL(toggled(bool)), this, SLOT(updateSettings())); + connect(ui->cbFilterLabeling, SIGNAL(toggled(bool)), this, SLOT(updateSettings())); installEventFilter(this); } @@ -141,6 +143,7 @@ void MainSettingsDialog::updateSettings() settings.setValue("Remote/Host", ui->lineRemoteHost->text()); settings.setValue("Remote/Port", ui->lineRemotePort->text()); settings.setValue("Remote/AutoStart", ui->cbAutoStartRemote->isChecked()); + settings.setValue("Main/FilterLabeling", ui->cbFilterLabeling->isChecked()); settings.sync(); emit updatedSettings(); diff --git a/mainwindow.cpp b/mainwindow.cpp index b25a73c..2f9381e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -8,6 +8,7 @@ #include "connections/connectionwindow.h" #include "helpwindow.h" #include "utility.h" +#include "filterutility.h" /* Some notes on things I'd like to put into the program but haven't put on github (yet) @@ -143,6 +144,9 @@ MainWindow::MainWindow(QWidget *parent) : ui->lbFPS->setText("0"); ui->lbNumFrames->setText("0"); + // Prevent annoying accidental horizontal scrolling when filter list is populated with long interpreted message names + ui->listFilters->horizontalScrollBar()->setEnabled(false); + connect(&updateTimer, &QTimer::timeout, this, &MainWindow::tickGUIUpdate); updateTimer.setInterval(250); updateTimer.start(); @@ -324,7 +328,13 @@ void MainWindow::readUpdateableSettings() useFiltered = settings.value("Main/UseFiltered", false).toBool(); model->setTimeFormat(settings.value("Main/TimeFormat", "MMM-dd HH:mm:ss.zzz").toString()); -} + if (settings.value("Main/FilterLabeling", false).toBool()) + ui->listFilters->setMaximumWidth(250); + else + ui->listFilters->setMaximumWidth(175); + updateFilterList(); +} + void MainWindow::writeSettings() { @@ -391,7 +401,7 @@ void MainWindow::gridDoubleClicked(QModelIndex idx) void MainWindow::interpretToggled(bool state) { - model->setInterpetMode(state); + model->setInterpretMode(state); //ui->canFramesView->resizeRowsToContents(); //a VERY costly operation! } @@ -422,6 +432,8 @@ void MainWindow::updateFilterList() qDebug() << "updateFilterList called on MainWindow"; + inhibitFilterUpdate = true; + ui->listFilters->clear(); if (filters->isEmpty()) return; @@ -429,22 +441,19 @@ void MainWindow::updateFilterList() QMap::const_iterator filterIter; for (filterIter = filters->begin(); filterIter != filters->end(); ++filterIter) { - QListWidgetItem *thisItem = new QListWidgetItem(); - thisItem->setText(Utility::formatCANID(filterIter.key())); - thisItem->setFlags(thisItem->flags() | Qt::ItemIsUserCheckable); - if (filterIter.value()) thisItem->setCheckState(Qt::Checked); - else thisItem->setCheckState(Qt::Unchecked); - ui->listFilters->addItem(thisItem); + QListWidgetItem *thisItem = FilterUtility::createCheckableFilterItem(filterIter.key(), filterIter.value(), ui->listFilters); } + inhibitFilterUpdate = false; } void MainWindow::filterListItemChanged(QListWidgetItem *item) { if (inhibitFilterUpdate) return; //qDebug() << item->text(); - int ID; + + // strip away possible filter label + int ID = FilterUtility::getIdAsInt(item); bool isSet = false; - ID = Utility::ParseStringToNum(item->text()); if (item->checkState() == Qt::Checked) isSet = true; model->setFilterState(ID, isSet); diff --git a/re/flowviewwindow.cpp b/re/flowviewwindow.cpp index a728d9a..c3ec0c0 100644 --- a/re/flowviewwindow.cpp +++ b/re/flowviewwindow.cpp @@ -2,6 +2,7 @@ #include "ui_flowviewwindow.h" #include "mainwindow.h" #include "helpwindow.h" +#include "filterutility.h" const QColor FlowViewWindow::graphColors[8] = {Qt::blue, Qt::green, Qt::black, Qt::red, //0 1 2 3 Qt::gray, Qt::yellow, Qt::cyan, Qt::darkMagenta}; //4 5 6 7 @@ -85,7 +86,6 @@ FlowViewWindow::FlowViewWindow(const QVector *frames, QWidget *parent) connect(ui->btnForwardOne, SIGNAL(clicked(bool)), this, SLOT(btnFwdOneClick())); 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(ui->graphView, SIGNAL(plottableDoubleClick(QCPAbstractPlottable*,QMouseEvent*)), this, SLOT(plottableDoubleClick(QCPAbstractPlottable*,QMouseEvent*))); connect(ui->txtTrigger0, SIGNAL(textEdited(QString)), this, SLOT(updateTriggerValues())); @@ -97,6 +97,13 @@ FlowViewWindow::FlowViewWindow(const QVector *frames, QWidget *parent) connect(ui->txtTrigger6, SIGNAL(textEdited(QString)), this, SLOT(updateTriggerValues())); connect(ui->txtTrigger7, SIGNAL(textEdited(QString)), this, SLOT(updateTriggerValues())); + // Using lambda expression to strip away the possible filter label before passing the ID to updateDetailsWindow + connect(ui->listFrameID, &QListWidget::currentTextChanged, + [this](QString itemText) + { + changeID(FilterUtility::getId(itemText)); + } ); + connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int))); ui->graphView->setContextMenuPolicy(Qt::CustomContextMenu); @@ -105,6 +112,9 @@ FlowViewWindow::FlowViewWindow(const QVector *frames, QWidget *parent) connect(ui->flowView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequestFlow(QPoint))); connect(ui->flowView, SIGNAL(gridClicked(int,int)), this, SLOT(gotCellClick(int, int))); + // Prevent annoying accidental horizontal scrolling when filter list is populated with long interpreted message names + ui->listFrameID->horizontalScrollBar()->setEnabled(false); + playbackTimer->setInterval(ui->spinPlayback->value()); //set the timer to the default value of the control } @@ -119,7 +129,7 @@ void FlowViewWindow::showEvent(QShowEvent* event) refreshIDList(); if (ui->listFrameID->count() > 0) { - changeID(ui->listFrameID->item(0)->text()); + changeID(FilterUtility::getId(ui->listFrameID->item(0))); ui->listFrameID->setCurrentRow(0); } updateFrameLabel(); @@ -161,6 +171,11 @@ void FlowViewWindow::readSettings() ui->cbTimeGraph->setChecked(true); } + if (settings.value("Main/FilterLabeling", false).toBool()) + ui->listFrameID->setMaximumWidth(250); + else + ui->listFrameID->setMaximumWidth(120); + secondsMode = settings.value("Main/TimeSeconds", false).toBool(); openGLMode = settings.value("Main/UseOpenGL", false).toBool(); } @@ -252,7 +267,7 @@ void FlowViewWindow::gotCenterTimeID(int32_t ID, double timestamp) for (int j = 0; j < ui->listFrameID->count(); j++) { - int thisNum = Utility::ParseStringToNum(ui->listFrameID->item(j)->text()); + int thisNum = FilterUtility::getIdAsInt(ui->listFrameID->item(j)); if (thisNum == ID) { ui->listFrameID->setCurrentRow(j); @@ -423,7 +438,7 @@ void FlowViewWindow::updatedFrames(int numFrames) if (!foundID.contains(thisFrame.ID)) { foundID.append(thisFrame.ID); - /*QListWidgetItem* item =*/ new QListWidgetItem(Utility::formatCANID(thisFrame.ID, thisFrame.extended), ui->listFrameID); + FilterUtility::createFilterItem(thisFrame.ID, ui->listFrameID); } if (thisFrame.ID == refID) @@ -540,7 +555,7 @@ void FlowViewWindow::refreshIDList() if (!foundID.contains(id)) { foundID.append(id); - /*QListWidgetItem* item = */ new QListWidgetItem(Utility::formatCANID(id, thisFrame.extended), ui->listFrameID); + FilterUtility::createFilterItem(id, ui->listFrameID); } } //default is to sort in ascending order diff --git a/re/frameinfowindow.cpp b/re/frameinfowindow.cpp index 4db0fbb..894e6f8 100644 --- a/re/frameinfowindow.cpp +++ b/re/frameinfowindow.cpp @@ -4,6 +4,7 @@ #include "helpwindow.h" #include #include +#include "filterutility.h" const QColor FrameInfoWindow::byteGraphColors[8] = {Qt::blue, Qt::green, Qt::black, Qt::red, //0 1 2 3 Qt::gray, Qt::yellow, Qt::cyan, Qt::darkMagenta}; //4 5 6 7 @@ -22,7 +23,13 @@ FrameInfoWindow::FrameInfoWindow(const QVector *frames, QWidget *paren modelFrames = frames; - connect(ui->listFrameID, &QListWidget::currentTextChanged, this, &FrameInfoWindow::updateDetailsWindow); + // Using lambda expression to strip away the possible filter label before passing the ID to updateDetailsWindow + connect(ui->listFrameID, &QListWidget::currentTextChanged, + [this](QString itemText) + { + FrameInfoWindow::updateDetailsWindow(FilterUtility::getId(itemText)); + } ); + connect(MainWindow::getReference(), &MainWindow::framesUpdated, this, &FrameInfoWindow::updatedFrames); connect(ui->btnSave, &QAbstractButton::clicked, this, &FrameInfoWindow::saveDetails); @@ -82,6 +89,9 @@ FrameInfoWindow::FrameInfoWindow(const QVector *frames, QWidget *paren ui->timeHistogram->setAntialiasedElements(QCP::aeNone); } + // Prevent annoying accidental horizontal scrolling when filter list is populated with long interpreted message names + ui->listFrameID->horizontalScrollBar()->setEnabled(false); + installEventFilter(this); for (int i = 0; i < 8; i++) @@ -98,7 +108,7 @@ void FrameInfoWindow::showEvent(QShowEvent* event) refreshIDList(); if (ui->listFrameID->count() > 0) { - updateDetailsWindow(ui->listFrameID->item(0)->text()); + updateDetailsWindow(FilterUtility::getId(ui->listFrameID->item(0))); ui->listFrameID->setCurrentRow(0); } } @@ -135,12 +145,23 @@ void FrameInfoWindow::closeEvent(QCloseEvent *event) void FrameInfoWindow::readSettings() { QSettings settings; + + if (settings.value("Main/FilterLabeling", false).toBool()) + { + ui->listFrameID->setMinimumWidth(250); + } + else + { + ui->listFrameID->setMinimumWidth(120); + } + if (settings.value("Main/SaveRestorePositions", false).toBool()) { resize(settings.value("FrameInfo/WindowSize", QSize(794, 694)).toSize()); move(settings.value("FrameInfo/WindowPos", QPoint(50, 50)).toPoint()); } useOpenGL = settings.value("Main/UseOpenGL", false).toBool(); + } void FrameInfoWindow::writeSettings() @@ -174,7 +195,7 @@ void FrameInfoWindow::updatedFrames(int numFrames) refreshIDList(); if (ui->listFrameID->count() > 0) { - updateDetailsWindow(ui->listFrameID->item(0)->text()); + updateDetailsWindow(FilterUtility::getId(ui->listFrameID->item(0))); ui->listFrameID->setCurrentRow(0); } } @@ -185,7 +206,7 @@ void FrameInfoWindow::updatedFrames(int numFrames) unsigned int currID = 0; if (ui->listFrameID->currentItem()) - currID = static_cast(ui->listFrameID->currentItem()->text().toInt(nullptr, 16)); + currID = static_cast(FilterUtility::getIdAsInt(ui->listFrameID->currentItem())); bool thisID = false; for (int x = modelFrames->count() - numFrames; x < modelFrames->count(); x++) { @@ -194,7 +215,7 @@ void FrameInfoWindow::updatedFrames(int numFrames) if (!foundID.contains(id)) { foundID.append(id); - ui->listFrameID->addItem(Utility::formatCANID(id, thisFrame.extended)); + FilterUtility::createFilterItem(id, ui->listFrameID); } if (currID == modelFrames->at(x).ID) @@ -266,6 +287,7 @@ void FrameInfoWindow::updateDetailsWindow(QString newID) if (frameCache[0].extended) //if these frames seem to be extended then try for J1939 decoding { + // ------- J1939 decoding ---------- J1939ID jid; jid.src = targettedID & 0xFF; jid.priority = targettedID >> 26; @@ -273,36 +295,56 @@ void FrameInfoWindow::updateDetailsWindow(QString newID) jid.pf = (targettedID >> 16) & 0xFF; jid.ps = (targettedID >> 8) & 0xFF; + tempItem = new QTreeWidgetItem(); + tempItem->setText(0, tr("J1939 decoding")); + baseNode->addChild(tempItem); + if (jid.pf > 0xEF) { jid.isBroadcast = true; jid.dest = 0xFFFF; tempItem = new QTreeWidgetItem(); - tempItem->setText(0, tr("Broadcast Frame")); + tempItem->setText(0, tr(" Broadcast Frame")); baseNode->addChild(tempItem); } else { jid.dest = jid.ps; tempItem = new QTreeWidgetItem(); - tempItem->setText(0, tr("Destination ID: ") + Utility::formatNumber(static_cast(jid.dest))); + tempItem->setText(0, tr(" Destination ID: ") + Utility::formatNumber(static_cast(jid.dest))); baseNode->addChild(tempItem); } tempItem = new QTreeWidgetItem(); - tempItem->setText(0, tr("SRC: ") + Utility::formatNumber(static_cast(jid.src))); + tempItem->setText(0, tr(" SRC: ") + Utility::formatNumber(static_cast(jid.src))); baseNode->addChild(tempItem); tempItem = new QTreeWidgetItem(); - tempItem->setText(0, tr("PGN: ") + Utility::formatNumber(static_cast(jid.pgn)) + "(" + QString::number(jid.pgn) + ")"); + tempItem->setText(0, tr(" PGN: ") + Utility::formatNumber(static_cast(jid.pgn)) + "(" + QString::number(jid.pgn) + ")"); baseNode->addChild(tempItem); tempItem = new QTreeWidgetItem(); - tempItem->setText(0, tr("PF: ") + Utility::formatNumber(static_cast(jid.pf))); + tempItem->setText(0, tr(" PF: ") + Utility::formatNumber(static_cast(jid.pf))); baseNode->addChild(tempItem); tempItem = new QTreeWidgetItem(); - tempItem->setText(0, tr("PS: ") + Utility::formatNumber(static_cast(jid.ps))); + tempItem->setText(0, tr(" PS: ") + Utility::formatNumber(static_cast(jid.ps))); baseNode->addChild(tempItem); + + // ------- GMLAN 29bit decoding ---------- + tempItem = new QTreeWidgetItem(); + tempItem->setText(0, tr("GMLAN 29bit decoding")); + baseNode->addChild(tempItem); + + tempItem = new QTreeWidgetItem(); + tempItem->setText(0, tr(" Priority bits: ") + Utility::formatNumber( FilterUtility::getGMLanPriorityBits(targettedID))); + baseNode->addChild(tempItem); + tempItem = new QTreeWidgetItem(); + tempItem->setText(0, tr(" Arbitration Id: ") + Utility::formatNumber( FilterUtility::getGMLanArbitrationId(targettedID))); + baseNode->addChild(tempItem); + tempItem = new QTreeWidgetItem(); + tempItem->setText(0, tr(" Sender Id: ") + Utility::formatNumber( FilterUtility::getGMLanSenderId(targettedID))); + baseNode->addChild(tempItem); + } tempItem = new QTreeWidgetItem(); @@ -562,7 +604,7 @@ void FrameInfoWindow::refreshIDList() if (!foundID.contains(id)) { foundID.append(id); - ui->listFrameID->addItem(Utility::formatCANID(id, thisFrame.extended)); + FilterUtility::createFilterItem(id, ui->listFrameID); } } //default is to sort in ascending order @@ -603,7 +645,7 @@ void FrameInfoWindow::saveDetails() //go through all IDs, recalculate the data, and then save it to file for (int i = 0; i < ui->listFrameID->count(); i++) { - updateDetailsWindow(ui->listFrameID->item(i)->text()); + updateDetailsWindow(FilterUtility::getId(ui->listFrameID->item(i))); dumpNode(ui->treeDetails->invisibleRootItem(), outFile, 0); outFile->write("\n\n"); } diff --git a/re/fuzzingwindow.cpp b/re/fuzzingwindow.cpp index 00fedb0..43c60c7 100644 --- a/re/fuzzingwindow.cpp +++ b/re/fuzzingwindow.cpp @@ -5,6 +5,7 @@ #include "mainwindow.h" #include "helpwindow.h" #include "connections/canconmanager.h" +#include "filterutility.h" FuzzingWindow::FuzzingWindow(const QVector *frames, QWidget *parent) : QDialog(parent), @@ -43,6 +44,9 @@ FuzzingWindow::FuzzingWindow(const QVector *frames, QWidget *parent) : for (int n = 0; n < numBuses; n++) ui->cbBuses->addItem(QString::number(n)); ui->cbBuses->addItem(tr("All")); + // Prevent annoying accidental horizontal scrolling when filter list is populated with long interpreted message names + ui->listID->horizontalScrollBar()->setEnabled(false); + installEventFilter(this); } @@ -95,11 +99,7 @@ void FuzzingWindow::updatedFrames(int numFrames) { foundIDs.append(id); selectedIDs.append(id); - QListWidgetItem *thisItem = new QListWidgetItem(); - thisItem->setText(Utility::formatCANID(id, modelFrames->at(i).extended)); - thisItem->setFlags(thisItem->flags() | Qt::ItemIsUserCheckable); - thisItem->setCheckState(Qt::Checked); - ui->listID->addItem(thisItem); + FilterUtility::createCheckableFilterItem(id, true, ui->listID); } } } @@ -376,11 +376,7 @@ void FuzzingWindow::refreshIDList() { foundIDs.append(id); selectedIDs.append(id); - QListWidgetItem *thisItem = new QListWidgetItem(); - thisItem->setText(Utility::formatCANID(id, thisFrame.extended)); - thisItem->setFlags(thisItem->flags() | Qt::ItemIsUserCheckable); - thisItem->setCheckState(Qt::Checked); - ui->listID->addItem(thisItem); + FilterUtility::createCheckableFilterItem(id, true, ui->listID); } } //default is to sort in ascending order @@ -389,7 +385,7 @@ void FuzzingWindow::refreshIDList() void FuzzingWindow::idListChanged(QListWidgetItem *item) { - int id = Utility::ParseStringToNum(item->text()); + int id = FilterUtility::getIdAsInt(item); if (item->checkState() == Qt::Checked) { if (!selectedIDs.contains(id)) diff --git a/ui/dbcloadsavewindow.ui b/ui/dbcloadsavewindow.ui index d32abf1..4041084 100644 --- a/ui/dbcloadsavewindow.ui +++ b/ui/dbcloadsavewindow.ui @@ -6,7 +6,7 @@ 0 0 - 506 + 680 665 diff --git a/ui/mainsettingsdialog.ui b/ui/mainsettingsdialog.ui index 05de6aa..cce67e8 100644 --- a/ui/mainsettingsdialog.ui +++ b/ui/mainsettingsdialog.ui @@ -73,6 +73,13 @@ + + + + Label filters using messages from DBC files + + +