Files
giesCANne/filecomparatorwindow.cpp
T
Collin Kidder 07de662532 Updated the entire program to work in either hex or decimal. Changing the mode in settings will change which is used in many places.
You can always still enter values in decimal, hex, or binary regardless of the mode you are in.
2015-08-12 20:18:33 -04:00

351 lines
12 KiB
C++

#include "filecomparatorwindow.h"
#include "ui_filecomparatorwindow.h"
#include <QSettings>
FileComparatorWindow::FileComparatorWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::FileComparatorWindow)
{
ui->setupUi(this);
connect(ui->btnInterestedFile, SIGNAL(clicked(bool)), this, SLOT(loadInterestedFile()));
connect(ui->btnLoadRefFile, SIGNAL(clicked(bool)), this, SLOT(loadReferenceFile()));
connect(ui->btnSaveDetails, SIGNAL(clicked(bool)), this, SLOT(saveDetails()));
connect(ui->btnClear, SIGNAL(clicked(bool)), this, SLOT(clearReference()));
ui->lblFirstFile->setText("");
ui->lblRefFrames->setText("0");
}
FileComparatorWindow::~FileComparatorWindow()
{
delete ui;
}
void FileComparatorWindow::showEvent(QShowEvent *)
{
readSettings();
}
void FileComparatorWindow::closeEvent(QCloseEvent *event)
{
writeSettings();
}
void FileComparatorWindow::readSettings()
{
QSettings settings;
if (settings.value("Main/SaveRestorePositions", false).toBool())
{
resize(settings.value("FileComparator/WindowSize", QSize(720, 631)).toSize());
move(settings.value("FileComparator/WindowPos", QPoint(50, 50)).toPoint());
}
}
void FileComparatorWindow::writeSettings()
{
QSettings settings;
if (settings.value("Main/SaveRestorePositions", false).toBool())
{
settings.setValue("FileComparator/WindowSize", size());
settings.setValue("FileComparator/WindowPos", pos());
}
}
void FileComparatorWindow::loadInterestedFile()
{
interestedFrames.clear();
QString result = FrameFileIO::loadFrameFile(&interestedFrames);
if (result.length() > 0)
{
ui->lblFirstFile->setText(result);
interestedFilename = result;
if (interestedFrames.count() > 0 && referenceFrames.count() > 0) calculateDetails();
}
}
void FileComparatorWindow::loadReferenceFile()
{
//secondFileFrames.clear();
QString result = FrameFileIO::loadFrameFile(&referenceFrames);
if (result.length() > 0)
{
ui->lblRefFrames->setText(QString::number(referenceFrames.length()));
if (interestedFrames.count() > 0 && referenceFrames.count() > 0) calculateDetails();
}
}
void FileComparatorWindow::clearReference()
{
referenceFrames.clear();
ui->treeDetails->clear();
}
void FileComparatorWindow::calculateDetails()
{
QMap<int, FrameData> interestedIDs;
QMap<int, FrameData> referenceIDs;
QTreeWidgetItem *interestedOnlyBase, *referenceOnlyBase, *sharedBase, *bitmapBaseInterested, *bitmapBaseReference;
QTreeWidgetItem *valuesBase, *detail, *sharedItem, *valuesInterested, *valuesReference;
uint64_t tmp;
bool uniqueInterested = ui->ckUniqueToInterested->isChecked();
ui->treeDetails->clear();
interestedOnlyBase = new QTreeWidgetItem();
interestedOnlyBase->setText(0,"IDs found only in " + interestedFilename);
if (!uniqueInterested)
{
referenceOnlyBase = new QTreeWidgetItem();
referenceOnlyBase->setText(0, "IDs found only in reference frames");
}
sharedBase = new QTreeWidgetItem();
sharedBase->setText(0,"IDs found in both places");
//first we have to fill out the data structures to get ready to do the report
for (int x = 0; x < interestedFrames.count(); x++)
{
CANFrame frame = interestedFrames.at(x);
if (interestedIDs.contains(frame.ID)) //if we saw this ID before then add to the QList in there
{
for (int y = 0; y < frame.len; y++)
{
interestedIDs[frame.ID].values[y][frame.data[y]]++;
tmp = frame.data[y];
tmp = tmp << (8 * y);
interestedIDs[frame.ID].bitmap |= tmp;
//qDebug() << "bitmap: " << QString::number(interestedIDs[frame.ID].bitmap, 16);
}
}
else //never seen this ID before so add one
{
FrameData *newData = new FrameData();
newData->ID = frame.ID;
newData->dataLen = frame.len;
//it would be possible to implement a constructor for FrameData
//that sets the bitmap and values to zero. That would be cleaner and better.
newData->bitmap = 0;
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 256; y++)
{
newData->values[x][y] = 0;
}
}
//memset(newData->values, 0, 256 * 8);
for (int y = 0; y < frame.len; y++)
{
newData->values[y][frame.data[y]] = 1;
tmp = frame.data[y];
tmp = tmp << (8 * y);
newData->bitmap |= tmp;
//qDebug() << "bitmap: " << QString::number(newData->bitmap, 16);
}
interestedIDs.insert(frame.ID, *newData);
}
}
for (int x = 0; x < referenceFrames.count(); x++)
{
CANFrame frame = referenceFrames.at(x);
if (referenceIDs.contains(frame.ID)) //if we saw this ID before then add to the QList in there
{
for (int y = 0; y < frame.len; y++)
{
referenceIDs[frame.ID].values[y][frame.data[y]]++;
tmp = frame.data[y];
tmp = tmp << (8 * y);
referenceIDs[frame.ID].bitmap |= tmp;
//qDebug() << "bitmap: " << QString::number(referenceIDs[frame.ID].bitmap, 16);
}
}
else //never seen this ID before so add one
{
FrameData *newData = new FrameData();
newData->ID = frame.ID;
newData->dataLen = frame.len;
newData->bitmap = 0;
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 256; y++)
{
newData->values[x][y] = 0;
}
}
//memset(newData->values, 0, 256 * 8);
for (int y = 0; y < frame.len; y++)
{
newData->values[y][frame.data[y]] = 1;
tmp = frame.data[y];
tmp = tmp << (8 * y);
newData->bitmap |= tmp;
//qDebug() << "bitmap: " << QString::number(newData->bitmap, 16);
}
referenceIDs.insert(frame.ID, *newData);
}
}
//now we iterate through the IDs within both files and see which are unique to one file and which
//are shared
bool interestedHadUnique = false;
QMap<int, FrameData>::iterator i;
for (i = interestedIDs.begin(); i != interestedIDs.end(); ++i)
{
int keyone = i.key();
if (!referenceIDs.contains(keyone))
{
valuesBase = new QTreeWidgetItem();
valuesBase->setText(0, QString::number(keyone, 16));
interestedOnlyBase->addChild(valuesBase);
}
else //ID was in both files
{
interestedHadUnique = false;
sharedItem = new QTreeWidgetItem();
sharedItem->setText(0, Utility::formatHexNum(keyone));
//if the ID was in both files then we can use the data accumulated above in bitmap
//and values to figure out what has changed between the two files
FrameData interested = interestedIDs[keyone];
FrameData reference = referenceIDs[keyone];
bitmapBaseInterested = new QTreeWidgetItem();
bitmapBaseInterested->setText(0, "Bits set only in " + interestedFilename);
if (!uniqueInterested)
{
bitmapBaseReference = new QTreeWidgetItem();
bitmapBaseReference->setText(0, "Bits set only in reference frames");
}
sharedItem->addChild(bitmapBaseInterested);
if (!uniqueInterested) sharedItem->addChild(bitmapBaseReference);
uint64_t interestedBits = interested.bitmap;
uint64_t referenceBits = reference.bitmap;
//first up, which bits were set in one file but not the other
for (int b = 0; b < (8 * interested.dataLen); b++)
{
detail = new QTreeWidgetItem();
detail->setText(0, QString::number(b) + " (" + QString::number(b / 8) + ":" + QString::number(b % 8) + ")");
if ( (interestedBits & 1) && !(referenceBits & 1) )
{
bitmapBaseInterested->addChild(detail);
interestedHadUnique = true;
}
else if ( !(interestedBits & 1) && (referenceBits & 1) )
{
if (!uniqueInterested) bitmapBaseReference->addChild(detail);
}
//qDebug() << b << " " << QString::number(interestedBits, 16) << " " << QString::number(referenceBits, 16);
interestedBits = interestedBits >> 1;
referenceBits = referenceBits >> 1;
}
for (int i = 0; i < qMax(interested.dataLen, reference.dataLen); i++)
{
valuesBase = new QTreeWidgetItem();
valuesBase->setText(0, "Byte " + QString::number(i));
sharedItem->addChild(valuesBase);
valuesInterested = new QTreeWidgetItem();
valuesInterested->setText(0, "Values found only in " + interestedFilename);
if (!uniqueInterested)
{
valuesReference = new QTreeWidgetItem();
valuesReference->setText(0, "Values found only in reference frames");
}
valuesBase->addChild(valuesInterested);
if (!uniqueInterested) valuesBase->addChild(valuesReference);
for (int j = 0; j < 256; j++)
{
detail = new QTreeWidgetItem();
detail->setText(0, Utility::formatHexNum(j));
if ((interested.values[i][j] > 0) && (reference.values[i][j] == 0) )
{
valuesInterested->addChild(detail);
interestedHadUnique = true;
}
if ((reference.values[i][j] > 0) && (interested.values[i][j] == 0) )
{
if (!uniqueInterested) valuesReference->addChild(detail);
}
}
}
if (interestedHadUnique || !uniqueInterested) sharedBase->addChild(sharedItem);
}
}
if (!uniqueInterested)
{
QMap<int, FrameData>::iterator itwo;
for (itwo = referenceIDs.begin(); itwo != referenceIDs.end(); ++itwo)
{
int keytwo = itwo.key();
if (!interestedIDs.contains(keytwo))
{
valuesBase = new QTreeWidgetItem();
valuesBase->setText(0, Utility::formatHexNum(keytwo));
referenceOnlyBase->addChild(valuesBase);
}
}
}
ui->treeDetails->addTopLevelItem(interestedOnlyBase);
if (!uniqueInterested) ui->treeDetails->addTopLevelItem(referenceOnlyBase);
ui->treeDetails->addTopLevelItem(sharedBase);
//ui->treeDetails->setSortingEnabled(true);
//ui->treeDetails->sortByColumn(0, Qt::AscendingOrder);
QSettings settings;
if (settings.value("InfoCompare/AutoExpand", false).toBool())
{
ui->treeDetails->expandAll();
}
}
void FileComparatorWindow::saveDetails()
{
QString filename;
QFileDialog dialog(this);
QStringList filters;
filters.append(QString(tr("Text File (*.txt)")));
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() == QDialog::Accepted)
{
filename = dialog.selectedFiles()[0];
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();
}
}