Files
giesCANne/mainwindow.cpp
T
Collin Kidder 4dc8c5b434 Initial commit where connection window is active and it is possible to
connect to GVRET but this time through the connection window and the
menu option "Connect".
2015-10-18 15:34:40 -04:00

1100 lines
35 KiB
C++

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "can_structs.h"
#include <QDateTime>
#include <QFileDialog>
#include <QtSerialPort/QSerialPortInfo>
#include "canframemodel.h"
#include "utility.h"
#include "serialworker.h"
/*
Things that were planned for the GVRET-PC project but never completed.
Single / Multi state - The goal is to find bits that change based on toggles or discrete state items (shifters, etc)
Range state - Find things that range like accelerator pedal inputs, road speed, tach, etc
fuzzy scope - Try to find potential places where a given value might be stored - offer guesses and the program tries to find candidates for you
or, try to find things that appear to be multi-byte integers
*/
QString MainWindow::loadedFileName = "";
MainWindow *MainWindow::selfRef = NULL;
MainWindow *MainWindow::getReference()
{
return selfRef;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
useHex = true;
//These things are used by QSettings to set up setting storage
QCoreApplication::setOrganizationName("EVTV");
QCoreApplication::setOrganizationDomain("evtv.me");
QCoreApplication::setApplicationName("SavvyCAN");
selfRef = this;
this->setWindowTitle("Savvy CAN V" + QString::number(VERSION));
model = new CANFrameModel();
ui->canFramesView->setModel(model);
readSettings();
QStringList headers;
headers << "Timestamp" << "ID" << "Ext" << "Bus" << "Len" << "Data";
//model->setHorizontalHeaderLabels(headers);
ui->canFramesView->setColumnWidth(0, 110);
ui->canFramesView->setColumnWidth(1, 70);
ui->canFramesView->setColumnWidth(2, 40);
ui->canFramesView->setColumnWidth(3, 40);
ui->canFramesView->setColumnWidth(4, 40);
ui->canFramesView->setColumnWidth(5, 275);
QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader();
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
//enabling the below line kills performance in every way imaginable. Left here as a warning. Do not do this.
//ui->canFramesView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
worker = new SerialWorker(model);
worker->moveToThread(&serialWorkerThread);
connect(&serialWorkerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &MainWindow::sendSerialPort, worker, &SerialWorker::setSerialPort, Qt::QueuedConnection);
connect(worker, &SerialWorker::frameUpdateTick, this, &MainWindow::gotFrames, Qt::QueuedConnection);
connect(this, &MainWindow::updateBaudRates, worker, &SerialWorker::updateBaudRates, Qt::QueuedConnection);
connect(this, &MainWindow::sendCANFrame, worker, &SerialWorker::sendFrame, Qt::QueuedConnection);
connect(worker, &SerialWorker::connectionSuccess, this, &MainWindow::connectionSucceeded, Qt::QueuedConnection);
connect(worker, &SerialWorker::connectionFailure, this, &MainWindow::connectionFailed, Qt::QueuedConnection);
connect(worker, &SerialWorker::deviceInfo, this, &MainWindow::gotDeviceInfo, Qt::QueuedConnection);
connect(this, &MainWindow::closeSerialPort, worker, &SerialWorker::closeSerialPort, Qt::QueuedConnection);
connect(this, &MainWindow::startFrameCapturing, worker, &SerialWorker::startFrameCapture);
connect(this, &MainWindow::stopFrameCapturing, worker, &SerialWorker::stopFrameCapture);
connect(this, &MainWindow::settingsUpdated, worker, &SerialWorker::readSettings);
serialWorkerThread.start();
serialWorkerThread.setPriority(QThread::HighPriority);
graphingWindow = NULL;
frameInfoWindow = NULL;
playbackWindow = NULL;
flowViewWindow = NULL;
frameSenderWindow = NULL;
dbcMainEditor = NULL;
comparatorWindow = NULL;
settingsDialog = NULL;
firmwareUploaderWindow = NULL;
discreteStateWindow = NULL;
connectionWindow = NULL;
dbcHandler = new DBCHandler;
bDirty = false;
inhibitFilterUpdate = false;
model->setDBCHandler(dbcHandler);
connect(ui->actionOpen_Log_File, SIGNAL(triggered(bool)), this, SLOT(handleLoadFile()));
connect(ui->actionGraph_Dta, SIGNAL(triggered(bool)), this, SLOT(showGraphingWindow()));
connect(ui->actionFrame_Data_Analysis, SIGNAL(triggered(bool)), this, SLOT(showFrameDataAnalysis()));
connect(ui->btnClearFrames, SIGNAL(clicked(bool)), this, SLOT(clearFrames()));
connect(ui->actionSave_Log_File, SIGNAL(triggered(bool)), this, SLOT(handleSaveFile()));
connect(ui->actionSave_Filtered_Log_File, SIGNAL(triggered(bool)), this, SLOT(handleSaveFilteredFile()));
connect(ui->actionLoad_Filter_Definition, SIGNAL(triggered(bool)), this, SLOT(handleLoadFilters()));
connect(ui->actionSave_Filter_Definition, SIGNAL(triggered(bool)), this, SLOT(handleSaveFilters()));
connect(ui->action_Playback, SIGNAL(triggered(bool)), this, SLOT(showPlaybackWindow()));
connect(ui->actionFlow_View, SIGNAL(triggered(bool)), this, SLOT(showFlowViewWindow()));
connect(ui->action_Custom, SIGNAL(triggered(bool)), this, SLOT(showFrameSenderWindow()));
connect(ui->actionLoad_DBC_File, SIGNAL(triggered(bool)), this, SLOT(handleLoadDBC()));
connect(ui->actionSave_DBC_File, SIGNAL(triggered(bool)), this, SLOT(handleSaveDBC()));
connect(ui->canFramesView, SIGNAL(clicked(QModelIndex)), this, SLOT(gridClicked(QModelIndex)));
connect(ui->canFramesView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(gridDoubleClicked(QModelIndex)));
connect(ui->cbInterpret, SIGNAL(toggled(bool)), this, SLOT(interpretToggled(bool)));
connect(ui->cbOverwrite, SIGNAL(toggled(bool)), this, SLOT(overwriteToggled(bool)));
connect(ui->actionEdit_Messages_Signals, SIGNAL(triggered(bool)), this, SLOT(showDBCEditor()));
connect(ui->btnCaptureToggle, SIGNAL(clicked(bool)), this, SLOT(toggleCapture()));
connect(ui->actionExit_Application, SIGNAL(triggered(bool)), this, SLOT(exitApp()));
connect(ui->actionFuzzy_Scope, SIGNAL(triggered(bool)), this, SLOT(showFuzzyScopeWindow()));
connect(ui->actionRange_State, SIGNAL(triggered(bool)), this, SLOT(showRangeWindow()));
connect(ui->actionSave_Decoded_Frames, SIGNAL(triggered(bool)), this, SLOT(handleSaveDecoded()));
connect(ui->actionSingle_Multi_State, SIGNAL(triggered(bool)), this, SLOT(showSingleMultiWindow()));
connect(ui->actionFile_Comparison, SIGNAL(triggered(bool)), this, SLOT(showComparisonWindow()));
connect(ui->btnNormalize, SIGNAL(clicked(bool)), this, SLOT(normalizeTiming()));
connect(ui->actionPreferences, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog()));
connect(model, SIGNAL(updatedFiltersList()), this, SLOT(updateFilterList()));
connect(ui->listFilters, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(filterListItemChanged(QListWidgetItem*)));
connect(ui->btnFilterAll, SIGNAL(clicked(bool)), this, SLOT(filterSetAll()));
connect(ui->btnFilterNone, SIGNAL(clicked(bool)), this, SLOT(filterClearAll()));
connect(ui->actionFirmware_Uploader, SIGNAL(triggered(bool)), this, SLOT(showFirmwareUploaderWindow()));
connect(ui->actionSetup, SIGNAL(triggered(bool)), SLOT(showConnectionSettingsWindow()));
connect(ui->actionConnect, SIGNAL(triggered(bool)), this, SLOT(connButtonPress()));
lbStatusConnected.setText(tr("Not connected"));
updateFileStatus();
lbStatusDatabase.setText(tr("No DBC database loaded"));
ui->statusBar->addWidget(&lbStatusConnected);
ui->statusBar->addWidget(&lbStatusFilename);
ui->statusBar->addWidget(&lbStatusDatabase);
ui->lbFPS->setText("0");
ui->lbNumFrames->setText("0");
isConnected = false;
allowCapture = true;
//create a temporary frame to be able to capture the correct
//default height of an item in the table. Need to do this in case
//of scaling or font differences between different computers.
CANFrame temp;
temp.bus = 0;
temp.ID = 0x100;
temp.len = 0;
model->addFrame(temp, true);
normalRowHeight = ui->canFramesView->rowHeight(0);
qDebug() << "normal row height = " << normalRowHeight;
model->clearFrames();
}
MainWindow::~MainWindow()
{
serialWorkerThread.quit();
serialWorkerThread.wait();
//delete worker;
if (graphingWindow)
{
graphingWindow->close();
delete graphingWindow;
}
if (frameInfoWindow)
{
frameInfoWindow->close();
delete frameInfoWindow;
}
if (playbackWindow)
{
playbackWindow->close();
delete playbackWindow;
}
if (flowViewWindow)
{
flowViewWindow->close();
delete flowViewWindow;
}
if (frameSenderWindow)
{
frameSenderWindow->close();
delete frameSenderWindow;
}
if (comparatorWindow)
{
comparatorWindow->close();
delete comparatorWindow;
}
if (dbcMainEditor)
{
dbcMainEditor->close();
delete dbcMainEditor;
}
if (settingsDialog)
{
settingsDialog->close();
delete settingsDialog;
}
if (discreteStateWindow)
{
discreteStateWindow->close();
delete discreteStateWindow;
}
if (connectionWindow)
{
connectionWindow->close();
delete connectionWindow;
}
delete ui;
delete dbcHandler;
model->clearFrames();
delete model;
}
void MainWindow::closeEvent(QCloseEvent *event)
{
Q_UNUSED(event);
writeSettings();
exitApp();
}
void MainWindow::updateSettings()
{
readUpdateableSettings();
emit settingsUpdated();
}
void MainWindow::readSettings()
{
QSettings settings;
if (settings.value("Main/SaveRestorePositions", false).toBool())
{
resize(settings.value("Main/WindowSize", QSize(800, 750)).toSize());
move(settings.value("Main/WindowPos", QPoint(100, 100)).toPoint());
}
if (settings.value("Main/AutoScroll", false).toBool())
{
ui->cbAutoScroll->setChecked(true);
}
readUpdateableSettings();
}
void MainWindow::readUpdateableSettings()
{
QSettings settings;
useHex = settings.value("Main/UseHex", true).toBool();
model->setHexMode(useHex);
Utility::decimalMode = !useHex;
secondsMode = settings.value("Main/TimeSeconds", false).toBool();
model->setSecondsMode(secondsMode);
useFiltered = settings.value("Main/UseFiltered", false).toBool();
}
void MainWindow::writeSettings()
{
QSettings settings;
if (settings.value("Main/SaveRestorePositions", false).toBool())
{
settings.setValue("Main/WindowSize", size());
settings.setValue("Main/WindowPos", pos());
}
}
void MainWindow::updateConnectionSettings(QString connectionType, QString port, int speed0, int speed1)
{
connType = connectionType;
portName = port;
canSpeed0 = speed0;
canSpeed1 = speed1;
if (isConnected)
{
emit updateBaudRates(speed0, speed1);
}
}
void MainWindow::connButtonPress()
{
if (!isConnected)
{
if (connType == "GVRET")
{
QList<QSerialPortInfo> ports;
ports = QSerialPortInfo::availablePorts();
for (int i = 0; i < ports.count(); i++)
{
if (ports[i].portName() == portName)
{
portInfo = ports[i];
emit sendSerialPort(&portInfo);
lbStatusConnected.setText(tr("Attempting to connect to port ") + portName);
}
}
}
else if (connType == "KVASER")
{
}
else if (connType == "SOCKETCAN")
{
}
}
else
{
emit closeSerialPort();
isConnected = false;
lbStatusConnected.setText(tr("Not Connected"));
ui->actionConnect->setText(tr("Connect"));
}
}
void MainWindow::gridClicked(QModelIndex idx)
{
if (ui->canFramesView->rowHeight(idx.row()) > normalRowHeight)
{
ui->canFramesView->setRowHeight(idx.row(), normalRowHeight);
}
else {
ui->canFramesView->resizeRowToContents(idx.row());
}
}
void MainWindow::gridDoubleClicked(QModelIndex idx)
{
//grab ID and timestamp and send them away
CANFrame frame = model->getListReference()->at(idx.row());
emit sendCenterTimeID(frame.ID, frame.timestamp / 1000000.0);
}
void MainWindow::interpretToggled(bool state)
{
model->setInterpetMode(state);
}
void MainWindow::overwriteToggled(bool state)
{
model->setOverwriteMode(state);
}
void MainWindow::updateFilterList()
{
if (model == NULL) return;
const QMap<int, bool> *filters = model->getFiltersReference();
if (filters == NULL) return;
qDebug() << "updateFilterList called on MainWindow";
ui->listFilters->clear();
if (filters->isEmpty()) return;
QMap<int, bool>::const_iterator filterIter;
for (filterIter = filters->begin(); filterIter != filters->end(); ++filterIter)
{
QListWidgetItem *thisItem = new QListWidgetItem();
thisItem->setText(Utility::formatNumber(filterIter.key()));
thisItem->setFlags(thisItem->flags() | Qt::ItemIsUserCheckable);
if (filterIter.value()) thisItem->setCheckState(Qt::Checked);
else thisItem->setCheckState(Qt::Unchecked);
ui->listFilters->addItem(thisItem);
}
}
void MainWindow::filterListItemChanged(QListWidgetItem *item)
{
if (inhibitFilterUpdate) return;
//qDebug() << item->text();
int ID;
bool isSet = false;
ID = Utility::ParseStringToNum(item->text());
if (item->checkState() == Qt::Checked) isSet = true;
model->setFilterState(ID, isSet);
}
void MainWindow::filterSetAll()
{
inhibitFilterUpdate = true;
for (int i = 0; i < ui->listFilters->count(); i++)
{
ui->listFilters->item(i)->setCheckState(Qt::Checked);
}
inhibitFilterUpdate = false;
model->setAllFilters(true);
}
void MainWindow::filterClearAll()
{
inhibitFilterUpdate = true;
for (int i = 0; i < ui->listFilters->count(); i++)
{
ui->listFilters->item(i)->setCheckState(Qt::Unchecked);
}
inhibitFilterUpdate = false;
model->setAllFilters(false);
}
//most of the work is handled elsewhere. Need only to update the # of frames
//and maybe auto scroll
void MainWindow::gotFrames(int FPS, int framesSinceLastUpdate)
{
ui->lbNumFrames->setText(QString::number(model->rowCount()));
if (ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom();
ui->lbFPS->setText(QString::number(FPS));
if (framesSinceLastUpdate > 0)
{
bDirty = true;
emit framesUpdated(framesSinceLastUpdate); //anyone care that frames were updated?
}
if (model->needsFilterRefresh()) updateFilterList();
}
void MainWindow::addFrameToDisplay(CANFrame &frame, bool autoRefresh = false)
{
model->addFrame(frame, autoRefresh);
if (autoRefresh)
{
if (ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom();
ui->lbNumFrames->setText(QString::number(model->rowCount()));
}
}
//A sub-window is sending us a center on timestamp and ID signal
//try to find the relevant frame in the list and focus on it.
void MainWindow::gotCenterTimeID(int32_t ID, double timestamp)
{
int idx = model->getIndexFromTimeID(ID, timestamp);
if (idx > -1)
{
ui->canFramesView->selectRow(idx);
}
}
void MainWindow::clearFrames()
{
ui->canFramesView->scrollToTop();
model->clearFrames();
ui->lbNumFrames->setText(QString::number(model->rowCount()));
bDirty = false;
loadedFileName = "";
updateFileStatus();
emit framesUpdated(-1);
}
void MainWindow::normalizeTiming()
{
model->normalizeTiming();
emit framesUpdated(-2); //claim an all new set of frames because every frame was updated.
}
void MainWindow::changeBaudRates()
{
int Speed1 = 0, Speed2 = 0;
//Speed1 = ui->cbSpeed1->currentText().toInt();
//Speed2 = ui->cbSpeed2->currentText().toInt();
emit updateBaudRates(Speed1, Speed2);
}
void MainWindow::handleLoadFile()
{
QString filename;
QFileDialog dialog(this);
bool result = false;
QStringList filters;
filters.append(QString(tr("CRTD Logs (*.txt)")));
filters.append(QString(tr("GVRET Logs (*.csv)")));
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
filters.append(QString(tr("BusMaster Log (*.log)")));
filters.append(QString(tr("Microchip Log (*.can)")));
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
if (dialog.exec() == QDialog::Accepted)
{
filename = dialog.selectedFiles()[0];
ui->canFramesView->scrollToTop();
model->clearFrames();
QVector<CANFrame> tempFrames;
QProgressDialog progress(this);
progress.setWindowModality(Qt::WindowModal);
progress.setLabelText("Loading file...");
progress.setCancelButton(0);
progress.setRange(0,0);
progress.setMinimumDuration(0);
progress.show();
qApp->processEvents();
if (dialog.selectedNameFilter() == filters[0]) result = FrameFileIO::loadCRTDFile(filename, &tempFrames);
if (dialog.selectedNameFilter() == filters[1]) result = FrameFileIO::loadNativeCSVFile(filename, &tempFrames);
if (dialog.selectedNameFilter() == filters[2]) result = FrameFileIO::loadGenericCSVFile(filename, &tempFrames);
if (dialog.selectedNameFilter() == filters[3]) result = FrameFileIO::loadLogFile(filename, &tempFrames);
if (dialog.selectedNameFilter() == filters[4]) result = FrameFileIO::loadMicrochipFile(filename, &tempFrames);
progress.cancel();
if (result)
{
model->insertFrames(tempFrames);
QStringList fileList = filename.split('/');
loadedFileName = fileList[fileList.length() - 1];
model->recalcOverwrite();
ui->lbNumFrames->setText(QString::number(model->rowCount()));
if (ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom();
updateFileStatus();
emit framesUpdated(-2);
}
}
}
void MainWindow::handleSaveFile()
{
QString filename;
QFileDialog dialog(this);
bool result = false;
QStringList filters;
filters.append(QString(tr("CRTD Logs (*.txt)")));
filters.append(QString(tr("GVRET Logs (*.csv)")));
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
filters.append(QString(tr("BusMaster Log (*.log)")));
filters.append(QString(tr("Microchip Log (*.can)")));
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() == QDialog::Accepted)
{
const QVector<CANFrame> *frames = model->getListReference();
filename = dialog.selectedFiles()[0];
QProgressDialog progress(this);
progress.setWindowModality(Qt::WindowModal);
progress.setLabelText("Saving file...");
progress.setCancelButton(0);
progress.setRange(0,0);
progress.setMinimumDuration(0);
progress.show();
qApp->processEvents();
if (dialog.selectedNameFilter() == filters[0])
{
if (!filename.contains('.')) filename += ".txt";
result = FrameFileIO::saveCRTDFile(filename, frames);
}
if (dialog.selectedNameFilter() == filters[1])
{
if (!filename.contains('.')) filename += ".csv";
result = FrameFileIO::saveNativeCSVFile(filename, frames);
}
if (dialog.selectedNameFilter() == filters[2])
{
if (!filename.contains('.')) filename += ".csv";
result = FrameFileIO::saveGenericCSVFile(filename, frames);
}
if (dialog.selectedNameFilter() == filters[3])
{
if (!filename.contains('.')) filename += ".log";
result = FrameFileIO::saveLogFile(filename, frames);
}
if (dialog.selectedNameFilter() == filters[4])
{
if (!filename.contains('.')) filename += ".log";
result = FrameFileIO::saveMicrochipFile(filename, frames);
}
progress.cancel();
if (result)
{
QStringList fileList = filename.split('/');
loadedFileName = fileList[fileList.length() - 1];
updateFileStatus();
}
}
}
void MainWindow::handleSaveFilteredFile()
{
QString filename;
QFileDialog dialog(this);
bool result = false;
QStringList filters;
filters.append(QString(tr("CRTD Logs (*.txt)")));
filters.append(QString(tr("GVRET Logs (*.csv)")));
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
filters.append(QString(tr("BusMaster Log (*.log)")));
filters.append(QString(tr("Microchip Log (*.log)")));
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() == QDialog::Accepted)
{
const QVector<CANFrame> *frames = model->getFilteredListReference();
filename = dialog.selectedFiles()[0];
QProgressDialog progress(this);
progress.setWindowModality(Qt::WindowModal);
progress.setLabelText("Saving filtered file...");
progress.setCancelButton(0);
progress.setRange(0,0);
progress.setMinimumDuration(0);
progress.show();
qApp->processEvents();
if (dialog.selectedNameFilter() == filters[0])
{
if (!filename.contains('.')) filename += ".txt";
result = FrameFileIO::saveCRTDFile(filename, frames);
}
if (dialog.selectedNameFilter() == filters[1])
{
if (!filename.contains('.')) filename += ".csv";
result = FrameFileIO::saveNativeCSVFile(filename, frames);
}
if (dialog.selectedNameFilter() == filters[2])
{
if (!filename.contains('.')) filename += ".csv";
result = FrameFileIO::saveGenericCSVFile(filename, frames);
}
if (dialog.selectedNameFilter() == filters[3])
{
if (!filename.contains('.')) filename += ".log";
result = FrameFileIO::saveLogFile(filename, frames);
}
if (dialog.selectedNameFilter() == filters[4])
{
if (!filename.contains('.')) filename += ".log";
result = FrameFileIO::saveMicrochipFile(filename, frames);
}
progress.cancel();
if (result)
{
QStringList fileList = filename.split('/');
loadedFileName = fileList[fileList.length() - 1];
updateFileStatus();
}
}
}
void MainWindow::handleSaveFilters()
{
QString filename;
QFileDialog dialog(this);
QStringList filters;
filters.append(QString(tr("Filter list (*.ftl)")));
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() == QDialog::Accepted)
{
filename = dialog.selectedFiles()[0];
if (!filename.contains('.')) filename += ".ftl";
if (dialog.selectedNameFilter() == filters[0]) model->saveFilterFile(filename);
}
}
void MainWindow::handleLoadFilters()
{
QString filename;
QFileDialog dialog(this);
QStringList filters;
filters.append(QString(tr("Filter List (*.ftl)")));
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
if (dialog.exec() == QDialog::Accepted)
{
filename = dialog.selectedFiles()[0];
//right now there is only one file type that can be loaded here so just do it.
model->loadFilterFile(filename);
}
}
void MainWindow::handleLoadDBC()
{
QString filename;
QFileDialog dialog(this);
QStringList filters;
filters.append(QString(tr("DBC File (*.dbc)")));
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
if (dialog.exec() == QDialog::Accepted)
{
filename = dialog.selectedFiles()[0];
//right now there is only one file type that can be loaded here so just do it.
dbcHandler->loadDBCFile(filename);
//dbcHandler->listDebugging();
QStringList fileList = filename.split('/');
lbStatusDatabase.setText(fileList[fileList.length() - 1] + tr(" loaded."));
}
}
void MainWindow::handleSaveDBC()
{
QString filename;
QFileDialog dialog(this);
QStringList filters;
filters.append(QString(tr("DBC File (*.dbc)")));
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() == QDialog::Accepted)
{
filename = dialog.selectedFiles()[0];
if (!filename.contains('.')) filename += ".dbc";
dbcHandler->saveDBCFile(filename);
QStringList fileList = filename.split('/');
lbStatusDatabase.setText(fileList[fileList.length() - 1] + tr(" loaded."));
}
}
void MainWindow::handleSaveDecoded()
{
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];
if (!filename.contains('.')) filename += ".txt";
saveDecodedTextFile(filename);
}
}
void MainWindow::saveDecodedTextFile(QString filename)
{
QFile *outFile = new QFile(filename);
const QVector<CANFrame> *frames = model->getListReference();
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
return;
/*
Time: 205.173000 ID: 0x20E Std Bus: 0 Len: 8
Data Bytes: 88 10 00 13 BB 00 06 00
SignalName Value
*/
for (int c = 0; c < frames->count(); c++)
{
CANFrame thisFrame = frames->at(c);
QString builderString;
builderString += tr("Time: ") + QString::number((thisFrame.timestamp / 1000000.0), 'f', 6);
builderString += tr(" ID: ") + Utility::formatNumber(thisFrame.ID);
if (thisFrame.extended) builderString += tr(" Ext ");
else builderString += tr(" Std ");
builderString += tr("Bus: ") + QString::number(thisFrame.bus);
builderString += " Len: " + QString::number(thisFrame.len) + "\n";
outFile->write(builderString.toUtf8());
builderString = tr("Data Bytes: ");
for (int temp = 0; temp < thisFrame.len; temp++)
{
builderString += Utility::formatNumber(thisFrame.data[temp]) + " ";
}
builderString += "\n";
outFile->write(builderString.toUtf8());
builderString = "";
if (dbcHandler != NULL)
{
DBC_MESSAGE *msg = dbcHandler->findMsgByID(thisFrame.ID);
if (msg != NULL)
{
for (int j = 0; j < msg->msgSignals.length(); j++)
{
builderString.append("\t" + dbcHandler->processSignal(thisFrame, msg->msgSignals.at(j)));
builderString.append("\n");
}
}
builderString.append("\n");
outFile->write(builderString.toUtf8());
}
}
outFile->close();
}
void MainWindow::toggleCapture()
{
allowCapture = !allowCapture;
if (allowCapture)
{
ui->btnCaptureToggle->setText("Suspend Capturing");
emit startFrameCapturing();
}
else
{
ui->btnCaptureToggle->setText("Restart Capturing");
emit stopFrameCapturing();
}
}
void MainWindow::connectionSucceeded(int baud0, int baud1)
{
lbStatusConnected.setText(tr("Connected to GVRET"));
//finally, find the baud rate in the list of rates or
//add it to the bottom if needed (that'll be weird though...
/*
int idx = ui->cbSpeed1->findText(QString::number(baud0));
if (idx > -1) ui->cbSpeed1->setCurrentIndex(idx);
else
{
ui->cbSpeed1->addItem(QString::number(baud0));
ui->cbSpeed1->setCurrentIndex(ui->cbSpeed1->count() - 1);
}
idx = ui->cbSpeed2->findText(QString::number(baud1));
if (idx > -1) ui->cbSpeed2->setCurrentIndex(idx);
else
{
ui->cbSpeed2->addItem(QString::number(baud1));
ui->cbSpeed2->setCurrentIndex(ui->cbSpeed2->count() - 1);
}
*/
//ui->btnConnect->setEnabled(false);
ui->actionConnect->setText(tr("Disconnect"));
isConnected = true;
}
void MainWindow::connectionFailed()
{
lbStatusConnected.setText(tr("Failed to connect!"));
QMessageBox msgBox;
msgBox.setText("Connection to the GVRET firmware failed.\nYou might have an old version of GVRET\nor may have chosen the wrong serial port.");
msgBox.exec();
}
void MainWindow::updateFileStatus()
{
QString output;
if (model->rowCount() == 0)
{
output = tr("No file loaded");
}
else
{
if (loadedFileName.length() > 2)
{
output = loadedFileName + " loaded";
}
else
{
output = tr("No file loaded");
}
if (bDirty)
{
output += " (X)";
}
}
lbStatusFilename.setText(output);
}
void MainWindow::gotDeviceInfo(int build, int swCAN)
{
QString str = tr("Connected to GVRET ") + QString::number(build);
if (swCAN == 1) str += "(SW)";
lbStatusConnected.setText(str);
if (build < CURRENT_GVRET_VER)
{
QMessageBox msgBox;
msgBox.setText("It appears that you are not running\nan up-to-date version of GVRET\n\nYour version: "
+ QString::number(build) +"\nCurrent Version: " + QString::number(CURRENT_GVRET_VER)
+ "\n\nPlease upgrade your firmware version.\nOtherwise, you may experience difficulties.");
msgBox.exec();
}
}
void MainWindow::setTargettedID(int id)
{
worker->targetFrameID(id);
}
void MainWindow::showSettingsDialog()
{
if (!settingsDialog)
{
settingsDialog = new MainSettingsDialog();
connect(settingsDialog, SIGNAL(finished(int)), this, SLOT(updateSettings()));
}
settingsDialog->show();
}
//always gets unfiltered list. You ask for the graphs so there is no need to send filtered frames
void MainWindow::showGraphingWindow()
{
if (!graphingWindow) {
graphingWindow = new GraphingWindow(dbcHandler, model->getListReference());
connect(graphingWindow, SIGNAL(sendCenterTimeID(int32_t,double)), this, SLOT(gotCenterTimeID(int32_t,double)));
connect(this, SIGNAL(sendCenterTimeID(int32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
}
if (flowViewWindow) //connect the two external windows together
{
connect(graphingWindow, SIGNAL(sendCenterTimeID(int32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
connect(flowViewWindow, SIGNAL(sendCenterTimeID(int32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
}
graphingWindow->show();
}
void MainWindow::showFrameDataAnalysis()
{
//only create an instance of the object if we dont have one. Otherwise just display the existing one.
if (!frameInfoWindow)
{
if (!useFiltered)
frameInfoWindow = new FrameInfoWindow(model->getListReference());
else
frameInfoWindow = new FrameInfoWindow(model->getFilteredListReference());
}
frameInfoWindow->show();
}
void MainWindow::showFrameSenderWindow()
{
if (!frameSenderWindow)
{
if (!useFiltered)
frameSenderWindow = new FrameSenderWindow(model->getListReference());
else
frameSenderWindow = new FrameSenderWindow(model->getFilteredListReference());
connect(frameSenderWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int)));
}
frameSenderWindow->show();
}
void MainWindow::showPlaybackWindow()
{
if (!playbackWindow)
{
if (!useFiltered)
playbackWindow = new FramePlaybackWindow(model->getListReference(), worker);
else
playbackWindow = new FramePlaybackWindow(model->getFilteredListReference(), worker);
}
playbackWindow->show();
}
void MainWindow::showFirmwareUploaderWindow()
{
if (!firmwareUploaderWindow)
{
firmwareUploaderWindow = new FirmwareUploaderWindow(model->getListReference());
connect(firmwareUploaderWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int)));
connect(worker, SIGNAL(gotTargettedFrame(int)), firmwareUploaderWindow, SLOT(gotTargettedFrame(int)));
}
firmwareUploaderWindow->show();
}
void MainWindow::showComparisonWindow()
{
if (!comparatorWindow)
{
comparatorWindow = new FileComparatorWindow();
}
comparatorWindow->show();
}
void MainWindow::showSingleMultiWindow()
{
if (!discreteStateWindow)
{
discreteStateWindow = new DiscreteStateWindow(model->getListReference());
}
discreteStateWindow->show();
}
void MainWindow::showRangeWindow()
{
//not done yet
}
void MainWindow::showFuzzyScopeWindow()
{
//not done yet
}
void MainWindow::exitApp()
{
if (graphingWindow) graphingWindow->close();
if (frameInfoWindow) frameInfoWindow->close();
if (playbackWindow) playbackWindow->close();
if (flowViewWindow) flowViewWindow->close();
if (frameSenderWindow) frameSenderWindow->close();
if (dbcMainEditor) dbcMainEditor->close();
if (comparatorWindow) comparatorWindow->close();
if (connectionWindow) connectionWindow->close();
this->close();
}
void MainWindow::showFlowViewWindow()
{
if (!flowViewWindow)
{
if (!useFiltered)
flowViewWindow = new FlowViewWindow(model->getListReference());
else
flowViewWindow = new FlowViewWindow(model->getFilteredListReference());
connect(flowViewWindow, SIGNAL(sendCenterTimeID(int32_t,double)), this, SLOT(gotCenterTimeID(int32_t,double)));
connect(this, SIGNAL(sendCenterTimeID(int32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
}
if (graphingWindow)
{
connect(graphingWindow, SIGNAL(sendCenterTimeID(int32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(int32_t,double)));
connect(flowViewWindow, SIGNAL(sendCenterTimeID(int32_t,double)), graphingWindow, SLOT(gotCenterTimeID(int32_t,double)));
}
flowViewWindow->show();
}
//this one always gets the unfiltered list intentionally.
void MainWindow::showDBCEditor()
{
if (!dbcMainEditor)
{
dbcMainEditor = new DBCMainEditor(dbcHandler, model->getListReference());
}
dbcMainEditor->show();
}
void MainWindow::showConnectionSettingsWindow()
{
if (!connectionWindow)
{
connectionWindow = new ConnectionWindow();
connect(connectionWindow, SIGNAL(updateConnectionSettings(QString,QString,int,int)), this, SLOT(updateConnectionSettings(QString,QString,int,int)));
}
connectionWindow->show();
}