diff --git a/README.md b/README.md index 9040884..4566633 100644 --- a/README.md +++ b/README.md @@ -97,3 +97,18 @@ when you installed Qt. ### What to do if `qmake` fails with error `Project ERROR: Unknown module(s) in QT: qml serialbus help` on Ubuntu? : `sudo apt install libqt5serialbus5-dev qtdeclarative5-dev qttools5-dev` + +### Used Items Requiring Attribution + +nodes by Adrien Coquet from the Noun Project + +message by Vectorstall from the Noun Project + +signal by shashank singh from the Noun Project + +signal by juli from the Noun Project + +signal by yudi from the Noun Project + +Death by Adrien Coquet from the Noun Project + diff --git a/SavvyCAN.pro b/SavvyCAN.pro index 605b90b..33c8cb6 100644 --- a/SavvyCAN.pro +++ b/SavvyCAN.pro @@ -15,7 +15,7 @@ DEFINES += QCUSTOMPLOT_USE_OPENGL TARGET = SavvyCAN TEMPLATE = app -SOURCES += main.cpp\ +SOURCES += main.cpp\ mainwindow.cpp \ canframemodel.cpp \ utility.cpp \ @@ -39,6 +39,7 @@ SOURCES += main.cpp\ re/sniffer/snifferitem.cpp \ re/sniffer/sniffermodel.cpp \ re/sniffer/snifferwindow.cpp \ + dbc/dbcmessageeditor.cpp \ dbc/dbc_classes.cpp \ dbc/dbchandler.cpp \ dbc/dbcloadsavewindow.cpp \ @@ -73,7 +74,7 @@ SOURCES += main.cpp\ HEADERS += mainwindow.h \ can_structs.h \ - canframemodel.h \ + canframemodel.h \ utility.h \ qcustomplot.h \ frameplaybackwindow.h \ @@ -103,6 +104,7 @@ HEADERS += mainwindow.h \ dbc/dbcloadsavewindow.h \ dbc/dbcmaineditor.h \ dbc/dbcsignaleditor.h \ + dbc/dbcmessageeditor.h \ re/discretestatewindow.h \ re/filecomparatorwindow.h \ re/flowviewwindow.h \ @@ -132,6 +134,7 @@ HEADERS += mainwindow.h \ filterutility.h FORMS += ui/candatagrid.ui \ + ui/dbcmessageeditor.ui \ ui/connectionwindow.ui \ ui/dbcloadsavewindow.ui \ ui/dbcmaineditor.ui \ diff --git a/dbc/dbcmaineditor.cpp b/dbc/dbcmaineditor.cpp index f7e3386..f4a851d 100644 --- a/dbc/dbcmaineditor.cpp +++ b/dbc/dbcmaineditor.cpp @@ -20,41 +20,30 @@ DBCMainEditor::DBCMainEditor( const QVector *frames, QWidget *parent) dbcHandler = DBCHandler::getReference(); referenceFrames = frames; - QStringList headers; - headers << "Node Name" << "Comment"; - ui->NodesTable->setColumnCount(2); - ui->NodesTable->setColumnWidth(0, 240); - ui->NodesTable->setColumnWidth(1, 700); - ui->NodesTable->setHorizontalHeaderLabels(headers); - ui->NodesTable->horizontalHeader()->setStretchLastSection(true); - - QStringList headers2; - headers2 << "Msg ID" << "Msg Name" << "Data Len" << "Signals" << "Fg" << "Bg" << "Comment"; - ui->MessagesTable->setColumnCount(headers2.count()); - ui->MessagesTable->setColumnWidth(0, 80); - ui->MessagesTable->setColumnWidth(1, 200); - ui->MessagesTable->setColumnWidth(2, 80); - ui->MessagesTable->setColumnWidth(3, 80); - ui->MessagesTable->setColumnWidth(4, 40); - ui->MessagesTable->setColumnWidth(5, 40); - ui->MessagesTable->setColumnWidth(6, 300); - ui->MessagesTable->setHorizontalHeaderLabels(headers2); - ui->MessagesTable->horizontalHeader()->setStretchLastSection(true); - - connect(ui->NodesTable, SIGNAL(cellChanged(int,int)), this, SLOT(onCellChangedNode(int,int))); - connect(ui->NodesTable, SIGNAL(cellClicked(int,int)), this, SLOT(onCellClickedNode(int,int))); - connect(ui->NodesTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomMenuNode(QPoint))); - ui->NodesTable->setContextMenuPolicy(Qt::CustomContextMenu); - - connect(ui->MessagesTable, SIGNAL(cellChanged(int,int)), this, SLOT(onCellChangedMessage(int,int))); - connect(ui->MessagesTable, SIGNAL(cellClicked(int,int)), this, SLOT(onCellClickedMessage(int,int))); - connect(ui->MessagesTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomMenuMessage(QPoint))); - ui->MessagesTable->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->btnSearch, &QAbstractButton::clicked, this, &DBCMainEditor::handleSearch); connect(ui->lineSearch, &QLineEdit::returnPressed, this, &DBCMainEditor::handleSearch); + connect(ui->treeDBC, &QTreeWidget::doubleClicked, this, &DBCMainEditor::onTreeDoubleClicked); sigEditor = new DBCSignalEditor(this); + msgEditor = new DBCMessageEditor(this); + + nodeIcon = QIcon(":/icons/images/node.png"); + messageIcon = QIcon(":/icons/images/message.png"); + signalIcon = QIcon(":/icons/images/signal.png"); + multiplexedSignalIcon = QIcon(":/icons/images/multiplexed-signal.png"); + multiplexorSignalIcon = QIcon(":/icons/images/multiplexor-signal.png"); + + //ui->btnDelete->setFixedSize(32,32); + ui->btnDelete->setIconSize(QSize(32, 32)); + + //ui->btnNewNode->setFixedSize(32,32); + ui->btnNewNode->setIconSize(QSize(32, 32)); + + //ui->btnNewMessage->setFixedSize(32,32); + ui->btnNewMessage->setIconSize(QSize(32, 32)); + + //ui->btnNewSignal->setFixedSize(32,32); + ui->btnNewSignal->setIconSize(QSize(32, 32)); installEventFilter(this); } @@ -63,13 +52,7 @@ void DBCMainEditor::showEvent(QShowEvent* event) { QDialog::showEvent(event); - inhibitCellChanged = true; - refreshNodesTable(); - if (dbcFile->dbc_nodes.count() > 0) - refreshMessagesTable(&dbcFile->dbc_nodes.at(0)); - - currRow = 0; - inhibitCellChanged = false; + refreshTree(); } DBCMainEditor::~DBCMainEditor() @@ -132,30 +115,20 @@ void DBCMainEditor::writeSettings() } } -void DBCMainEditor::onCustomMenuNode(QPoint point) -{ - QMenu *menu = new QMenu(this); - menu->setAttribute(Qt::WA_DeleteOnClose); - - menu->addAction(tr("Delete currently selected node"), this, SLOT(deleteCurrentNode())); - - menu->popup(ui->NodesTable->mapToGlobal(point)); - -} - -void DBCMainEditor::onCustomMenuMessage(QPoint point) +void DBCMainEditor::onCustomMenuTree(QPoint point) { QMenu *menu = new QMenu(this); menu->setAttribute(Qt::WA_DeleteOnClose); menu->addAction(tr("Delete currently selected message"), this, SLOT(deleteCurrentMessage())); - menu->popup(ui->MessagesTable->mapToGlobal(point)); + //menu->popup(ui->MessagesTable->mapToGlobal(point)); } -void DBCMainEditor::deleteCurrentNode() +void DBCMainEditor::deleteCurrentTreeItem() { + /* int thisRow = ui->NodesTable->currentRow(); QTableWidgetItem* thisItem = ui->NodesTable->item(thisRow, 0); if (!thisItem) return; @@ -168,11 +141,12 @@ void DBCMainEditor::deleteCurrentNode() refreshMessagesTable(&dbcFile->dbc_nodes[0]); ui->NodesTable->selectRow(0); inhibitCellChanged = false; - } + } */ } -void DBCMainEditor::deleteCurrentMessage() -{ +//void DBCMainEditor::deleteCurrentMessage() +//{ + /* int thisRow = ui->MessagesTable->currentRow(); QTableWidgetItem* thisItem = ui->MessagesTable->item(thisRow, 0); if (!thisItem) return; @@ -181,10 +155,12 @@ void DBCMainEditor::deleteCurrentMessage() ui->MessagesTable->removeRow(thisRow); dbcFile->messageHandler->removeMessageByIndex(thisRow); } -} + */ +//} void DBCMainEditor::handleSearch() { + /* uint32_t msgId = Utility::ParseStringToNum(ui->lineSearch->text()); if (ui->radioID->isChecked()) { @@ -255,228 +231,50 @@ void DBCMainEditor::handleSearch() } } } - } + } */ } -void DBCMainEditor::onCellChangedNode(int row,int col) +//Double clicking is interpreted as a desire to edit the given item. +void DBCMainEditor::onTreeDoubleClicked(const QModelIndex &index) { - if (inhibitCellChanged) return; - if (row == ui->NodesTable->rowCount() - 1) - { - //if this was the last row then it's new and we need to both - //create another potentially new record underneath and also - //add a node entry in the nodes list and store the record - //That is, so long as the node name was filled out - if (col == 0) - { - DBC_NODE newNode; - QString newName = ui->NodesTable->item(row, col)->text().simplified().replace(' ', '_'); - qDebug() << "new name: " << newName; - if (newName.length() == 0) return; - if (dbcFile->findNodeByName(newName) != nullptr) //duplicates an existing node! - { - QMessageBox msg; - msg.setParent(nullptr); - msg.setText("An existing node with that name already exists! Aborting!"); - msg.exec(); - return; - } - newNode.name = newName; - dbcFile->dbc_nodes.append(newNode); - qDebug() << "# of nodes now " << dbcFile->dbc_nodes.count(); - QTableWidgetItem *widgetName = new QTableWidgetItem(newName); - inhibitCellChanged = true; - ui->NodesTable->setItem(row, col, widgetName); - ui->NodesTable->insertRow(ui->NodesTable->rowCount()); - inhibitCellChanged = false; - } - } - else - { - if (col == 0) - { - DBC_NODE *oldNode = dbcFile->findNodeByIdx(row); - QString nodeName = ui->NodesTable->item(row, col)->text().simplified().replace(' ', '_'); - if (oldNode == nullptr) return; - if (row != 0) oldNode->name = nodeName; - else nodeName = oldNode->name; - inhibitCellChanged = true; - QTableWidgetItem *widgetName = new QTableWidgetItem(nodeName); - ui->NodesTable->setItem(row, col, widgetName); - inhibitCellChanged = false; - } - if (col == 1) //must have been col 1 then - { - QString nodeName = ui->NodesTable->item(row, 0)->text().simplified().replace(' ', '_'); - qDebug() << "searching for node " << nodeName; - DBC_NODE *thisNode = dbcFile->findNodeByName(nodeName); - if (thisNode == nullptr) return; - thisNode->comment = ui->NodesTable->item(row, col)->text().simplified(); - qDebug() << "New comment: " << thisNode->comment; - } - } - ui->NodesTable->setCurrentCell(row, col); -} + Q_UNUSED(index) -void DBCMainEditor::onCellChangedMessage(int row,int col) -{ - QTableWidgetItem* item = nullptr; - bool ret = false; - DBC_MESSAGE *msg = nullptr; - uint msgID; - - if (inhibitCellChanged) return; - - DBC_NODE *node = dbcFile->findNodeByIdx(ui->NodesTable->currentRow()); - if (node == nullptr) - { - qDebug() << "No node set?!? This is bad!"; - return; - } - - item = ui->MessagesTable->item(row, 0); - if(!item) return; - - msgID = Utility::ParseStringToNum2(item->text(), &ret); - msg = dbcFile->messageHandler->findMsgByID(msgID); - - switch(col) - { - case 0: //msg id - { - /* sanity checks */ - if(!ret) - { - /* bad message id */ - ui->MessagesTable->item(row, 0)->setText(""); - return; - } - if (msg != nullptr) - { - QMessageBox msg; - msg.setParent(nullptr); - msg.setText("An existing msg with that ID already exists! Aborting!"); - msg.exec(); - - ui->MessagesTable->item(row, 0)->setText(""); - return; - } - - /* insert row */ - DBC_MESSAGE newMsg; - newMsg.ID = msgID; - newMsg.name = ""; - newMsg.sender = node; - newMsg.len = 0; - newMsg.fgColor = QColor(dbcFile->findAttributeByName("GenMsgForegroundColor")->defaultValue.toString()); - newMsg.bgColor = QColor(dbcFile->findAttributeByName("GenMsgBackgroundColor")->defaultValue.toString()); - - for (int i = 0; i < referenceFrames->length(); i++) - { - if ((uint) referenceFrames->at(i).frameId() == msgID) - { - newMsg.len = static_cast(referenceFrames->at(i).payload().length()); - break; - } - } - dbcFile->messageHandler->addMessage(newMsg); - - /* insert message in table */ - inhibitCellChanged = true; - - item = ui->MessagesTable->item(row, 0); - item->setFlags(item->flags() & ~Qt::ItemIsEditable); - item->setText(Utility::formatCANID(msgID)); - - for(int i=1 ; i < ui->MessagesTable->columnCount(); i++) - { - item = ui->MessagesTable->item(row, i); - item->setFlags(item->flags() | Qt::ItemIsEditable); - } - - /* set length */ - item = ui->MessagesTable->item(row, 2); - item->setText(QString::number(newMsg.len)); - - inhibitCellChanged = false; - - /* insert a new row */ - insertBlankRow(); - break; - } - case 1: //msg name - { - QString msgName = ui->MessagesTable->item(row, 1)->text().simplified().replace(' ', '_'); - if (msgName.length() == 0) return; - if( ret && (msg!=nullptr) ) - msg->name = msgName; - break; - } - case 2: //data length - { - bool parseOk = false; - uint msgLen = ui->MessagesTable->item(row, col)->text().toUInt(&parseOk); - - /* sanity checks */ - if(!parseOk) - { - ui->MessagesTable->item(row, col)->setText(""); - return; - } - if (msgLen > 8) - { - msgLen = 8; - ui->MessagesTable->item(row, col)->setText(QString::number(msgLen)); - } - - if( ret && (msg!=nullptr) ) - msg->len = msgLen; - break; - } - case 3: //signals (number) - we don't handle anything here. User cannot directly change this value - break; - case 6: //comment - { - QString msgComment = ui->MessagesTable->item(row, col)->text().simplified(); - if( ret && (msgComment!=nullptr) ) - msg->comment = msgComment; - break; - } - } - - ui->MessagesTable->setCurrentCell(row, col); -} - -void DBCMainEditor::onCellClickedNode(int row, int col) -{ - //reload messages list if the currently selected row has changed. - qDebug() << "Clicked at row " << row << " col " << col; - if (row != currRow) - { - currRow = row; - QTableWidgetItem *item = ui->NodesTable->item(currRow, 0); - QString nodeName; - if (item == nullptr) return; - - nodeName = item->text(); - qDebug() << "Trying to find node with name " << nodeName; - DBC_NODE *node = dbcFile->findNodeByName(nodeName); - //qDebug() << "Address of node: " << (int)node; - inhibitCellChanged = true; - refreshMessagesTable(node); - inhibitCellChanged = false; - } -} - -void DBCMainEditor::onCellClickedMessage(int row, int col) -{ - QTableWidgetItem* thisItem = ui->MessagesTable->item(row, col); - QTableWidgetItem* firstCol = ui->MessagesTable->item(row, 0); + QTreeWidgetItem* firstCol = ui->treeDBC->currentItem(); bool ret = false; DBC_MESSAGE *msg; + DBC_SIGNAL *sig; uint32_t msgID; + QString idString; - if (col == 3) //3 is the signals field. If clicked we go to the signals dialog + qDebug() << firstCol->data(0, Qt::UserRole) << " - " << firstCol->text(0); + + switch (firstCol->data(0, Qt::UserRole).toInt()) + { + case 1: //a node + break; + case 2: //a message + idString = firstCol->text(0).split(" ")[0]; + msgID = static_cast(Utility::ParseStringToNum(idString)); + msg = dbcFile->messageHandler->findMsgByID(msgID); + msgEditor->setMessageRef(msg); + msgEditor->setFileIdx(fileIdx); + msgEditor->setWindowModality(Qt::WindowModal); + msgEditor->exec(); //blocks this window from being active until we're done + break; + case 3: //a signal + idString = firstCol->parent()->text(0).split(" ")[0]; + msgID = static_cast(Utility::ParseStringToNum(idString)); + msg = dbcFile->messageHandler->findMsgByID(msgID); + sig = msg->sigHandler->findSignalByName(firstCol->text(0).split(" ")[0]); + sigEditor->setSignalRef(sig); + sigEditor->setMessageRef(msg); + sigEditor->setFileIdx(fileIdx); + sigEditor->setWindowModality(Qt::WindowModal); + sigEditor->exec(); //blocks this window from being active until we're done + break; + } + +/* if (col == 3) //3 is the signals field. If clicked we go to the signals dialog { QTableWidgetItem* msg = ui->MessagesTable->item(row, 0); if(msg) { @@ -546,15 +344,17 @@ void DBCMainEditor::onCellClickedMessage(int row, int col) msg->attributes.append(newVal); } } - } + } */ } -void DBCMainEditor::refreshNodesTable() -{ - ui->NodesTable->clearContents(); //first step, clear out any previous crap - ui->NodesTable->setRowCount(0); - int rowIdx; +/* + * Recreate the whole tree with pretty icons and custom user roles that give the rest of code an easy way to figure out whether a given tree node + * is a node, message, or signal. +*/ +void DBCMainEditor::refreshTree() +{ + ui->treeDBC->clear(); if (dbcFile->findNodeByName("Vector__XXX") == nullptr) { @@ -564,82 +364,40 @@ void DBCMainEditor::refreshNodesTable() dbcFile->dbc_nodes.append(newNode); } - for (int x = 0; x < dbcFile->dbc_nodes.count(); x++) - { - DBC_NODE node = dbcFile->dbc_nodes.at(x); - QTableWidgetItem *nodeName = new QTableWidgetItem(node.name); - QTableWidgetItem *nodeComment = new QTableWidgetItem(node.comment); - rowIdx = ui->NodesTable->rowCount(); - ui->NodesTable->insertRow(rowIdx); - ui->NodesTable->setItem(rowIdx, 0, nodeName); - ui->NodesTable->setItem(rowIdx, 1, nodeComment); - } - - //insert a fresh entry at the bottom that contains nothing - ui->NodesTable->insertRow(ui->NodesTable->rowCount()); - ui->NodesTable->selectRow(0); -} - -void DBCMainEditor::refreshMessagesTable(const DBC_NODE *node) -{ - ui->MessagesTable->clearContents(); - ui->MessagesTable->setRowCount(0); - - qDebug() << "In refreshMessagesTable"; - - int rowIdx; - - if (node != nullptr) + foreach (DBC_NODE node, dbcFile->dbc_nodes) { + QTreeWidgetItem *nodeItem = new QTreeWidgetItem(); + QString nodeInfo = node.name; + if (node.comment.count() > 0) nodeInfo.append(" - ").append(node.comment); + nodeItem->setText(0, nodeInfo); + nodeItem->setIcon(0, nodeIcon); + nodeItem->setData(0, Qt::UserRole, 1); for (int x = 0; x < dbcFile->messageHandler->getCount(); x++) { DBC_MESSAGE *msg = dbcFile->messageHandler->findMsgByIdx(x); - if (msg->sender == node) + if (msg->sender->name == node.name) { - //many of these are simplistic first versions just to test functionality. - QTableWidgetItem *msgID = new QTableWidgetItem(Utility::formatCANID(msg->ID)); - QTableWidgetItem *msgName = new QTableWidgetItem(msg->name); - QTableWidgetItem *msgLen = new QTableWidgetItem(QString::number(msg->len)); - QTableWidgetItem *msgSignals = new QTableWidgetItem(QString::number(msg->sigHandler->getCount())); - QTableWidgetItem *fgColor = new QTableWidgetItem(""); - if (msg->fgColor.isValid()) fgColor->setBackground(msg->fgColor); - else fgColor->setBackground(QColor(dbcFile->findAttributeByName("GenMsgForegroundColor")->defaultValue.toString())); - QTableWidgetItem *bgColor = new QTableWidgetItem(""); - if (msg->bgColor.isValid()) bgColor->setBackground(msg->bgColor); - else bgColor->setBackground(QColor(dbcFile->findAttributeByName("GenMsgBackgroundColor")->defaultValue.toString())); - - QTableWidgetItem *msgComment = new QTableWidgetItem(msg->comment); - - rowIdx = ui->MessagesTable->rowCount(); - ui->MessagesTable->insertRow(rowIdx); - ui->MessagesTable->setItem(rowIdx, 0, msgID); - ui->MessagesTable->setItem(rowIdx, 1, msgName); - ui->MessagesTable->setItem(rowIdx, 2, msgLen); - ui->MessagesTable->setItem(rowIdx, 3, msgSignals); - ui->MessagesTable->setItem(rowIdx, 4, fgColor); - ui->MessagesTable->setItem(rowIdx, 5, bgColor); - ui->MessagesTable->setItem(rowIdx, 6, msgComment); - //note that there is a sending node field in the structure but we're - //not displaying it. It has to be the node we selected from the node list - //so no need to show that here. + QTreeWidgetItem *msgItem = new QTreeWidgetItem(nodeItem); + QString msgInfo = Utility::formatCANID(msg->ID) + " " + msg->name; + if (msg->comment.count() > 0) msgInfo.append(" - ").append(msg->comment); + msgItem->setText(0, msgInfo); + msgItem->setIcon(0, messageIcon); + msgItem->setData(0, Qt::UserRole, 2); + for (int i = 0; i < msg->sigHandler->getCount(); i++) + { + DBC_SIGNAL *sig = msg->sigHandler->findSignalByIdx(i); + QTreeWidgetItem *sigItem = new QTreeWidgetItem(msgItem); + QString sigInfo = sig->name; + if (sig->comment.count() > 0) sigInfo.append(" - ").append(sig->comment); + sigItem->setText(0, sigInfo); + if (sig->isMultiplexed) sigItem->setIcon(0, multiplexedSignalIcon); + else if (sig->isMultiplexor) sigItem->setIcon(0, multiplexorSignalIcon); + else sigItem->setIcon(0, signalIcon); + sigItem->setData(0, Qt::UserRole, 3); + } } } + ui->treeDBC->addTopLevelItem(nodeItem); } - - //insert blank record that can be used to add new messages - insertBlankRow(); -} - -void DBCMainEditor::insertBlankRow() -{ - int rowIdx = ui->MessagesTable->rowCount(); - ui->MessagesTable->insertRow(rowIdx); - for(int i=1 ; i < ui->MessagesTable->columnCount(); i++) - { - QTableWidgetItem *item = new QTableWidgetItem(""); - if (i == 4) item->setBackground(QApplication::palette().color(QPalette::WindowText)); //foreground color - if (i == 5) item->setBackground(QApplication::palette().color(QPalette::Base)); - item->setFlags(item->flags() & ~Qt::ItemIsEditable); - ui->MessagesTable->setItem(rowIdx, i, item); - } + ui->treeDBC->sortItems(0, Qt::SortOrder::AscendingOrder); //sort the display list for ease in viewing by mere mortals, helps me a lot. } diff --git a/dbc/dbcmaineditor.h b/dbc/dbcmaineditor.h index c369c2c..3d2447e 100644 --- a/dbc/dbcmaineditor.h +++ b/dbc/dbcmaineditor.h @@ -3,8 +3,10 @@ #include #include +#include #include "dbchandler.h" #include "dbcsignaleditor.h" +#include "dbcmessageeditor.h" #include "utility.h" namespace Ui { @@ -21,14 +23,9 @@ public: void setFileIdx(int idx); private slots: - void onCellChangedNode(int,int); - void onCellClickedNode(int, int); - void onCellClickedMessage(int, int); - void onCellChangedMessage(int,int); - void onCustomMenuNode(QPoint); - void onCustomMenuMessage(QPoint); - void deleteCurrentNode(); - void deleteCurrentMessage(); + void onTreeDoubleClicked(const QModelIndex &index); + void onCustomMenuTree(QPoint); + void deleteCurrentTreeItem(); void handleSearch(); private: @@ -36,19 +33,21 @@ private: DBCHandler *dbcHandler; const QVector *referenceFrames; DBCSignalEditor *sigEditor; - int currRow; + DBCMessageEditor *msgEditor; DBCFile *dbcFile; int fileIdx; - bool inhibitCellChanged; + QIcon nodeIcon; + QIcon messageIcon; + QIcon signalIcon; + QIcon multiplexorSignalIcon; + QIcon multiplexedSignalIcon; - void refreshNodesTable(); - void refreshMessagesTable(const DBC_NODE *node); + void refreshTree(); void showEvent(QShowEvent* event); void closeEvent(QCloseEvent *event); bool eventFilter(QObject *obj, QEvent *event); void readSettings(); void writeSettings(); - void insertBlankRow(); }; diff --git a/dbc/dbcmessageeditor.cpp b/dbc/dbcmessageeditor.cpp new file mode 100644 index 0000000..1ccdcb5 --- /dev/null +++ b/dbc/dbcmessageeditor.cpp @@ -0,0 +1,185 @@ +#include "dbcmessageeditor.h" +#include "ui_dbcmessageeditor.h" + +#include +#include +#include +#include "helpwindow.h" +#include "utility.h" + +DBCMessageEditor::DBCMessageEditor(QWidget *parent) : + QDialog(parent), + ui(new Ui::DBCMessageEditor) +{ + ui->setupUi(this); + + readSettings(); + + dbcHandler = DBCHandler::getReference(); + dbcMessage = nullptr; + + connect(ui->btnTextColor, &QAbstractButton::clicked, + [=]() + { + QColor newColor = QColorDialog::getColor(dbcMessage->fgColor); + + dbcMessage->fgColor = newColor; + DBC_ATTRIBUTE_VALUE *val = dbcMessage->findAttrValByName("GenMsgForegroundColor"); + if (val) + { + val->value = newColor.name(); + } + else + { + DBC_ATTRIBUTE_VALUE newVal; + newVal.attrName = "GenMsgForegroundColor"; + newVal.value = newColor.name(); + dbcMessage->attributes.append(newVal); + } + generateSampleText(); + }); + + connect(ui->btnBackgroundColor, &QAbstractButton::clicked, + [=]() + { + QColor newColor = QColorDialog::getColor(dbcMessage->bgColor); + + dbcMessage->bgColor = newColor; + DBC_ATTRIBUTE_VALUE *val = dbcMessage->findAttrValByName("GenMsgBackgroundColor"); + if (val) + { + val->value = newColor.name(); + } + else + { + DBC_ATTRIBUTE_VALUE newVal; + newVal.attrName = "GenMsgBackgroundColor"; + newVal.value = newColor.name(); + dbcMessage->attributes.append(newVal); + } + generateSampleText(); + }); + + installEventFilter(this); +} + +DBCMessageEditor::~DBCMessageEditor() +{ + removeEventFilter(this); + delete ui; +} + +void DBCMessageEditor::closeEvent(QCloseEvent *event) +{ + Q_UNUSED(event); + writeSettings(); +} + +bool DBCMessageEditor::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::KeyRelease) { + QKeyEvent *keyEvent = static_cast(event); + switch (keyEvent->key()) + { + case Qt::Key_F1: + HelpWindow::getRef()->showHelp("messageeditor.html"); + break; + } + return true; + } else { + // standard event processing + return QObject::eventFilter(obj, event); + } + return false; +} + +void DBCMessageEditor::setFileIdx(int idx) +{ + if (idx < 0 || idx > dbcHandler->getFileCount() - 1) return; + dbcFile = dbcHandler->getFileByIdx(idx); + + for (int x = 0; x < dbcFile->dbc_nodes.count(); x++) + { + ui->comboSender->addItem(dbcFile->dbc_nodes[x].name); + } +} + +void DBCMessageEditor::readSettings() +{ + QSettings settings; + if (settings.value("Main/SaveRestorePositions", false).toBool()) + { + resize(settings.value("DBCMessageEditor/WindowSize", QSize(340, 400)).toSize()); + move(settings.value("DBCMessageEditor/WindowPos", QPoint(100, 100)).toPoint()); + } +} + +void DBCMessageEditor::writeSettings() +{ + QSettings settings; + + if (settings.value("Main/SaveRestorePositions", false).toBool()) + { + settings.setValue("DBCMessageEditor/WindowSize", size()); + settings.setValue("DBCMessageEditor/WindowPos", pos()); + } +} + + +void DBCMessageEditor::setMessageRef(DBC_MESSAGE *msg) +{ + dbcMessage = msg; +} + +void DBCMessageEditor::showEvent(QShowEvent* event) +{ + QDialog::showEvent(event); + + refreshView(); +} + +void DBCMessageEditor::refreshView() +{ + ui->lineComment->setText(dbcMessage->comment); + ui->lineFrameID->setText(Utility::formatCANID(dbcMessage->ID)); + ui->lineMsgName->setText(dbcMessage->name); + ui->lineFrameLen->setText(QString::number(dbcMessage->len)); + for (int i = 0; i < ui->comboSender->count(); i++) + { + if (ui->comboSender->itemText(i) == dbcMessage->sender->name) + { + ui->comboSender->setCurrentIndex(i); + break; + } + } + + generateSampleText(); +} + +void DBCMessageEditor::generateSampleText() +{ + QBrush fg, bg; + + if (dbcMessage->fgColor.isValid()) fg = QBrush(dbcMessage->fgColor); + else fg = QBrush(QColor(dbcFile->findAttributeByName("GenMsgForegroundColor")->defaultValue.toString())); + if (dbcMessage->bgColor.isValid()) bg = QBrush(dbcMessage->bgColor); + else bg = QBrush(QColor(dbcFile->findAttributeByName("GenMsgBackgroundColor")->defaultValue.toString())); + + ui->listSample->clear(); + QListWidgetItem *item = new QListWidgetItem("Test String"); + item->setForeground(fg); + item->setBackground(bg); + ui->listSample->addItem(item); + item = new QListWidgetItem("0x20F TestMsg"); + item->setForeground(fg); + item->setBackground(bg); + ui->listSample->addItem(item); + item = new QListWidgetItem("20 FF 10 A1 BB CC 4D"); + item->setForeground(fg); + item->setBackground(bg); + ui->listSample->addItem(item); + item = new QListWidgetItem("1024.3434"); + item->setForeground(fg); + item->setBackground(bg); + ui->listSample->addItem(item); +} diff --git a/dbc/dbcmessageeditor.h b/dbc/dbcmessageeditor.h new file mode 100644 index 0000000..2685fcc --- /dev/null +++ b/dbc/dbcmessageeditor.h @@ -0,0 +1,38 @@ +#ifndef DBCMESSAGEEDITOR_H +#define DBCMESSAGEEDITOR_H + +#include +#include "dbc_classes.h" +#include "dbchandler.h" + +namespace Ui { +class DBCMessageEditor; +} + +class DBCMessageEditor : public QDialog +{ + Q_OBJECT + +public: + explicit DBCMessageEditor(QWidget *parent = nullptr); + ~DBCMessageEditor(); + void showEvent(QShowEvent*); + void setMessageRef(DBC_MESSAGE *msg); + void setFileIdx(int idx); + +private: + Ui::DBCMessageEditor *ui; + + DBCHandler *dbcHandler; + DBC_MESSAGE *dbcMessage; + DBCFile *dbcFile; + + void closeEvent(QCloseEvent *event); + bool eventFilter(QObject *obj, QEvent *event); + void readSettings(); + void writeSettings(); + void refreshView(); + void generateSampleText(); +}; + +#endif // DBCMESSAGEEDITOR_H diff --git a/dbc/dbcsignaleditor.cpp b/dbc/dbcsignaleditor.cpp index 4cd27b6..f8cbe6d 100644 --- a/dbc/dbcsignaleditor.cpp +++ b/dbc/dbcsignaleditor.cpp @@ -34,10 +34,7 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) : ui->comboType->addItem("DOUBLE PRECISION"); ui->comboType->addItem("STRING"); - connect(ui->signalsList, SIGNAL(currentRowChanged(int)), this, SLOT(clickSignalList(int))); connect(ui->bitfield, SIGNAL(gridClicked(int,int)), this, SLOT(bitfieldClicked(int,int))); - connect(ui->signalsList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomMenuSignals(QPoint))); - ui->signalsList->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->valuesTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomMenuValues(QPoint))); ui->valuesTable->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->valuesTable, SIGNAL(cellChanged(int,int)), this, SLOT(onValuesCellChanged(int,int))); @@ -155,7 +152,7 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) : QString tempNameStr = ui->txtName->text().simplified().replace(' ', '_'); if (tempNameStr.length() > 0) currentSignal->name = tempNameStr; //need to update the list too. - ui->signalsList->currentItem()->setText(currentSignal->name); + //ui->signalsList->currentItem()->setText(currentSignal->name); }); connect(ui->txtMultiplexValue, &QLineEdit::editingFinished, @@ -228,9 +225,6 @@ bool DBCSignalEditor::eventFilter(QObject *obj, QEvent *event) case Qt::Key_F1: HelpWindow::getRef()->showHelp("signaleditor.html"); break; - case Qt::Key_F2: - cloneSignal(); - break; } return true; } else { @@ -278,12 +272,18 @@ void DBCSignalEditor::setMessageRef(DBC_MESSAGE *msg) dbcMessage = msg; } +void DBCSignalEditor::setSignalRef(DBC_SIGNAL *sig) +{ + currentSignal = sig; +} + + void DBCSignalEditor::showEvent(QShowEvent* event) { QDialog::showEvent(event); - currentSignal = nullptr; - refreshSignalsList(); + fillSignalForm(currentSignal); + fillValueTable(currentSignal); } void DBCSignalEditor::onValuesCellChanged(int row,int col) @@ -317,21 +317,6 @@ void DBCSignalEditor::onValuesCellChanged(int row,int col) } } -void DBCSignalEditor::onCustomMenuSignals(QPoint point) -{ - QMenu *menu = new QMenu(this); - menu->setAttribute(Qt::WA_DeleteOnClose); - - menu->addAction(tr("Add a new signal"), this, SLOT(addNewSignal())); - if (ui->signalsList->currentRow() != -1) - { - menu->addAction(tr("Clone currently selected signal"), this, SLOT(cloneSignal())); - menu->addAction(tr("Delete currently selected signal"), this, SLOT(deleteCurrentSignal())); - } - - menu->popup(ui->signalsList->mapToGlobal(point)); -} - void DBCSignalEditor::onCustomMenuValues(QPoint point) { QMenu *menu = new QMenu(this); @@ -342,86 +327,6 @@ void DBCSignalEditor::onCustomMenuValues(QPoint point) menu->popup(ui->valuesTable->mapToGlobal(point)); } -void DBCSignalEditor::addNewSignal() -{ - int num = QRandomGenerator::global()->bounded(70000); - QString newName = "SIGNAL" + QString::number(num); - DBC_SIGNAL newSig; - newSig.name = newName; - newSig.bias = 0.0; - newSig.factor = 1.0; - newSig.intelByteOrder = true; - newSig.max = 0.0; - newSig.min = 0.0; - newSig.receiver = dbcFile->findNodeByIdx(0); - newSig.signalSize = 1; - newSig.startBit = 0; - newSig.valType = UNSIGNED_INT; - newSig.isMultiplexed = false; - newSig.isMultiplexor = false; - newSig.multiplexValue = 0; - newSig.parentMessage = dbcMessage; - - dbcMessage->sigHandler->addSignal(newSig); - - /* add item at the end of the list and select it */ - /* this will call clickSignalList */ - ui->signalsList->addItem(newName); - ui->signalsList->setCurrentRow(ui->signalsList->count()-1); -} - -void DBCSignalEditor::cloneSignal() -{ - int num = QRandomGenerator::global()->bounded(100); - - int idx = ui->signalsList->currentRow(); - if (idx < 0) return; - - DBC_SIGNAL *oldSig = dbcMessage->sigHandler->findSignalByIdx(idx); - if (!oldSig) return; - - QString newName = oldSig->name + QString::number(num); - DBC_SIGNAL newSig; - newSig.name = newName; - newSig.bias = oldSig->bias; - newSig.factor = oldSig->factor; - newSig.intelByteOrder = oldSig->intelByteOrder; - newSig.max = oldSig->max; - newSig.min = oldSig->min; - newSig.receiver = oldSig->receiver; - newSig.signalSize = oldSig->signalSize; - newSig.startBit = oldSig->startBit; - newSig.valType = oldSig->valType; - newSig.valList.append(oldSig->valList); - newSig.isMultiplexed = oldSig->isMultiplexed; - newSig.isMultiplexor = oldSig->isMultiplexor; //maybe should force this false since you can't have two or more! - newSig.multiplexValue = oldSig->multiplexValue; - newSig.parentMessage = dbcMessage; - - dbcMessage->sigHandler->addSignal(newSig); - - /* add item at the end of the list */ - ui->signalsList->addItem(newName); - - //unlike adding a signal we don't want to select the new signal here. - //ui->signalsList->setCurrentRow(ui->signalsList->count()-1); -} - -void DBCSignalEditor::deleteCurrentSignal() -{ - int currIdx = ui->signalsList->currentRow(); - - //if(currIdx==ui->signalsList->count()-1) - //return; - - if (currIdx > -1) - { - delete(ui->signalsList->item(currIdx)); - dbcMessage->sigHandler->removeSignal(currIdx); - currentSignal = nullptr; - } -} - void DBCSignalEditor::deleteCurrentValue() { int currIdx = ui->valuesTable->currentRow(); @@ -432,25 +337,6 @@ void DBCSignalEditor::deleteCurrentValue() } } -void DBCSignalEditor::refreshSignalsList() -{ - ui->signalsList->clear(); - - - for (int x = 0; x < dbcMessage->sigHandler->getCount(); x++) - { - DBC_SIGNAL *sig = dbcMessage->sigHandler->findSignalByIdx(x); - ui->signalsList->addItem(sig->name); - } - - if( ui->signalsList->count()>0 ) { - /* click first element */ - ui->signalsList->setCurrentRow(0); - } - else - clickSignalList(-1); -} - /* fillSignalForm also handles group "enabled" state */ /* WARNING: fillSignalForm can be called recursively since it is in the listener of cbIntelFormat */ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig) @@ -598,16 +484,6 @@ void DBCSignalEditor::fillValueTable(DBC_SIGNAL *sig) inhibitCellChanged = false; } -void DBCSignalEditor::clickSignalList(int row) -{ - //qDebug() << ui->signalsList->item(row)->text(); - - DBC_SIGNAL *thisSig = (row<0) ? nullptr : dbcMessage->sigHandler->findSignalByName(ui->signalsList->item(row)->text()); - currentSignal = thisSig; - fillSignalForm(thisSig); - fillValueTable(thisSig); -} - void DBCSignalEditor::bitfieldClicked(int x, int y) { int bit = (7 - x) + (y * 8); diff --git a/dbc/dbcsignaleditor.h b/dbc/dbcsignaleditor.h index e807f58..2b6e94f 100644 --- a/dbc/dbcsignaleditor.h +++ b/dbc/dbcsignaleditor.h @@ -16,19 +16,15 @@ class DBCSignalEditor : public QDialog public: explicit DBCSignalEditor(QWidget *parent = 0); void setMessageRef(DBC_MESSAGE *msg); - void showEvent(QShowEvent*); void setFileIdx(int idx); + void setSignalRef(DBC_SIGNAL *sig); + void showEvent(QShowEvent*); ~DBCSignalEditor(); private slots: - void clickSignalList(int); void bitfieldClicked(int x, int y); void onValuesCellChanged(int row,int col); - void onCustomMenuSignals(QPoint); void onCustomMenuValues(QPoint); - void addNewSignal(); - void cloneSignal(); - void deleteCurrentSignal(); void deleteCurrentValue(); private: @@ -39,7 +35,6 @@ private: DBCFile *dbcFile; bool inhibitCellChanged; - void refreshSignalsList(); void fillSignalForm(DBC_SIGNAL *sig); void fillValueTable(DBC_SIGNAL *sig); void generateUsedBits(); diff --git a/icons.qrc b/icons.qrc index cd68926..49ac17c 100644 --- a/icons.qrc +++ b/icons.qrc @@ -6,5 +6,14 @@ images/PlayHS.png images/ReverseHS.png images/StopHS.png + images/signal.png + images/node.png + images/message.png + images/multiplexed-signal.png + images/multiplexor-signal.png + images/skull.png + images/signal_new.png + images/node_new.png + images/message_new.png diff --git a/images/message.png b/images/message.png new file mode 100644 index 0000000..985a134 Binary files /dev/null and b/images/message.png differ diff --git a/images/message_new.png b/images/message_new.png new file mode 100644 index 0000000..15c8dc4 Binary files /dev/null and b/images/message_new.png differ diff --git a/images/multiplexed-signal.png b/images/multiplexed-signal.png new file mode 100644 index 0000000..55f66f9 Binary files /dev/null and b/images/multiplexed-signal.png differ diff --git a/images/multiplexor-signal.png b/images/multiplexor-signal.png new file mode 100644 index 0000000..afd11cd Binary files /dev/null and b/images/multiplexor-signal.png differ diff --git a/images/node.png b/images/node.png new file mode 100644 index 0000000..f2a52f5 Binary files /dev/null and b/images/node.png differ diff --git a/images/node_new.png b/images/node_new.png new file mode 100644 index 0000000..75ae0aa Binary files /dev/null and b/images/node_new.png differ diff --git a/images/signal.png b/images/signal.png new file mode 100644 index 0000000..dbfc714 Binary files /dev/null and b/images/signal.png differ diff --git a/images/signal_new.png b/images/signal_new.png new file mode 100644 index 0000000..3581a85 Binary files /dev/null and b/images/signal_new.png differ diff --git a/images/skull.png b/images/skull.png new file mode 100644 index 0000000..01453fc Binary files /dev/null and b/images/skull.png differ diff --git a/images/sourceImages/noun_Death_3194193.png b/images/sourceImages/noun_Death_3194193.png new file mode 100644 index 0000000..5d1825f Binary files /dev/null and b/images/sourceImages/noun_Death_3194193.png differ diff --git a/images/sourceImages/noun_Death_3194193.xcf b/images/sourceImages/noun_Death_3194193.xcf new file mode 100644 index 0000000..18605ba Binary files /dev/null and b/images/sourceImages/noun_Death_3194193.xcf differ diff --git a/images/sourceImages/noun_message_1977390.png b/images/sourceImages/noun_message_1977390.png new file mode 100644 index 0000000..5fd6b42 Binary files /dev/null and b/images/sourceImages/noun_message_1977390.png differ diff --git a/images/sourceImages/noun_message_1977390.xcf b/images/sourceImages/noun_message_1977390.xcf new file mode 100644 index 0000000..9dcab24 Binary files /dev/null and b/images/sourceImages/noun_message_1977390.xcf differ diff --git a/images/sourceImages/noun_nodes_2397529.png b/images/sourceImages/noun_nodes_2397529.png new file mode 100644 index 0000000..c14e1e0 Binary files /dev/null and b/images/sourceImages/noun_nodes_2397529.png differ diff --git a/images/sourceImages/noun_nodes_2397529.xcf b/images/sourceImages/noun_nodes_2397529.xcf new file mode 100644 index 0000000..8cfe1ab Binary files /dev/null and b/images/sourceImages/noun_nodes_2397529.xcf differ diff --git a/images/sourceImages/noun_signal_1402315.png b/images/sourceImages/noun_signal_1402315.png new file mode 100644 index 0000000..4ea4e8d Binary files /dev/null and b/images/sourceImages/noun_signal_1402315.png differ diff --git a/images/sourceImages/noun_signal_1402315.xcf b/images/sourceImages/noun_signal_1402315.xcf new file mode 100644 index 0000000..9007239 Binary files /dev/null and b/images/sourceImages/noun_signal_1402315.xcf differ diff --git a/images/sourceImages/noun_signal_1716563.png b/images/sourceImages/noun_signal_1716563.png new file mode 100644 index 0000000..cb29efa Binary files /dev/null and b/images/sourceImages/noun_signal_1716563.png differ diff --git a/images/sourceImages/noun_signal_1716563.xcf b/images/sourceImages/noun_signal_1716563.xcf new file mode 100644 index 0000000..2ccfc2f Binary files /dev/null and b/images/sourceImages/noun_signal_1716563.xcf differ diff --git a/images/sourceImages/noun_signal_1771815.png b/images/sourceImages/noun_signal_1771815.png new file mode 100644 index 0000000..c007970 Binary files /dev/null and b/images/sourceImages/noun_signal_1771815.png differ diff --git a/images/sourceImages/noun_signal_1771815.xcf b/images/sourceImages/noun_signal_1771815.xcf new file mode 100644 index 0000000..828dff5 Binary files /dev/null and b/images/sourceImages/noun_signal_1771815.xcf differ diff --git a/ui/dbcmaineditor.ui b/ui/dbcmaineditor.ui index 126452b..4fa6719 100644 --- a/ui/dbcmaineditor.ui +++ b/ui/dbcmaineditor.ui @@ -13,33 +13,95 @@ DBC Editing Window - + - + - + - Nodes + New Node + + + + :/icons/images/node_new.png:/icons/images/node_new.png + + + Qt::ToolButtonTextUnderIcon - + + + New Message + + + + :/icons/images/message_new.png:/icons/images/message_new.png + + + Qt::ToolButtonTextUnderIcon + + + + + + + New Signal + + + + :/icons/images/signal_new.png:/icons/images/signal_new.png + + + Qt::ToolButtonTextUnderIcon + + + + + + + Delete + + + + :/icons/images/skull.png:/icons/images/skull.png + + + Qt::ToolButtonTextUnderIcon + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 1 + + + - - - - Messages - - - - - - @@ -82,6 +144,8 @@ - + + + diff --git a/ui/dbcsignaleditor.ui b/ui/dbcsignaleditor.ui index d2ea6aa..4a1d45c 100644 --- a/ui/dbcsignaleditor.ui +++ b/ui/dbcsignaleditor.ui @@ -6,7 +6,7 @@ 0 0 - 1239 + 967 644 @@ -15,10 +15,7 @@ - - - - + @@ -210,7 +207,7 @@ - Value Table For Selected Signal: + Value Table: @@ -228,7 +225,6 @@ - signalsList txtName rbNotMulti rbMultiplexed