diff --git a/SavvyCAN.pro b/SavvyCAN.pro index 34c629a..be58289 100644 --- a/SavvyCAN.pro +++ b/SavvyCAN.pro @@ -22,6 +22,7 @@ ICON = icons/SavvyIcon.icns SOURCES += main.cpp\ connections/lawicel_serial.cpp \ connections/mqtt_bus.cpp \ + dbc/dbcnodeduplicateeditor.cpp \ mqtt/qmqtt_client.cpp \ mqtt/qmqtt_client_p.cpp \ mqtt/qmqtt_frame.cpp \ @@ -68,6 +69,7 @@ SOURCES += main.cpp\ dbc/dbcmaineditor.cpp \ dbc/dbcnodeeditor.cpp \ dbc/dbcsignaleditor.cpp \ + dbc/dbcnoderebaseeditor.cpp \ re/discretestatewindow.cpp \ re/filecomparatorwindow.cpp \ re/flowviewwindow.cpp \ @@ -102,6 +104,8 @@ HEADERS += mainwindow.h \ connections/lawicel_serial.h \ connections/socketcand.h \ connections/mqtt_bus.h \ + dbc/dbcnodeduplicateeditor.h \ + dbc/dbcnoderebaseeditor.h \ mqtt/qmqtt.h \ mqtt/qmqtt_client.h \ mqtt/qmqtt_client_p.h \ @@ -185,11 +189,14 @@ HEADERS += mainwindow.h \ pcaplite.h FORMS += ui/candatagrid.ui \ + ui/dbcnodeduplicateeditor.ui \ ui/dbccomparatorwindow.ui \ ui/dbcmessageeditor.ui \ ui/connectionwindow.ui \ ui/dbcloadsavewindow.ui \ ui/dbcmaineditor.ui \ + ui/dbcnodeduplicateeditor.ui \ + ui/dbcnoderebaseeditor.ui \ ui/dbcsignaleditor.ui \ ui/dbcnodeeditor.ui \ ui/discretestatewindow.ui \ diff --git a/connections/socketcand.cpp b/connections/socketcand.cpp index df1157d..a049d8c 100644 --- a/connections/socketcand.cpp +++ b/connections/socketcand.cpp @@ -291,6 +291,10 @@ QString SocketCANd::decodeFrames(QString data, int busNum) if(frameParsed.length() < 4) { qDebug() << "Received frame doesn't contain any data: " << data; + + //todo + //this is not totally true, ive seen frames come through that look like < frame 1F020240 1664924225.371291 > + //if we found the closing token but theres no data then remove the message from the buffer return data; } diff --git a/dbc/dbchandler.cpp b/dbc/dbchandler.cpp index 8290c10..27df434 100644 --- a/dbc/dbchandler.cpp +++ b/dbc/dbchandler.cpp @@ -177,6 +177,24 @@ DBC_MESSAGE* DBCMessageHandler::findMsgByPartialName(QString name) return nullptr; } +QList DBCMessageHandler::findMsgsByNode(DBC_NODE* node) +{ + QList messagesForNode; + + if (messages.count() == 0) + return messagesForNode; + + for (int i = 0; i < messages.count(); i++) + { + if (messages[i].sender == node) + { + messagesForNode.append(&messages[i]); + } + } + + return messagesForNode; +} + bool DBCMessageHandler::addMessage(DBC_MESSAGE &msg) { messages.append(msg); @@ -453,7 +471,7 @@ DBC_MESSAGE* DBCFile::parseMessageLine(QString line) DBC_MESSAGE msg; uint32_t ID = match.captured(1).toULong(); //the ID is always stored in decimal format msg.ID = ID & 0x1FFFFFFFul; - msg.extendedID = (ID & 80000000ul) ? true : false; + msg.extendedID = (ID & 0x80000000ul) ? true : false; msg.name = match.captured(2); msg.len = match.captured(3).toUInt(); msg.sender = findNodeByName(match.captured(4)); @@ -1369,7 +1387,10 @@ bool DBCFile::saveFile(QString fileName) } uint32_t ID = msg->ID; - if (msg->ID > 0x7FF || msg->extendedID) msg->ID += 0x80000000ul; //set bit 31 if this ID is extended. + if (msg->ID > 0x7FF || msg->extendedID) + { + msg->ID += 0x80000000ul; //set bit 31 if this ID is extended. + } msgOutput.append("BO_ " + QString::number(ID) + " " + msg->name + ": " + QString::number(msg->len) + " " + msg->sender->name + "\n"); @@ -1565,7 +1586,10 @@ bool DBCFile::saveFile(QString fileName) DBC_MESSAGE *msg = messageHandler->findMsgByIdx(x); uint32_t ID = msg->ID; - if (msg->ID > 0x7FF || msg->extendedID) msg->ID += 0x80000000ul; //set bit 31 if this ID is extended. + if (msg->ID > 0x7FF || msg->extendedID) + { + msg->ID += 0x80000000ul; //set bit 31 if this ID is extended. + } for (int s = 0; s < msg->sigHandler->getCount(); s++) { diff --git a/dbc/dbchandler.h b/dbc/dbchandler.h index 9e040cb..925bc8c 100644 --- a/dbc/dbchandler.h +++ b/dbc/dbchandler.h @@ -43,6 +43,7 @@ public: DBC_MESSAGE *findMsgByIdx(int idx); DBC_MESSAGE *findMsgByName(QString name); DBC_MESSAGE *findMsgByPartialName(QString name); + QList findMsgsByNode(DBC_NODE *node); bool addMessage(DBC_MESSAGE &msg); bool removeMessage(DBC_MESSAGE *msg); bool removeMessageByIndex(int idx); diff --git a/dbc/dbcmaineditor.cpp b/dbc/dbcmaineditor.cpp index 54a046b..53982e3 100644 --- a/dbc/dbcmaineditor.cpp +++ b/dbc/dbcmaineditor.cpp @@ -21,25 +21,35 @@ DBCMainEditor::DBCMainEditor( const QVector *frames, QWidget *parent) dbcHandler = DBCHandler::getReference(); referenceFrames = frames; + ui->treeDBC->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->btnSearch, &QAbstractButton::clicked, this, &DBCMainEditor::handleSearch); connect(ui->lineSearch, &QLineEdit::returnPressed, this, &DBCMainEditor::handleSearch); connect(ui->btnSearchNext, &QAbstractButton::clicked, this, &DBCMainEditor::handleSearchForward); connect(ui->btnSearchPrev, &QAbstractButton::clicked, this, &DBCMainEditor::handleSearchBackward); connect(ui->treeDBC, &QTreeWidget::doubleClicked, this, &DBCMainEditor::onTreeDoubleClicked); + connect(ui->treeDBC, &QTreeWidget::customContextMenuRequested, this, &DBCMainEditor::onTreeContextMenu); connect(ui->treeDBC, &QTreeWidget::currentItemChanged, this, &DBCMainEditor::currentItemChanged); connect(ui->btnDelete, &QAbstractButton::clicked, this, &DBCMainEditor::deleteCurrentTreeItem); - connect(ui->btnNewNode, &QAbstractButton::clicked, this, &DBCMainEditor::newNode); + connect(ui->btnNewNode, &QAbstractButton::clicked, this, QOverload<>::of(&DBCMainEditor::newNode)); connect(ui->btnNewMessage, &QAbstractButton::clicked, this, &DBCMainEditor::newMessage); connect(ui->btnNewSignal, &QAbstractButton::clicked, this, &DBCMainEditor::newSignal); sigEditor = new DBCSignalEditor(this); msgEditor = new DBCMessageEditor(this); nodeEditor = new DBCNodeEditor(this); + nodeRebaseEditor = new DBCNodeRebaseEditor(this); + nodeDuplicateEditor = new DBCNodeDuplicateEditor(this); //all three might potentially change the data stored and force the tree to be updated connect(sigEditor, &DBCSignalEditor::updatedTreeInfo, this, &DBCMainEditor::updatedSignal); connect(msgEditor, &DBCMessageEditor::updatedTreeInfo, this, &DBCMainEditor::updatedMessage); connect(nodeEditor, &DBCNodeEditor::updatedTreeInfo, this, &DBCMainEditor::updatedNode); + connect(nodeRebaseEditor, &DBCNodeRebaseEditor::updatedTreeInfo, this, &DBCMainEditor::updatedMessage); + connect(nodeDuplicateEditor, &DBCNodeDuplicateEditor::updatedTreeInfo, this, &DBCMainEditor::updatedMessage); + connect(nodeDuplicateEditor, &DBCNodeDuplicateEditor::createNode, this, QOverload::of(&DBCMainEditor::newNode)); + connect(nodeDuplicateEditor, &DBCNodeDuplicateEditor::cloneMessageToNode, this, &DBCMainEditor::copyMessageToNode); + connect(nodeDuplicateEditor, &DBCNodeDuplicateEditor::nodeAdded, this, &DBCMainEditor::refreshTree); nodeIcon = QIcon(":/icons/images/node.png"); messageIcon = QIcon(":/icons/images/message.png"); @@ -298,6 +308,83 @@ void DBCMainEditor::onTreeDoubleClicked(const QModelIndex &index) } } +void DBCMainEditor::onTreeContextMenu(const QPoint & pos) +{ + QTreeWidgetItem* firstCol = ui->treeDBC->currentItem(); + bool ret = false; + DBC_MESSAGE *msg; + DBC_SIGNAL *sig; + DBC_NODE *node; + uint32_t msgID; + QString idString; + + qDebug() << firstCol->data(0, Qt::UserRole) << " - " << firstCol->text(0); + + switch (firstCol->data(0, Qt::UserRole).toInt()) + { + case 1: //a node + idString = firstCol->text(0).split(" ")[0]; + node = dbcFile->findNodeByName(idString); + + QAction *actionRebase = new QAction(QIcon(":/Resource/warning32.ico"), tr("Rebase all messages"), this); + actionRebase->setStatusTip(tr("Rebase all messages in node")); + connect(actionRebase, SIGNAL(triggered()), this, SLOT(onRebaseMessages())); + + QAction *actionDupe = new QAction(QIcon(":/Resource/warning32.ico"), tr("Duplicate node"), this); + actionDupe->setStatusTip(tr("Duplicate node and messages")); + connect(actionDupe, SIGNAL(triggered()), this, SLOT(onDuplicateNode())); + + QMenu menu(this); + menu.addAction(actionRebase); + menu.addAction(actionDupe); + + QPoint pt(pos); + menu.exec( ui->treeDBC->mapToGlobal(pos) ); + break; + } +} + +void DBCMainEditor::onRebaseMessages() +{ + QTreeWidgetItem* firstCol = ui->treeDBC->currentItem(); + bool ret = false; + DBC_MESSAGE *msg; + DBC_SIGNAL *sig; + DBC_NODE *node; + uint32_t msgID; + QString idString; + + idString = firstCol->text(0).split(" ")[0]; + node = dbcFile->findNodeByName(idString); + nodeRebaseEditor->setFileIdx(fileIdx); + nodeRebaseEditor->setNodeRef(node); + if(nodeRebaseEditor->refreshView()) + { + nodeRebaseEditor->setModal(true); + nodeRebaseEditor->show(); + } +} + +void DBCMainEditor::onDuplicateNode() +{ + QTreeWidgetItem* firstCol = ui->treeDBC->currentItem(); + bool ret = false; + DBC_MESSAGE *msg; + DBC_SIGNAL *sig; + DBC_NODE *node; + uint32_t msgID; + QString idString; + + idString = firstCol->text(0).split(" ")[0]; + node = dbcFile->findNodeByName(idString); + nodeDuplicateEditor->setFileIdx(fileIdx); + nodeDuplicateEditor->setNodeRef(node); + if(nodeDuplicateEditor->refreshView()) + { + nodeDuplicateEditor->setModal(true); + nodeDuplicateEditor->show(); + } +} /* * 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 @@ -481,11 +568,18 @@ void DBCMainEditor::updatedSignal(DBC_SIGNAL *sig) else qDebug() << "That signal doesn't exist. That's a bug dude."; } -void DBCMainEditor::newNode() +void DBCMainEditor::newNode(QString nodeName) { DBC_NODE node; DBC_NODE *nodePtr; - node.name = "Unnamed" + QString::number(randGen.bounded(50000)); + if(nodeName.isEmpty()) + { + node.name = "Unnamed" + QString::number(randGen.bounded(50000)); + } + else + { + node.name = nodeName; + } dbcFile->dbc_nodes.append(node); nodePtr = dbcFile->findNodeByName(node.name); QTreeWidgetItem *nodeItem = new QTreeWidgetItem(); @@ -499,6 +593,77 @@ void DBCMainEditor::newNode() dbcFile->setDirtyFlag(); } +void DBCMainEditor::newNode() +{ + newNode(QString()); +} + +void DBCMainEditor::copyMessageToNode(DBC_NODE *parentNode, DBC_MESSAGE *source, uint newMsgId) +{ + DBC_NODE *node = parentNode; + if (!node) node = dbcFile->findNodeByIdx(0); + QTreeWidgetItem *nodeItem = nullptr; + DBC_MESSAGE msg; + DBC_MESSAGE *msgPtr; + + nodeItem = ui->treeDBC->currentItem(); + + msg.name = source->name; + msg.ID = newMsgId; + msg.len = source->len; + msg.bgColor = source->bgColor; + msg.fgColor = source->fgColor; + msg.comment = source->comment; + msg.sender = node; + + DBC_SIGNAL *sigSource; + int sigCount = source->sigHandler->getCount(); + + for(int i=0; isigHandler->findSignalByIdx(i); + + DBC_SIGNAL sig; + + //Does not properly handle multiplexed signals, for now + sig.name = sigSource->name; + sig.bias = sigSource->bias; + sig.isMultiplexed = false; //sigSource->isMultiplexed; + sig.isMultiplexor = false; //sigSource->isMultiplexor; + sig.max = sigSource->max; + sig.min = sigSource->min; + sig.multiplexLowValue = sigSource->multiplexLowValue; + sig.multiplexHighValue = sigSource->multiplexHighValue; + sig.factor = sigSource->factor; + sig.intelByteOrder = sigSource->intelByteOrder; + sig.parentMessage = &msg; + sig.multiplexParent = nullptr; //need to learn about multiplexed signals and track them when copying + sig.receiver = node; + sig.signalSize = sigSource->signalSize; + sig.startBit = sigSource->startBit; + sig.valType = sigSource->valType; + + + sig.parentMessage = &msg; + msg.sigHandler->addSignal(sig); + } + + msg.sigHandler->sort(); + + dbcFile->messageHandler->addMessage(msg); + msgPtr = dbcFile->messageHandler->findMsgByIdx(dbcFile->messageHandler->getCount() - 1); + QTreeWidgetItem *newMsgItem = new QTreeWidgetItem(); + QString msgInfo = Utility::formatCANID(msg.ID) + " " + msg.name; + if (msg.comment.count() > 0) msgInfo.append(" - ").append(msg.comment); + newMsgItem->setText(0, msgInfo); + newMsgItem->setIcon(0, messageIcon); + newMsgItem->setData(0, Qt::UserRole, 2); + messageToItem.insert(msgPtr, newMsgItem); + itemToMessage.insert(newMsgItem, msgPtr); + nodeItem->addChild(newMsgItem); + //ui->treeDBC->setCurrentItem(newMsgItem); + dbcFile->setDirtyFlag(); +} //create a new message with it's parent being the node we're currently within void DBCMainEditor::newMessage() diff --git a/dbc/dbcmaineditor.h b/dbc/dbcmaineditor.h index bfc3acd..5977f82 100644 --- a/dbc/dbcmaineditor.h +++ b/dbc/dbcmaineditor.h @@ -10,6 +10,8 @@ #include "dbcsignaleditor.h" #include "dbcmessageeditor.h" #include "dbcnodeeditor.h" +#include "dbcnoderebaseeditor.h" +#include "dbcnodeduplicateeditor.h" #include "utility.h" namespace Ui { @@ -32,6 +34,7 @@ public slots: private slots: void onTreeDoubleClicked(const QModelIndex &index); + void onTreeContextMenu(const QPoint & pos); void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *prev); void onCustomMenuTree(QPoint); void deleteCurrentTreeItem(); @@ -41,9 +44,13 @@ private slots: void handleSearch(); void handleSearchForward(); void handleSearchBackward(); + void newNode(QString nodeName); void newNode(); + void copyMessageToNode(DBC_NODE *node, DBC_MESSAGE *source, uint newMsgId); void newMessage(); - void newSignal(); + void newSignal(); + void onRebaseMessages(); + void onDuplicateNode(); private: Ui::DBCMainEditor *ui; @@ -52,6 +59,8 @@ private: DBCSignalEditor *sigEditor; DBCMessageEditor *msgEditor; DBCNodeEditor *nodeEditor; + DBCNodeRebaseEditor *nodeRebaseEditor; + DBCNodeDuplicateEditor *nodeDuplicateEditor; DBCFile *dbcFile; int fileIdx; QIcon nodeIcon; diff --git a/dbc/dbcnodeduplicateeditor.cpp b/dbc/dbcnodeduplicateeditor.cpp new file mode 100644 index 0000000..0c5b546 --- /dev/null +++ b/dbc/dbcnodeduplicateeditor.cpp @@ -0,0 +1,204 @@ +#include "dbcnodeduplicateeditor.h" +#include "ui_dbcnodeduplicateeditor.h" + +#include +#include +#include +#include +#include "helpwindow.h" +#include "utility.h" + +DBCNodeDuplicateEditor::DBCNodeDuplicateEditor(QWidget *parent) : + QDialog(parent), + ui(new Ui::DBCNodeDuplicateEditor) +{ + ui->setupUi(this); + + readSettings(); + + dbcHandler = DBCHandler::getReference(); + dbcNode = nullptr; + + connect(ui->btnDuplicate, &QPushButton::pressed, + [=]() + { + if (dbcNode == nullptr) return; + if (lowestMsgId > 0x1FFFFFFFul) return; + + uint newBase = Utility::ParseStringToNum(ui->lineNewBaseId->text()); + + if(newBase <= 0 || newBase > 0x1FFFFFFFul) + { + QMessageBox::question(this, "Invalid Address", "The new address is outside of the valid range.", + QMessageBox::Ok); + return; + } + + if(newBase == lowestMsgId) + { + QMessageBox::question(this, "Invalid Address", "The new address is the same as the original.", + QMessageBox::Ok); + return; + } + + uint rebaseDiff = newBase - lowestMsgId; + + QList messagesForNode = dbcFile->messageHandler->findMsgsByNode(dbcNode); + if(messagesForNode.count() == 0) + { + QMessageBox::question(this, "No Messages", "The node has no messages to duplicate.", + QMessageBox::Ok); + return; + } + + if(ui->lineNodeName->text().isEmpty()) + { + QMessageBox::question(this, "No Name", "The new node needs a name before it can be created.", + QMessageBox::Ok); + return; + } + + QString newNodeName = ui->lineNodeName->text(); + emit createNode(newNodeName); + + DBC_NODE *nodePtr = dbcFile->findNodeByName(newNodeName); + + if(nodePtr == nullptr) + { + QMessageBox::question(this, "Node Invalid", "There was an problem identifying the selected node.", + QMessageBox::Ok); + return; + } + + for (int i=0; iID + rebaseDiff; + + if(newMsgId < 0 || newMsgId > 0x1FFFFFFFul) + { + QMessageBox::question(this, "Invalid Address Range", "The new starting address would cause a message to be outside of the valid address range.", + QMessageBox::Ok); + return; + } + } + + for (int i=0; iID + rebaseDiff; + emit cloneMessageToNode(nodePtr, messagesForNode[i], newMsgId); + } + + dbcFile->setDirtyFlag(); + emit nodeAdded(); + + this->close(); + + }); + + connect(ui->btnCancel, &QPushButton::pressed, + [=]() + { + this->close(); + }); + + installEventFilter(this); +} + +DBCNodeDuplicateEditor::~DBCNodeDuplicateEditor() +{ + removeEventFilter(this); + delete ui; +} + +void DBCNodeDuplicateEditor::closeEvent(QCloseEvent *event) +{ + Q_UNUSED(event); + writeSettings(); +} + +bool DBCNodeDuplicateEditor::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("nodeeditor.md"); + break; + } + return true; + } else { + // standard event processing + return QObject::eventFilter(obj, event); + } + return false; +} + +void DBCNodeDuplicateEditor::setFileIdx(int idx) +{ + if (idx < 0 || idx > dbcHandler->getFileCount() - 1) return; + dbcFile = dbcHandler->getFileByIdx(idx); +} + +void DBCNodeDuplicateEditor::readSettings() +{ + QSettings settings; + if (settings.value("Main/SaveRestorePositions", false).toBool()) + { + resize(settings.value("DBCNodeDuplicateEditor/WindowSize", QSize(312, 128)).toSize()); + move(Utility::constrainedWindowPos(settings.value("DBCNodeDuplicateEditor/WindowPos", QPoint(100, 100)).toPoint())); + } +} + +void DBCNodeDuplicateEditor::writeSettings() +{ + QSettings settings; + + if (settings.value("Main/SaveRestorePositions", false).toBool()) + { + settings.setValue("DBCNodeDuplicateEditor/WindowSize", size()); + settings.setValue("DBCNodeDuplicateEditor/WindowPos", pos()); + } +} + + +void DBCNodeDuplicateEditor::setNodeRef(DBC_NODE *node) +{ + dbcNode = node; +} + +void DBCNodeDuplicateEditor::showEvent(QShowEvent* event) +{ + QDialog::showEvent(event); + + refreshView(); +} + +bool DBCNodeDuplicateEditor::refreshView() +{ + ui->lineNewBaseId->setText(""); + + if(dbcNode) + { + QList messagesForNode = dbcFile->messageHandler->findMsgsByNode(dbcNode); + lowestMsgId = 0xFFFFFFFF; + + if(messagesForNode.count() == 0) + { + return false; + } + + for (int i=0; iID < lowestMsgId) + lowestMsgId = messagesForNode[i]->ID; + } + + ui->lineOriginalBaseId->setText(Utility::formatCANID(lowestMsgId & 0x1FFFFFFFul)); + ui->lineNodeName->setText(dbcNode->name + QString("_Copy")); + + return true; + } + + return false; +} diff --git a/dbc/dbcnodeduplicateeditor.h b/dbc/dbcnodeduplicateeditor.h new file mode 100644 index 0000000..57610bd --- /dev/null +++ b/dbc/dbcnodeduplicateeditor.h @@ -0,0 +1,45 @@ +#ifndef DBCNODEDUPLICATEEDITOR_H +#define DBCNODEDUPLICATEEDITOR_H + +#include +#include "dbc_classes.h" +#include "dbchandler.h" + +namespace Ui { +class DBCNodeDuplicateEditor; +} + +class DBCNodeDuplicateEditor : public QDialog +{ + Q_OBJECT + +public: + explicit DBCNodeDuplicateEditor(QWidget *parent = nullptr); + ~DBCNodeDuplicateEditor(); + void showEvent(QShowEvent*); + void setNodeRef(DBC_NODE *node); + void setFileIdx(int idx); + bool refreshView(); + +signals: + void updatedTreeInfo(DBC_MESSAGE *msg); + void createNode(QString nodeName); + void cloneMessageToNode(DBC_NODE *parentNode, DBC_MESSAGE *source, uint newMsgId); + void nodeAdded(); + +private: + Ui::DBCNodeDuplicateEditor *ui; + + DBCHandler *dbcHandler; + DBC_NODE *dbcNode; + DBCFile *dbcFile; + + void closeEvent(QCloseEvent *event); + bool eventFilter(QObject *obj, QEvent *event); + void readSettings(); + void writeSettings(); + + uint lowestMsgId; +}; + +#endif // DBCNODEDUPLICATEEDITOR_H diff --git a/dbc/dbcnoderebaseeditor.cpp b/dbc/dbcnoderebaseeditor.cpp new file mode 100644 index 0000000..8ce105d --- /dev/null +++ b/dbc/dbcnoderebaseeditor.cpp @@ -0,0 +1,195 @@ +#include "dbcnoderebaseeditor.h" +#include "ui_dbcnoderebaseeditor.h" + +#include +#include +#include +#include +#include "helpwindow.h" +#include "utility.h" + +DBCNodeRebaseEditor::DBCNodeRebaseEditor(QWidget *parent) : + QDialog(parent), + ui(new Ui::DBCNodeRebaseEditor) +{ + ui->setupUi(this); + + readSettings(); + + dbcHandler = DBCHandler::getReference(); + dbcNode = nullptr; + + connect(ui->btnDoRebase, &QPushButton::pressed, + [=]() + { + if (dbcNode == nullptr) + { + QMessageBox::question(this, "Node Invalid", "There was an problem identifying the selected node.", + QMessageBox::Ok); + return; + } + + if (lowestMsgId > 0x1FFFFFFFul) + { + QMessageBox::question(this, "No Valid Messages", "The node has no valid messages to change.", + QMessageBox::Ok); + return; + } + + uint newBase = Utility::ParseStringToNum(ui->lineNewBaseId->text()); + + if(newBase <= 0 || newBase > 0x1FFFFFFFul) + { + QMessageBox::question(this, "Invalid Address", "The new address is outside of the valid range.", + QMessageBox::Ok); + return; + } + + if(newBase == lowestMsgId) + { + QMessageBox::question(this, "Invalid Address", "The new address is the same as the original.", + QMessageBox::Ok); + return; + } + + uint rebaseDiff = newBase - lowestMsgId; + + QList messagesForNode = dbcFile->messageHandler->findMsgsByNode(dbcNode); + if(messagesForNode.count() == 0) + { + QMessageBox::question(this, "No Messages", "The node has no messages to change.", + QMessageBox::Ok); + return; + } + + for (int i=0; iID + rebaseDiff; + + if(newMsgId < 0 || newMsgId > 0x1FFFFFFFul) + { + QMessageBox::question(this, "Invalid Address Range", "The new starting address would cause a message to be outside of the valid address range.", + QMessageBox::Ok); + return; + } + } + + for (int i=0; iID += rebaseDiff; + emit updatedTreeInfo(messagesForNode[i]); + } + + dbcFile->setDirtyFlag(); + + this->close(); + + }); + + connect(ui->btnCancel, &QPushButton::pressed, + [=]() + { + this->close(); + }); + + installEventFilter(this); +} + +DBCNodeRebaseEditor::~DBCNodeRebaseEditor() +{ + removeEventFilter(this); + delete ui; +} + +void DBCNodeRebaseEditor::closeEvent(QCloseEvent *event) +{ + Q_UNUSED(event); + writeSettings(); +} + +bool DBCNodeRebaseEditor::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("nodeeditor.md"); + break; + } + return true; + } else { + // standard event processing + return QObject::eventFilter(obj, event); + } + return false; +} + +void DBCNodeRebaseEditor::setFileIdx(int idx) +{ + if (idx < 0 || idx > dbcHandler->getFileCount() - 1) return; + dbcFile = dbcHandler->getFileByIdx(idx); +} + +void DBCNodeRebaseEditor::readSettings() +{ + QSettings settings; + if (settings.value("Main/SaveRestorePositions", false).toBool()) + { + resize(settings.value("DBCNodeRebaseEditor/WindowSize", QSize(312, 128)).toSize()); + move(Utility::constrainedWindowPos(settings.value("DBCNodeRebaseEditor/WindowPos", QPoint(100, 100)).toPoint())); + } +} + +void DBCNodeRebaseEditor::writeSettings() +{ + QSettings settings; + + if (settings.value("Main/SaveRestorePositions", false).toBool()) + { + settings.setValue("DBCNodeRebaseEditor/WindowSize", size()); + settings.setValue("DBCNodeRebaseEditor/WindowPos", pos()); + } +} + + +void DBCNodeRebaseEditor::setNodeRef(DBC_NODE *node) +{ + dbcNode = node; +} + +void DBCNodeRebaseEditor::showEvent(QShowEvent* event) +{ + QDialog::showEvent(event); + + refreshView(); +} + +bool DBCNodeRebaseEditor::refreshView() +{ + ui->lineNewBaseId->setText(""); + + if(dbcNode) + { + QList messagesForNode = dbcFile->messageHandler->findMsgsByNode(dbcNode); + lowestMsgId = 0xFFFFFFFF; + + if(messagesForNode.count() == 0) + { + return false; + } + + for (int i=0; iID < lowestMsgId) + lowestMsgId = messagesForNode[i]->ID; + } + + ui->lineOriginalBaseId->setText(Utility::formatCANID(lowestMsgId & 0x1FFFFFFFul)); + ui->lineNodeName->setText(dbcNode->name); + + return true; + } + + return false; +} diff --git a/dbc/dbcnoderebaseeditor.h b/dbc/dbcnoderebaseeditor.h new file mode 100644 index 0000000..26f1645 --- /dev/null +++ b/dbc/dbcnoderebaseeditor.h @@ -0,0 +1,42 @@ +#ifndef DBCNODEREBASEEDITOR_H +#define DBCNODEREBASEEDITOR_H + +#include +#include "dbc_classes.h" +#include "dbchandler.h" + +namespace Ui { +class DBCNodeRebaseEditor; +} + +class DBCNodeRebaseEditor : public QDialog +{ + Q_OBJECT + +public: + explicit DBCNodeRebaseEditor(QWidget *parent = nullptr); + ~DBCNodeRebaseEditor(); + void showEvent(QShowEvent*); + void setNodeRef(DBC_NODE *node); + void setFileIdx(int idx); + bool refreshView(); + +signals: + void updatedTreeInfo(DBC_MESSAGE *msg); + +private: + Ui::DBCNodeRebaseEditor *ui; + + DBCHandler *dbcHandler; + DBC_NODE *dbcNode; + DBCFile *dbcFile; + + void closeEvent(QCloseEvent *event); + bool eventFilter(QObject *obj, QEvent *event); + void readSettings(); + void writeSettings(); + + uint lowestMsgId; +}; + +#endif // DBCNODEREBASEEDITOR_H diff --git a/dbc/dbcsignaleditor.cpp b/dbc/dbcsignaleditor.cpp index b81c11c..3788781 100644 --- a/dbc/dbcsignaleditor.cpp +++ b/dbc/dbcsignaleditor.cpp @@ -84,7 +84,7 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) : break; case 4: currentSignal->valType = STRING; - break; + break; } dbcFile->setDirtyFlag(); fillSignalForm(currentSignal); diff --git a/signalviewerwindow.cpp b/signalviewerwindow.cpp index c061074..8ec7936 100644 --- a/signalviewerwindow.cpp +++ b/signalviewerwindow.cpp @@ -351,16 +351,18 @@ void SignalViewerWindow::loadDefinitions(bool append) QString msgName = QString(tokens[2]); QString sigName = QString(tokens[3]); DBC_MESSAGE *msg;; - if (msg = dbcHandler->findMessage(msgName)) + if(msg = dbcHandler->findMessage(msgId)) { sig = msg->sigHandler->findSignalByName(sigName); - loadedSignals.append(sig); + if(sig) + loadedSignals.append(sig); } - else if(msg = dbcHandler->findMessage(msgId)) + else if (msg = dbcHandler->findMessage(msgName)) { + //this is not a very safe way to match since messages names can be duplicated sig = msg->sigHandler->findSignalByName(sigName); - //fix anything up about the name? - loadedSignals.append(sig); + if(sig) + loadedSignals.append(sig); } else { diff --git a/ui/dbcnodeduplicateeditor.ui b/ui/dbcnodeduplicateeditor.ui new file mode 100644 index 0000000..b236251 --- /dev/null +++ b/ui/dbcnodeduplicateeditor.ui @@ -0,0 +1,88 @@ + + + DBCNodeDuplicateEditor + + + + 0 + 0 + 314 + 144 + + + + + 0 + 0 + + + + Duplicate Node + + + + + 10 + 10 + 290 + 116 + + + + + + + New Node Name: + + + + + + + + + + Current Base ID: + + + + + + + true + + + true + + + + + + + New Base ID: + + + + + + + + + + Duplicate Node + + + + + + + Cancel + + + + + + + + + diff --git a/ui/dbcnoderebaseeditor.ui b/ui/dbcnoderebaseeditor.ui new file mode 100644 index 0000000..3c043cc --- /dev/null +++ b/ui/dbcnoderebaseeditor.ui @@ -0,0 +1,95 @@ + + + DBCNodeRebaseEditor + + + + 0 + 0 + 303 + 148 + + + + + 0 + 0 + + + + Rebase All Node Messages + + + + + 10 + 20 + 283 + 116 + + + + + + + Node Name: + + + + + + + true + + + true + + + + + + + Current Base ID: + + + + + + + true + + + true + + + + + + + New Base ID: + + + + + + + + + + Rebase All Messages in Node + + + + + + + Cancel + + + + + + + + +