Add tracking of DBC editing in order to warn when exiting without saving, add sorting to DBC routines, add a new screen that allows one to compare two DBC files for changes/differences.
This commit is contained in:
@@ -0,0 +1,399 @@
|
||||
#include "dbccomparatorwindow.h"
|
||||
#include "ui_dbccomparatorwindow.h"
|
||||
#include "helpwindow.h"
|
||||
#include <QProgressDialog>
|
||||
#include <QSettings>
|
||||
#include <qevent.h>
|
||||
|
||||
DBCComparatorWindow::DBCComparatorWindow(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::DBCComparatorWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowFlags(Qt::Window);
|
||||
|
||||
connect(ui->btnDBCFile1, SIGNAL(clicked(bool)), this, SLOT(loadFirstFile()));
|
||||
connect(ui->btnDBCFile2, SIGNAL(clicked(bool)), this, SLOT(loadSecondFile()));
|
||||
connect(ui->btnSaveDetails, SIGNAL(clicked(bool)), this, SLOT(saveDetails()));
|
||||
|
||||
ui->lblFirstFile->setText("");
|
||||
ui->lblSecondFile->setText("");
|
||||
|
||||
firstDBC = nullptr;
|
||||
secondDBC = nullptr;
|
||||
|
||||
installEventFilter(this);
|
||||
}
|
||||
|
||||
DBCComparatorWindow::~DBCComparatorWindow()
|
||||
{
|
||||
removeEventFilter(this);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DBCComparatorWindow::showEvent(QShowEvent *)
|
||||
{
|
||||
readSettings();
|
||||
}
|
||||
|
||||
void DBCComparatorWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
bool DBCComparatorWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyRelease) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_F1:
|
||||
HelpWindow::getRef()->showHelp("filecomparison.html");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// standard event processing
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DBCComparatorWindow::readSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||
{
|
||||
resize(settings.value("DBCComparator/WindowSize", QSize(720, 631)).toSize());
|
||||
move(settings.value("DBCComparator/WindowPos", QPoint(50, 50)).toPoint());
|
||||
}
|
||||
}
|
||||
|
||||
void DBCComparatorWindow::writeSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||
{
|
||||
settings.setValue("DBCComparator/WindowSize", size());
|
||||
settings.setValue("DBCComparator/WindowPos", pos());
|
||||
}
|
||||
}
|
||||
|
||||
QString DBCComparatorWindow::loadDBC(DBCFile **file)
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog;
|
||||
QSettings settings;
|
||||
|
||||
QStringList filters;
|
||||
filters.append(QString(tr("DBC Files (*.dbc *.DBC)")));
|
||||
|
||||
dialog.setDirectory(settings.value("FileIO/LoadSaveDirectory", dialog.directory().path()).toString());
|
||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||
dialog.setNameFilters(filters);
|
||||
dialog.setViewMode(QFileDialog::Detail);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
|
||||
QProgressDialog progress(qApp->activeWindow());
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
progress.setLabelText("Loading file...");
|
||||
progress.setCancelButton(nullptr);
|
||||
progress.setRange(0,0);
|
||||
progress.setMinimumDuration(0);
|
||||
progress.show();
|
||||
|
||||
qApp->processEvents();
|
||||
|
||||
if (dialog.selectedNameFilter() == filters[0])
|
||||
{
|
||||
if (file[0]) delete file[0];
|
||||
file[0] = new DBCFile;
|
||||
file[0]->loadFile(filename);
|
||||
qDebug() << "Loaded the DBC file into first slot";
|
||||
}
|
||||
|
||||
progress.cancel();
|
||||
return filename;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void DBCComparatorWindow::loadFirstFile()
|
||||
{
|
||||
QString filename;
|
||||
filename = loadDBC(&firstDBC);
|
||||
ui->lblFirstFile->setText(filename);
|
||||
if (firstDBC && secondDBC) calculateDetails();
|
||||
}
|
||||
|
||||
void DBCComparatorWindow::loadSecondFile()
|
||||
{
|
||||
QString filename;
|
||||
filename = loadDBC(&secondDBC);
|
||||
ui->lblSecondFile->setText(filename);
|
||||
if (firstDBC && secondDBC) calculateDetails();
|
||||
}
|
||||
|
||||
void DBCComparatorWindow::calculateDetails()
|
||||
{
|
||||
QProgressDialog progress(this);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
progress.setLabelText("Calculating differences");
|
||||
progress.setCancelButton(nullptr);
|
||||
progress.setRange(0,0);
|
||||
progress.setMinimumDuration(0);
|
||||
progress.show();
|
||||
|
||||
qApp->processEvents();
|
||||
|
||||
firstDBC->sort();
|
||||
secondDBC->sort();
|
||||
|
||||
|
||||
ui->treeDetails->clear();
|
||||
|
||||
//Find nodes missing in one of the DBC files
|
||||
|
||||
QTreeWidgetItem *nodeDiffRoot = new QTreeWidgetItem();
|
||||
nodeDiffRoot->setText(0, "Node Differences");
|
||||
QTreeWidgetItem *nodesMissingDBCFirst = new QTreeWidgetItem();
|
||||
nodesMissingDBCFirst->setText(0, "Nodes not found in first DBC");
|
||||
QTreeWidgetItem *nodesMissingDBCSecond = new QTreeWidgetItem();
|
||||
nodesMissingDBCSecond->setText(0, "Nodes not found in second DBC");
|
||||
nodeDiffRoot->addChild(nodesMissingDBCFirst);
|
||||
nodeDiffRoot->addChild(nodesMissingDBCSecond);
|
||||
ui->treeDetails->addTopLevelItem(nodeDiffRoot);
|
||||
|
||||
for (int i = 0; i < firstDBC->dbc_nodes.count(); i++)
|
||||
{
|
||||
QString nodeName = firstDBC->dbc_nodes[i].name;
|
||||
DBC_NODE *node = secondDBC->findNodeByName(nodeName);
|
||||
if (!node)
|
||||
{
|
||||
QTreeWidgetItem *missingNodeItem = new QTreeWidgetItem();
|
||||
missingNodeItem->setText(0, nodeName);
|
||||
nodesMissingDBCSecond->addChild(missingNodeItem);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < secondDBC->dbc_nodes.count(); i++)
|
||||
{
|
||||
QString nodeName = secondDBC->dbc_nodes[i].name;
|
||||
DBC_NODE *node = firstDBC->findNodeByName(nodeName);
|
||||
if (!node)
|
||||
{
|
||||
QTreeWidgetItem *missingNodeItem = new QTreeWidgetItem();
|
||||
missingNodeItem->setText(0, nodeName);
|
||||
nodesMissingDBCFirst->addChild(missingNodeItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Find messages that are missing in one of the DBC files
|
||||
//If a message exists in both then check for missing signals
|
||||
|
||||
QTreeWidgetItem *msgDiffRoot = new QTreeWidgetItem();
|
||||
msgDiffRoot->setText(0, "Message Differences");
|
||||
QTreeWidgetItem *msgMissingDBCFirst = new QTreeWidgetItem();
|
||||
msgMissingDBCFirst->setText(0, "Messages not found in first DBC");
|
||||
QTreeWidgetItem *msgMissingDBCSecond = new QTreeWidgetItem();
|
||||
msgMissingDBCSecond->setText(0, "Messages not found in second DBC");
|
||||
QTreeWidgetItem *msgSignalsDiff = new QTreeWidgetItem();
|
||||
msgSignalsDiff->setText(0, "Messages with missing signals");
|
||||
QTreeWidgetItem *sigDiffOne = new QTreeWidgetItem();
|
||||
sigDiffOne->setText(0, "Missing from first DBC");
|
||||
QTreeWidgetItem *sigDiffTwo = new QTreeWidgetItem();
|
||||
sigDiffTwo->setText(0, "Missing from second DBC");
|
||||
QTreeWidgetItem *sigModifiedRoot = new QTreeWidgetItem();
|
||||
sigModifiedRoot->setText(0, "Modified Signals");
|
||||
msgSignalsDiff->addChild(sigDiffOne);
|
||||
msgSignalsDiff->addChild(sigDiffTwo);
|
||||
|
||||
msgDiffRoot->addChild(msgMissingDBCFirst);
|
||||
msgDiffRoot->addChild(msgMissingDBCSecond);
|
||||
msgDiffRoot->addChild(msgSignalsDiff);
|
||||
msgDiffRoot->addChild(sigModifiedRoot);
|
||||
|
||||
ui->treeDetails->addTopLevelItem(msgDiffRoot);
|
||||
|
||||
QTreeWidgetItem *msgItem;
|
||||
QTreeWidgetItem *sigTemp;
|
||||
|
||||
for (int i = 0; i < firstDBC->messageHandler->getCount(); i++)
|
||||
{
|
||||
DBC_MESSAGE *thisMsg = firstDBC->messageHandler->findMsgByIdx(i);
|
||||
QString msgName = thisMsg->name;
|
||||
DBC_MESSAGE *otherMsg = secondDBC->messageHandler->findMsgByName(msgName);
|
||||
if (!otherMsg)
|
||||
{
|
||||
QTreeWidgetItem *missingMsgItem = new QTreeWidgetItem();
|
||||
missingMsgItem->setText(0, msgName);
|
||||
msgMissingDBCSecond->addChild(missingMsgItem);
|
||||
}
|
||||
else //both have Msg. Check sigs for missing
|
||||
{
|
||||
bool thisMsgHasMissing = false;
|
||||
bool thisMsgHasMods = false;
|
||||
|
||||
for (int i = 0; i < thisMsg->sigHandler->getCount(); i++)
|
||||
{
|
||||
DBC_SIGNAL *thisSig = thisMsg->sigHandler->findSignalByIdx(i);
|
||||
QString sigName = thisSig->name;
|
||||
DBC_SIGNAL *otherSig = otherMsg->sigHandler->findSignalByName(sigName);
|
||||
if (!otherSig)
|
||||
{
|
||||
QTreeWidgetItem *missingSigItem = new QTreeWidgetItem();
|
||||
missingSigItem->setText(0, sigName);
|
||||
if (!thisMsgHasMissing)
|
||||
{
|
||||
thisMsgHasMissing = true;
|
||||
msgItem = new QTreeWidgetItem();
|
||||
msgItem->setText(0, msgName);
|
||||
sigDiffTwo->addChild(msgItem);
|
||||
}
|
||||
msgItem->addChild(missingSigItem);
|
||||
}
|
||||
else //signal exists on both sides. See if it as changed position or length
|
||||
{
|
||||
bool didChange = false;
|
||||
QTreeWidgetItem *sigItem = new QTreeWidgetItem();
|
||||
sigItem->setText(0, sigName);
|
||||
if (thisSig->startBit != otherSig->startBit)
|
||||
{
|
||||
didChange = true;
|
||||
QTreeWidgetItem *sigStartBit = new QTreeWidgetItem();
|
||||
sigStartBit->setText(0, "Start Bit First DBC: " + QString::number(thisSig->startBit) + " Second: " + QString::number(otherSig->startBit));
|
||||
sigItem->addChild(sigStartBit);
|
||||
}
|
||||
if (thisSig->signalSize != otherSig->signalSize)
|
||||
{
|
||||
didChange = true;
|
||||
QTreeWidgetItem *sigSize = new QTreeWidgetItem();
|
||||
sigSize->setText(0, "Size First DBC: " + QString::number(thisSig->signalSize) + " Second: " + QString::number(otherSig->signalSize));
|
||||
sigItem->addChild(sigSize);
|
||||
}
|
||||
if (thisSig->bias != otherSig->bias)
|
||||
{
|
||||
didChange = true;
|
||||
QTreeWidgetItem *sigBias = new QTreeWidgetItem();
|
||||
sigBias->setText(0, "Bias First DBC: " + QString::number(thisSig->bias) + " Second: " + QString::number(otherSig->bias));
|
||||
sigItem->addChild(sigBias);
|
||||
}
|
||||
if (thisSig->factor != otherSig->factor)
|
||||
{
|
||||
didChange = true;
|
||||
QTreeWidgetItem *sigFactor = new QTreeWidgetItem();
|
||||
sigFactor->setText(0, "Factor First DBC: " + QString::number(thisSig->factor) + " Second: " + QString::number(otherSig->factor));
|
||||
sigItem->addChild(sigFactor);
|
||||
}
|
||||
if (didChange)
|
||||
{
|
||||
if (!thisMsgHasMods)
|
||||
{
|
||||
thisMsgHasMods = true;
|
||||
sigTemp = new QTreeWidgetItem();
|
||||
sigTemp->setText(0, msgName);
|
||||
sigModifiedRoot->addChild(sigTemp);
|
||||
}
|
||||
sigTemp->addChild(sigItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
thisMsgHasMissing = false;
|
||||
for (int i = 0; i < otherMsg->sigHandler->getCount(); i++)
|
||||
{
|
||||
DBC_SIGNAL *thisSig = otherMsg->sigHandler->findSignalByIdx(i);
|
||||
QString sigName = thisSig->name;
|
||||
DBC_SIGNAL *otherSig = thisMsg->sigHandler->findSignalByName(sigName);
|
||||
if (!otherSig)
|
||||
{
|
||||
QTreeWidgetItem *missingSigItem = new QTreeWidgetItem();
|
||||
missingSigItem->setText(0, sigName);
|
||||
if (!thisMsgHasMissing)
|
||||
{
|
||||
thisMsgHasMissing = true;
|
||||
msgItem = new QTreeWidgetItem();
|
||||
msgItem->setText(0, msgName);
|
||||
sigDiffOne->addChild(msgItem);
|
||||
}
|
||||
msgItem->addChild(missingSigItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < secondDBC->messageHandler->getCount(); i++)
|
||||
{
|
||||
QString msgName = secondDBC->messageHandler->findMsgByIdx(i)->name;
|
||||
DBC_MESSAGE *msg = firstDBC->messageHandler->findMsgByName(msgName);
|
||||
if (!msg)
|
||||
{
|
||||
QTreeWidgetItem *missingMsgItem = new QTreeWidgetItem();
|
||||
missingMsgItem->setText(0, msgName);
|
||||
msgMissingDBCFirst->addChild(missingMsgItem);
|
||||
}
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
if (settings.value("InfoCompare/AutoExpand", false).toBool())
|
||||
{
|
||||
ui->treeDetails->expandAll();
|
||||
}
|
||||
|
||||
progress.cancel();
|
||||
|
||||
qApp->processEvents();
|
||||
}
|
||||
|
||||
void DBCComparatorWindow::saveDetails()
|
||||
{
|
||||
QString filename;
|
||||
QFileDialog dialog(this);
|
||||
QSettings settings;
|
||||
|
||||
QStringList filters;
|
||||
filters.append(QString(tr("Text File (*.txt)")));
|
||||
|
||||
dialog.setFileMode(QFileDialog::AnyFile);
|
||||
dialog.setNameFilters(filters);
|
||||
dialog.setViewMode(QFileDialog::Detail);
|
||||
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||
dialog.setDirectory(settings.value("FileComparator/LoadSaveDirectory", dialog.directory().path()).toString());
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = dialog.selectedFiles()[0];
|
||||
settings.setValue("FileComparator/LoadSaveDirectory", dialog.directory().path());
|
||||
if (!filename.contains('.')) filename += ".txt";
|
||||
QFile *outFile = new QFile(filename);
|
||||
|
||||
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
return;
|
||||
|
||||
QTreeWidget *tree = ui->treeDetails;
|
||||
|
||||
|
||||
QTreeWidgetItemIterator it(tree);
|
||||
while (*it) {
|
||||
QTreeWidgetItem *item = *it;
|
||||
QString itemText = item->text(0);
|
||||
while (item->parent())
|
||||
{
|
||||
outFile->write(" ");
|
||||
item = item->parent();
|
||||
}
|
||||
outFile->write(itemText.toUtf8() + "\n");
|
||||
++it;
|
||||
}
|
||||
|
||||
outFile->close();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user