much more object oriented and encapsulated. The biggest addition is that it is now possible to support multiple DBC files being loaded at once with each file associated to one or both buses. Note that currently the program still does not support multiple DBC files but the groundwork is there.
460 lines
16 KiB
C++
460 lines
16 KiB
C++
#include "dbcmaineditor.h"
|
|
#include "ui_dbcmaineditor.h"
|
|
|
|
#include <QMenu>
|
|
#include <QMessageBox>
|
|
#include <QSettings>
|
|
|
|
DBCMainEditor::DBCMainEditor(DBCHandler *handler, const QVector<CANFrame> *frames, QWidget *parent) :
|
|
QDialog(parent),
|
|
ui(new Ui::DBCMainEditor)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
readSettings();
|
|
|
|
dbcHandler = handler;
|
|
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" << "Comment";
|
|
ui->MessagesTable->setColumnCount(5);
|
|
ui->MessagesTable->setColumnWidth(0, 80);
|
|
ui->MessagesTable->setColumnWidth(1, 240);
|
|
ui->MessagesTable->setColumnWidth(2, 80);
|
|
ui->MessagesTable->setColumnWidth(3, 80);
|
|
ui->MessagesTable->setColumnWidth(4, 340);
|
|
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);
|
|
|
|
sigEditor = new DBCSignalEditor(handler);
|
|
}
|
|
|
|
void DBCMainEditor::showEvent(QShowEvent* event)
|
|
{
|
|
QDialog::showEvent(event);
|
|
|
|
inhibitCellChanged = true;
|
|
refreshNodesTable();
|
|
if (dbcHandler->getFileByIdx(0)->dbc_nodes.count() > 0)
|
|
refreshMessagesTable(&dbcHandler->getFileByIdx(0)->dbc_nodes.at(0));
|
|
|
|
currRow = 0;
|
|
inhibitCellChanged = false;
|
|
}
|
|
|
|
DBCMainEditor::~DBCMainEditor()
|
|
{
|
|
delete ui;
|
|
delete sigEditor;
|
|
}
|
|
|
|
void DBCMainEditor::closeEvent(QCloseEvent *event)
|
|
{
|
|
Q_UNUSED(event);
|
|
writeSettings();
|
|
}
|
|
|
|
void DBCMainEditor::readSettings()
|
|
{
|
|
QSettings settings;
|
|
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
|
{
|
|
resize(settings.value("DBCMainEditor/WindowSize", QSize(1103, 571)).toSize());
|
|
move(settings.value("DBCMainEditor/WindowPos", QPoint(50, 50)).toPoint());
|
|
}
|
|
}
|
|
|
|
void DBCMainEditor::writeSettings()
|
|
{
|
|
QSettings settings;
|
|
|
|
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
|
{
|
|
settings.setValue("DBCMainEditor/WindowSize", size());
|
|
settings.setValue("DBCMainEditor/WindowPos", pos());
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
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));
|
|
|
|
}
|
|
|
|
void DBCMainEditor::deleteCurrentNode()
|
|
{
|
|
int thisRow = ui->NodesTable->currentRow();
|
|
QString nodeName = ui->NodesTable->item(thisRow, 0)->text();
|
|
if (nodeName.length() > 0 && nodeName.compare("Vector__XXX", Qt::CaseInsensitive) != 0)
|
|
{
|
|
ui->NodesTable->removeRow(thisRow);
|
|
dbcHandler->getFileByIdx(0)->dbc_nodes.removeAt(thisRow);
|
|
inhibitCellChanged = true;
|
|
refreshMessagesTable(&dbcHandler->getFileByIdx(0)->dbc_nodes[0]);
|
|
ui->NodesTable->selectRow(0);
|
|
inhibitCellChanged = false;
|
|
}
|
|
}
|
|
|
|
void DBCMainEditor::deleteCurrentMessage()
|
|
{
|
|
int thisRow = ui->MessagesTable->currentRow();
|
|
if (ui->MessagesTable->item(thisRow, 0)->text().length() > 0)
|
|
{
|
|
ui->MessagesTable->removeRow(thisRow);
|
|
dbcHandler->getFileByIdx(0)->messageHandler->removeMessageByIndex(thisRow);
|
|
}
|
|
}
|
|
|
|
void DBCMainEditor::onCellChangedNode(int row,int col)
|
|
{
|
|
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 (dbcHandler->getFileByIdx(0)->findNodeByName(newName) != NULL) //duplicates an existing node!
|
|
{
|
|
QMessageBox msg;
|
|
msg.setParent(0);
|
|
msg.setText("An existing node with that name already exists! Aborting!");
|
|
msg.exec();
|
|
return;
|
|
}
|
|
newNode.name = newName;
|
|
dbcHandler->getFileByIdx(0)->dbc_nodes.append(newNode);
|
|
qDebug() << "# of nodes now " << dbcHandler->getFileByIdx(0)->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 = dbcHandler->getFileByIdx(0)->findNodeByIdx(row);
|
|
QString nodeName = ui->NodesTable->item(row, col)->text().simplified().replace(' ', '_');
|
|
if (oldNode == NULL) 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 = dbcHandler->getFileByIdx(0)->findNodeByName(nodeName);
|
|
if (thisNode == NULL) return;
|
|
thisNode->comment = ui->NodesTable->item(row, col)->text().simplified();
|
|
qDebug() << "New comment: " << thisNode->comment;
|
|
}
|
|
}
|
|
ui->NodesTable->setCurrentCell(row, col);
|
|
}
|
|
|
|
void DBCMainEditor::onCellChangedMessage(int row,int col)
|
|
{
|
|
if (inhibitCellChanged) return;
|
|
|
|
qDebug() << "Editing row: " << row << " col: " << col;
|
|
|
|
QTableWidgetItem *replacement = NULL;
|
|
int msgID;
|
|
QString msgName;
|
|
int msgLen;
|
|
QString msgComment;
|
|
DBC_MESSAGE newMsg;
|
|
DBC_NODE *node = dbcHandler->getFileByIdx(0)->findNodeByIdx(ui->NodesTable->currentRow());
|
|
DBC_MESSAGE *msg;
|
|
if (node == NULL)
|
|
{
|
|
qDebug() << "No node set?!? This is bad!";
|
|
return;
|
|
//dbcHandler->findNodeByIdx(0);
|
|
}
|
|
|
|
msgID = Utility::ParseStringToNum(ui->MessagesTable->item(row, 0)->text());
|
|
qDebug() << "Msg ID of edited: " << msgID;
|
|
msg = dbcHandler->getFileByIdx(0)->messageHandler->findMsgByID(msgID);
|
|
|
|
switch(col)
|
|
{
|
|
case 0: //msg id
|
|
if (row == ui->MessagesTable->rowCount() - 1) //new record
|
|
{
|
|
if (dbcHandler->getFileByIdx(0)->messageHandler->findMsgByID(msgID) != NULL)
|
|
{
|
|
QMessageBox msg;
|
|
msg.setParent(0);
|
|
msg.setText("An existing msg with that ID already exists! Aborting!");
|
|
msg.exec();
|
|
return;
|
|
}
|
|
newMsg.ID = msgID;
|
|
newMsg.name = "";
|
|
newMsg.sender = node;
|
|
newMsg.len = 0;
|
|
for (int i = 0; i < referenceFrames->length(); i++)
|
|
{
|
|
if (referenceFrames->at(i).ID == msgID)
|
|
{
|
|
newMsg.len = referenceFrames->at(i).len;
|
|
break;
|
|
}
|
|
}
|
|
dbcHandler->getFileByIdx(0)->messageHandler->addMessage(newMsg);
|
|
}
|
|
else //editing an existing record
|
|
{
|
|
if (msg != NULL) msg->ID = msgID;
|
|
}
|
|
inhibitCellChanged = true;
|
|
replacement = new QTableWidgetItem(Utility::formatNumber(msgID));
|
|
ui->MessagesTable->setItem(row, col, replacement);
|
|
replacement = new QTableWidgetItem(QString::number(newMsg.len));
|
|
ui->MessagesTable->setItem(row, 2, replacement);
|
|
inhibitCellChanged = false;
|
|
break;
|
|
|
|
case 1: //msg name
|
|
msgName = ui->MessagesTable->item(row, col)->text().simplified().replace(' ', '_');
|
|
if (msgName.length() == 0) return;
|
|
if (row == ui->MessagesTable->rowCount() - 1) //new record
|
|
{
|
|
if (dbcHandler->getFileByIdx(0)->messageHandler->findMsgByName(msgName) != NULL)
|
|
{
|
|
QMessageBox msg;
|
|
msg.setParent(0);
|
|
msg.setText("An existing msg with that name already exists! Aborting!");
|
|
msg.exec();
|
|
return;
|
|
}
|
|
newMsg.ID = -1;
|
|
newMsg.name = msgName;
|
|
newMsg.sender = node;
|
|
dbcHandler->getFileByIdx(0)->messageHandler->addMessage(newMsg);
|
|
}
|
|
else
|
|
{
|
|
if (msg != NULL) msg->name = msgName;
|
|
}
|
|
inhibitCellChanged = true;
|
|
replacement = new QTableWidgetItem(msgName);
|
|
ui->MessagesTable->setItem(row, col, replacement);
|
|
inhibitCellChanged = false;
|
|
break;
|
|
|
|
case 2: //data length
|
|
msgLen = ui->MessagesTable->item(row, col)->text().toInt();
|
|
if (msgLen < 0) msgLen = 0;
|
|
if (msgLen > 8) msgLen = 8;
|
|
if (row == ui->MessagesTable->rowCount() - 1) //new record
|
|
{
|
|
DBC_MESSAGE newMsg;
|
|
newMsg.ID = -1;
|
|
newMsg.name = "";
|
|
newMsg.len = msgLen;
|
|
newMsg.sender = node;
|
|
dbcHandler->getFileByIdx(0)->messageHandler->addMessage(newMsg);
|
|
}
|
|
else //editing an existing record
|
|
{
|
|
if (msg != NULL) msg->len = msgLen;
|
|
}
|
|
inhibitCellChanged = true;
|
|
replacement = new QTableWidgetItem(QString::number(msgLen, 16));
|
|
ui->MessagesTable->setItem(row, col, replacement);
|
|
inhibitCellChanged = false;
|
|
|
|
break;
|
|
case 3: //signals (number) - we don't handle anything here. User cannot directly change this value
|
|
break;
|
|
case 4: //comment
|
|
msgComment = ui->MessagesTable->item(row, col)->text().simplified();
|
|
if (row == ui->MessagesTable->rowCount() - 1) //new record
|
|
{
|
|
DBC_MESSAGE newMsg;
|
|
newMsg.ID = -1;
|
|
newMsg.name = "";
|
|
newMsg.len = 0;
|
|
newMsg.comment = msgComment;
|
|
newMsg.sender = node;
|
|
dbcHandler->getFileByIdx(0)->messageHandler->addMessage(newMsg);
|
|
}
|
|
else //editing an existing record
|
|
{
|
|
if (msg != NULL) msg->comment = msgComment;
|
|
}
|
|
inhibitCellChanged = true;
|
|
replacement = new QTableWidgetItem(msgComment);
|
|
ui->MessagesTable->setItem(row, col, replacement);
|
|
inhibitCellChanged = false;
|
|
break;
|
|
|
|
}
|
|
|
|
if (row == ui->MessagesTable->rowCount() - 1)
|
|
{
|
|
ui->MessagesTable->insertRow(ui->MessagesTable->rowCount());
|
|
}
|
|
|
|
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 == NULL) return;
|
|
|
|
nodeName = item->text();
|
|
qDebug() << "Trying to find node with name " << nodeName;
|
|
DBC_NODE *node = dbcHandler->getFileByIdx(0)->findNodeByName(nodeName);
|
|
//qDebug() << "Address of node: " << (int)node;
|
|
inhibitCellChanged = true;
|
|
refreshMessagesTable(node);
|
|
inhibitCellChanged = false;
|
|
}
|
|
}
|
|
|
|
void DBCMainEditor::onCellClickedMessage(int row, int col)
|
|
{
|
|
if (col == 3) //3 is the signals field. If clicked we go to the signals dialog
|
|
{
|
|
QString idString = ui->MessagesTable->item(row, 0)->text();
|
|
DBC_MESSAGE *message = dbcHandler->getFileByIdx(0)->messageHandler->findMsgByID(Utility::ParseStringToNum(idString));
|
|
sigEditor->setMessageRef(message);
|
|
sigEditor->exec(); //blocks this window from being active until we're done
|
|
//now update the displayed # of signals
|
|
inhibitCellChanged = true;
|
|
QTableWidgetItem *replacement = new QTableWidgetItem(QString::number(message->sigHandler->getCount()));
|
|
ui->MessagesTable->setItem(row, col, replacement);
|
|
inhibitCellChanged = false;
|
|
}
|
|
}
|
|
|
|
void DBCMainEditor::refreshNodesTable()
|
|
{
|
|
ui->NodesTable->clearContents(); //first step, clear out any previous crap
|
|
ui->NodesTable->setRowCount(0);
|
|
|
|
int rowIdx;
|
|
|
|
if (dbcHandler->getFileByIdx(0)->findNodeByName("Vector__XXX") == NULL)
|
|
{
|
|
DBC_NODE newNode;
|
|
newNode.name = "Vector__XXX";
|
|
newNode.comment = "Default node if no other node is specified";
|
|
dbcHandler->getFileByIdx(0)->dbc_nodes.append(newNode);
|
|
}
|
|
|
|
for (int x = 0; x < dbcHandler->getFileByIdx(0)->dbc_nodes.count(); x++)
|
|
{
|
|
DBC_NODE node = dbcHandler->getFileByIdx(0)->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());
|
|
}
|
|
|
|
void DBCMainEditor::refreshMessagesTable(const DBC_NODE *node)
|
|
{
|
|
ui->MessagesTable->clearContents();
|
|
ui->MessagesTable->setRowCount(0);
|
|
|
|
qDebug() << "In refreshMessagesTable";
|
|
|
|
int rowIdx;
|
|
|
|
if (node != NULL)
|
|
{
|
|
for (int x = 0; x < dbcHandler->getFileByIdx(0)->messageHandler->getCount(); x++)
|
|
{
|
|
DBC_MESSAGE *msg = dbcHandler->getFileByIdx(0)->messageHandler->findMsgByIdx(x);
|
|
if (msg->sender == node)
|
|
{
|
|
//many of these are simplistic first versions just to test functionality.
|
|
QTableWidgetItem *msgID = new QTableWidgetItem(Utility::formatNumber(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 *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, 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.
|
|
}
|
|
}
|
|
}
|
|
|
|
//insert blank record that can be used to add new messages
|
|
ui->MessagesTable->insertRow(ui->MessagesTable->rowCount());
|
|
}
|