#include "mainwindow.h" #include "ui_mainwindow.h" #include "can_structs.h" #include #include #include #include "connections/canconmanager.h" #include "connections/connectionwindow.h" #include "helpwindow.h" #include "utility.h" /* Some notes on things I'd like to put into the program but haven't put on github (yet) Allow scripts to read/write signals from DBC files allow scripts to load DBC files in support of the script - maybe the graphing system too. */ 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); qRegisterMetaTypeStreamOperators>(); qRegisterMetaTypeStreamOperators>(); 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(this); // set parent to mainwindow to prevent canframemodel to change thread (might be done by setModel but just in case) QSortFilterProxyModel* proxyModel = new QSortFilterProxyModel; proxyModel->setSourceModel(model); ui->canFramesView->setModel(proxyModel); settingsDialog = new MainSettingsDialog(); //instantiate the settings dialog so it can initialize settings if this is the first run or the config file was deleted. settingsDialog->updateSettings(); //write out all the settings. If this is the first run it'll write defaults out. readSettings(); //QHeaderView *verticalHeader = ui->canFramesView->verticalHeader(); //verticalHeader->setSectionResizeMode(QHeaderView::Fixed); //verticalHeader->setDefaultSectionSize(10); QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader(); HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview connect(HorzHdr, SIGNAL(sectionClicked(int)), this, SLOT(headerClicked(int))); graphingWindow = nullptr; frameInfoWindow = nullptr; playbackWindow = nullptr; flowViewWindow = nullptr; frameSenderWindow = nullptr; dbcMainEditor = nullptr; comparatorWindow = nullptr; settingsDialog = nullptr; firmwareUploaderWindow = nullptr; discreteStateWindow = nullptr; connectionWindow = nullptr; scriptingWindow = nullptr; rangeWindow = nullptr; dbcFileWindow = nullptr; fuzzingWindow = nullptr; udsScanWindow = nullptr; motorctrlConfigWindow = nullptr; isoWindow = nullptr; snifferWindow = nullptr; bisectWindow = nullptr; signalViewerWindow = nullptr; temporalGraphWindow = nullptr; dbcHandler = DBCHandler::getReference(); bDirty = false; inhibitFilterUpdate = false; rxFrames = 0; framesPerSec = 0; continuousLogging = false; continuousLogFlushCounter = 0; connect(ui->actionSetup, SIGNAL(triggered(bool)), SLOT(showConnectionSettingsWindow())); connect(ui->actionOpen_Log_File, &QAction::triggered, this, &MainWindow::handleLoadFile); connect(ui->actionGraph_Dta, &QAction::triggered, this, &MainWindow::showGraphingWindow); connect(ui->actionFrame_Data_Analysis, &QAction::triggered, this, &MainWindow::showFrameDataAnalysis); connect(ui->btnClearFrames, &QAbstractButton::clicked, this, &MainWindow::clearFrames); connect(ui->actionSave_Log_File, &QAction::triggered, this, &MainWindow::handleSaveFile); connect(ui->actionSave_Filtered_Log_File, &QAction::triggered, this, &MainWindow::handleSaveFilteredFile); connect(ui->actionLoad_Filter_Definition, &QAction::triggered, this, &MainWindow::handleLoadFilters); connect(ui->actionSave_Filter_Definition, &QAction::triggered, this, &MainWindow::handleSaveFilters); connect(ui->action_Playback, &QAction::triggered, this, &MainWindow::showPlaybackWindow); connect(ui->actionFlow_View, &QAction::triggered, this, &MainWindow::showFlowViewWindow); connect(ui->action_Custom, &QAction::triggered, this, &MainWindow::showFrameSenderWindow); connect(ui->canFramesView, &QAbstractItemView::pressed, this, &MainWindow::gridClicked); connect(ui->canFramesView, &QAbstractItemView::doubleClicked, this, &MainWindow::gridDoubleClicked); connect(ui->cbInterpret, &QAbstractButton::toggled, this, &MainWindow::interpretToggled); connect(ui->cbOverwrite, &QAbstractButton::toggled, this, &MainWindow::overwriteToggled); connect(ui->btnCaptureToggle, &QAbstractButton::clicked, this, &MainWindow::toggleCapture); connect(ui->actionExit_Application, &QAction::triggered, this, &MainWindow::exitApp); connect(ui->actionFuzzy_Scope, &QAction::triggered, this, &MainWindow::showFuzzyScopeWindow); connect(ui->actionRange_State_2, &QAction::triggered, this, &MainWindow::showRangeWindow); connect(ui->actionSave_Decoded_Frames, &QAction::triggered, this, &MainWindow::handleSaveDecoded); connect(ui->actionSingle_Multi_State_2, &QAction::triggered, this, &MainWindow::showSingleMultiWindow); connect(ui->actionFile_Comparison, &QAction::triggered, this, &MainWindow::showComparisonWindow); connect(ui->actionScripting_INterface, &QAction::triggered, this, &MainWindow::showScriptingWindow); connect(ui->btnNormalize, &QAbstractButton::clicked, this, &MainWindow::normalizeTiming); connect(ui->actionPreferences, &QAction::triggered, this, &MainWindow::showSettingsDialog); connect(model, &CANFrameModel::updatedFiltersList, this, &MainWindow::updateFilterList); connect(ui->listFilters, &QListWidget::itemChanged, this, &MainWindow::filterListItemChanged); connect(ui->btnFilterAll, &QAbstractButton::clicked, this, &MainWindow::filterSetAll); connect(ui->btnFilterNone, &QAbstractButton::clicked, this, &MainWindow::filterClearAll); connect(ui->actionFirmware_Update, &QAction::triggered, this, &MainWindow::showFirmwareUploaderWindow); connect(ui->actionDBC_File_Manager, &QAction::triggered, this, &MainWindow::showDBCFileWindow); connect(ui->actionFuzzing, &QAction::triggered, this, &MainWindow::showFuzzingWindow); connect(ui->actionUDS_Scanner, &QAction::triggered, this, &MainWindow::showUDSScanWindow); connect(ui->actionISO_TP_Decoder, &QAction::triggered, this, &MainWindow::showISOInterpreterWindow); connect(ui->actionSniffer, &QAction::triggered, this, &MainWindow::showSnifferWindow); connect(ui->actionMotorControlConfig, &QAction::triggered, this, &MainWindow::showMCConfigWindow); connect(ui->actionCapture_Bisector, &QAction::triggered, this, &MainWindow::showBisectWindow); connect(ui->actionSignal_Viewer, &QAction::triggered, this, &MainWindow::showSignalViewer); connect(ui->actionSave_Continuous_Logfile, &QAction::triggered, this, &MainWindow::handleContinousLogging); connect(ui->actionTemporal_Graph, &QAction::triggered, this, &MainWindow::showTemporalGraphWindow); connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames); lbStatusConnected.setText(tr("Connected to 0 buses")); updateFileStatus(); //lbStatusDatabase.setText(tr("No DBC database loaded")); ui->statusBar->addWidget(&lbStatusConnected); ui->statusBar->addWidget(&lbStatusFilename); //ui->statusBar->addWidget(&lbStatusDatabase); ui->lblRemoteConn->setVisible(false); ui->lineRemoteKey->setVisible(false); ui->lbFPS->setText("0"); ui->lbNumFrames->setText("0"); connect(&updateTimer, &QTimer::timeout, this, &MainWindow::tickGUIUpdate); updateTimer.setInterval(250); updateTimer.start(); elapsedTime = new QTime; elapsedTime->start(); 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; temp.extended = false; temp.isReceived = true; temp.remote = false; temp.timestamp = 100000000; model->addFrame(temp, true); qApp->processEvents(); tickGUIUpdate(); //force a GUI refresh so that the row exists to measure normalRowHeight = ui->canFramesView->rowHeight(0); if (normalRowHeight == 0) normalRowHeight = 30; //should not be necessary but provides a sane number if something stupid happened. qDebug() << "normal row height = " << normalRowHeight; model->clearFrames(); //connect(CANConManager::getInstance(), CANConManager::connectionStatusUpdated, this, MainWindow::connectionStatusUpdated); connect(CANConManager::getInstance(), SIGNAL(connectionStatusUpdated(int)), this, SLOT(connectionStatusUpdated(int))); //Automatically create the connection window so it can be updated even if we never opened it. connectionWindow = new ConnectionWindow(); connect(this, SIGNAL(suspendCapturing(bool)), connectionWindow, SLOT(setSuspendAll(bool))); //these either are unfinished/not working or are not for general use. But,they exist //so if you want to enable them and play with them then go for it. ui->actionFirmware_Update->setVisible(false); ui->actionMotorControlConfig->setVisible(false); ui->actionSingle_Multi_State_2->setVisible(false); installEventFilter(this); } MainWindow::~MainWindow() { updateTimer.stop(); killEmAll(); //Ride the lightning delete ui; delete model; delete elapsedTime; delete dbcHandler; } //kill every sub window that could be open. At the moment a hard coded list //but eventually each window should be registered and be able to be iterated. void MainWindow::killEmAll() { killWindow(graphingWindow); killWindow(frameInfoWindow); killWindow(playbackWindow); killWindow(flowViewWindow); killWindow(frameSenderWindow); killWindow(comparatorWindow); killWindow(dbcMainEditor); killWindow(settingsDialog); killWindow(discreteStateWindow); killWindow(scriptingWindow); killWindow(rangeWindow); killWindow(dbcFileWindow); killWindow(fuzzingWindow); killWindow(udsScanWindow); killWindow(isoWindow); killWindow(snifferWindow); killWindow(bisectWindow); killWindow(firmwareUploaderWindow); killWindow(motorctrlConfigWindow); killWindow(signalViewerWindow); killWindow(connectionWindow); killWindow(temporalGraphWindow); } //forcefully close the window, kill it, and salt the earth //note, for some stupid reason this function causes a seg fault //it seems that when it runs just before the program closes it'll //fault out when trying to close the connection window. I assume //this could be because that window has long running threads open and doesn't //close quickly or maybe cleanly. Investigate. void MainWindow::killWindow(QDialog *win) { if (win) { win->close(); delete win; win = NULL; } } void MainWindow::exitApp() { this->close(); QApplication::quit(); //forces the whole application to terminate when the main window is closed } void MainWindow::closeEvent(QCloseEvent *event) { Q_UNUSED(event); removeEventFilter(this); writeSettings(); exitApp(); } bool MainWindow::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("mainscreen.html"); return true; break; } return false; } else { // standard event processing return QObject::eventFilter(obj, event); } return false; } 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()); ui->canFramesView->setColumnWidth(0, settings.value("Main/TimeColumn", 150).toUInt()); //time stamp ui->canFramesView->setColumnWidth(1, settings.value("Main/IDColumn", 70).toUInt()); //frame ID ui->canFramesView->setColumnWidth(2, settings.value("Main/ExtColumn", 40).toUInt()); //extended ui->canFramesView->setColumnWidth(3, settings.value("Main/RemColumn", 40).toUInt()); //remote ui->canFramesView->setColumnWidth(4, settings.value("Main/DirColumn", 40).toUInt()); //direction ui->canFramesView->setColumnWidth(5, settings.value("Main/BusColumn", 40).toUInt()); //bus ui->canFramesView->setColumnWidth(6, settings.value("Main/LengthColumn", 40).toUInt()); //length ui->canFramesView->setColumnWidth(7, settings.value("Main/AsciiColumn", 50).toUInt()); //ascii //ui->canFramesView->setColumnWidth(8, settings.value("Main/DataColumn", 225).toUInt()); //data } if (settings.value("Main/AutoScroll", false).toBool()) { ui->cbAutoScroll->setChecked(true); } int fontSize = settings.value("Main/FontSize", 9).toUInt(); QFont newFont = QFont(ui->canFramesView->font()); newFont.setPointSize(fontSize); ui->canFramesView->setFont(newFont); 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); useSystemClock = settings.value("Main/TimeClock", false).toBool(); model->setSysTimeMode(useSystemClock); useFiltered = settings.value("Main/UseFiltered", false).toBool(); model->setTimeFormat(settings.value("Main/TimeFormat", "MMM-dd HH:mm:ss.zzz").toString()); } void MainWindow::writeSettings() { QSettings settings; if (settings.value("Main/SaveRestorePositions", false).toBool()) { settings.setValue("Main/WindowSize", size()); settings.setValue("Main/WindowPos", pos()); settings.setValue("Main/TimeColumn", ui->canFramesView->columnWidth(0)); settings.setValue("Main/IDColumn", ui->canFramesView->columnWidth(1)); settings.setValue("Main/ExtColumn", ui->canFramesView->columnWidth(2)); settings.setValue("Main/RemColumn", ui->canFramesView->columnWidth(3)); settings.setValue("Main/DirColumn", ui->canFramesView->columnWidth(4)); settings.setValue("Main/BusColumn", ui->canFramesView->columnWidth(5)); settings.setValue("Main/LengthColumn", ui->canFramesView->columnWidth(6)); settings.setValue("Main/AsciiColumn", ui->canFramesView->columnWidth(7)); //settings.setValue("Main/DataColumn", ui->canFramesView->columnWidth(8)); } } void MainWindow::updateConnectionSettings(QString connectionType, QString port, int speed0, int speed1) { Q_UNUSED(connectionType); Q_UNUSED(port); Q_UNUSED(speed0); Q_UNUSED(speed1); //connType = connectionType; //portName = port; //canSpeed0 = speed0; //canSpeed1 = speed1; if (isConnected) { //emit updateBaudRates(speed0, speed1); } } void MainWindow::headerClicked(int logicalIndex) { //ui->canFramesView->sortByColumn(logicalIndex); model->sortByColumn(logicalIndex); } void MainWindow::gridClicked(QModelIndex idx) { //qDebug() << "Grid Clicked"; if (ui->canFramesView->rowHeight(idx.row()) > normalRowHeight) { ui->canFramesView->setRowHeight(idx.row(), normalRowHeight); } else { ui->canFramesView->resizeRowToContents(idx.row()); } } void MainWindow::gridDoubleClicked(QModelIndex idx) { //qDebug() << "Grid double clicked"; //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); //ui->canFramesView->resizeRowsToContents(); //a VERY costly operation! } void MainWindow::overwriteToggled(bool state) { if (state) { QMessageBox::StandardButton confirmDialog; confirmDialog = QMessageBox::question(this, "Danger Will Robinson", "Enabling Overwrite mode will\ndelete your captured frames\nand replace them with one\nframe per ID.\n\nAre you ready to do that?", QMessageBox::Yes|QMessageBox::No); if (confirmDialog == QMessageBox::Yes) { model->setOverwriteMode(true); } else ui->cbOverwrite->setCheckState(Qt::Unchecked); } else { model->setOverwriteMode(false); } } void MainWindow::updateFilterList() { if (model == NULL) return; const QMap *filters = model->getFiltersReference(); if (filters == NULL) return; qDebug() << "updateFilterList called on MainWindow"; ui->listFilters->clear(); if (filters->isEmpty()) return; QMap::const_iterator filterIter; for (filterIter = filters->begin(); filterIter != filters->end(); ++filterIter) { QListWidgetItem *thisItem = new QListWidgetItem(); thisItem->setText(Utility::formatCANID(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); } void MainWindow::tickGUIUpdate() { rxFrames = model->sendBulkRefresh(); //if(rxFrames>0) //{ int elapsed = elapsedTime->elapsed(); if(elapsed) { framesPerSec = (framesPerSec + (rxFrames * 1000 / elapsed)) / 2; elapsedTime->restart(); } else framesPerSec = 0; ui->lbNumFrames->setText(QString::number(model->rowCount())); if (rxFrames > 0 && /*allowCapture && */ ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom(); ui->lbFPS->setText(QString::number(framesPerSec)); if (rxFrames > 0) { bDirty = true; emit framesUpdated(rxFrames); //anyone care that frames were updated? } if (model->needsFilterRefresh()) updateFilterList(); if (continuousLogging) { const QVector *modelFrames = model->getListReference(); FrameFileIO::writeContinuousNative(modelFrames, modelFrames->count() - rxFrames); continuousLogFlushCounter++; if ((continuousLogFlushCounter % 3) == 0) { if (ui->lblContMsg->text().length() > 2) { ui->lblContMsg->setText(""); } else { ui->lblContMsg->setText("CONTINUOUS LOGGING"); } } if (continuousLogFlushCounter > 8) { continuousLogFlushCounter = 0; FrameFileIO::flushContinuousNative(); } } rxFrames = 0; //} } void MainWindow::gotFrames(int framesSinceLastUpdate) { rxFrames += framesSinceLastUpdate; emit frameUpdateRapid(framesSinceLastUpdate); } 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(); CANConManager::getInstance()->resetTimeBasis(); 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::handleLoadFile() { QString filename; QVector tempFrames; QMessageBox::StandardButton confirmDialog; bool loadResult = FrameFileIO::loadFrameFile(filename, &tempFrames); if (!loadResult) { confirmDialog = QMessageBox::question(this, "Error Loading", "Do you want to salvage what could be loaded?", QMessageBox::Yes|QMessageBox::No); if (confirmDialog == QMessageBox::Yes) { loadResult = true; } } if (loadResult) { ui->canFramesView->scrollToTop(); model->clearFrames(); model->insertFrames(tempFrames); loadedFileName = filename; model->recalcOverwrite(); ui->lbNumFrames->setText(QString::number(model->rowCount())); if (ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom(); updateFileStatus(); emit framesUpdated(-1); } } void MainWindow::handleSaveFile() { QString filename; if (FrameFileIO::saveFrameFile(filename, model->getListReference())) { loadedFileName = filename; updateFileStatus(); } } void MainWindow::handleContinousLogging() { continuousLogging = !continuousLogging; if (continuousLogging) { ui->actionSave_Continuous_Logfile->setText(tr("Cease Continuous Logging")); FrameFileIO::openContinuousNative(); } else { ui->actionSave_Continuous_Logfile->setText(tr("Start Continuous Logging")); ui->lblContMsg->setText(""); FrameFileIO::closeContinuousNative(); } } void MainWindow::handleSaveFilteredFile() { QString filename; if (FrameFileIO::saveFrameFile(filename, model->getFilteredListReference())) { loadedFileName = filename; 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); } } //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 *frames = model->getFilteredListReference(); 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::formatCANID(thisFrame.ID, thisFrame.extended); 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 (unsigned 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->findMessage(thisFrame); if (msg != NULL) { for (int j = 0; j < msg->sigHandler->getCount(); j++) { QString temp; if (msg->sigHandler->findSignalByIdx(j)->processAsText(thisFrame, temp)) { builderString.append("\t" + temp); builderString.append("\n"); } } } builderString.append("\n"); outFile->write(builderString.toUtf8()); } } outFile->close(); } void MainWindow::toggleCapture() { allowCapture = !allowCapture; if (allowCapture) ui->btnCaptureToggle->setText("Suspend Capturing"); else ui->btnCaptureToggle->setText("Restart Capturing"); emit suspendCapturing(!allowCapture); } void MainWindow::connectionStatusUpdated(int conns) { lbStatusConnected.setText(tr("Connected to ") + QString::number(conns) + tr(" buses")); } 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); } CANFrameModel* MainWindow::getCANFrameModel() { return model; } void MainWindow::showSettingsDialog() { if (!settingsDialog) { settingsDialog = new MainSettingsDialog(); connect (settingsDialog, SIGNAL(updatedSettings()), this, SLOT(readUpdateableSettings())); } 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(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::showTemporalGraphWindow() { //only create an instance of the object if we dont have one. Otherwise just display the existing one. if (!temporalGraphWindow) { if (!useFiltered) temporalGraphWindow = new TemporalGraphWindow(model->getListReference()); else temporalGraphWindow = new TemporalGraphWindow(model->getFilteredListReference()); } temporalGraphWindow->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::showISOInterpreterWindow() { if (!isoWindow) { if (!useFiltered) isoWindow = new ISOTP_InterpreterWindow(model->getListReference()); else isoWindow = new ISOTP_InterpreterWindow(model->getFilteredListReference()); } isoWindow->show(); } void MainWindow::showSnifferWindow() { if (!snifferWindow) snifferWindow = new SnifferWindow(this); snifferWindow->show(); } void MainWindow::showBisectWindow() { if (!bisectWindow) { bisectWindow = new BisectWindow(model->getListReference()); } bisectWindow->show(); } void MainWindow::showFrameSenderWindow() { if (!frameSenderWindow) { if (!useFiltered) frameSenderWindow = new FrameSenderWindow(model->getListReference()); else frameSenderWindow = new FrameSenderWindow(model->getFilteredListReference()); } frameSenderWindow->show(); } void MainWindow::showPlaybackWindow() { if (!playbackWindow) { if (!useFiltered) playbackWindow = new FramePlaybackWindow(model->getListReference()); else playbackWindow = new FramePlaybackWindow(model->getFilteredListReference()); } playbackWindow->show(); } void MainWindow::showFirmwareUploaderWindow() { if (!firmwareUploaderWindow) { firmwareUploaderWindow = new FirmwareUploaderWindow(model->getListReference()); } 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::showFuzzingWindow() { if (!fuzzingWindow) { fuzzingWindow = new FuzzingWindow(model->getListReference()); } fuzzingWindow->show(); } void MainWindow::showMCConfigWindow() { if (!motorctrlConfigWindow) { motorctrlConfigWindow = new MotorControllerConfigWindow(model->getListReference()); //connect(motorctrlConfigWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int))); //connect(motorctrlConfigWindow, SIGNAL(sendFrameBatch(const QList*)), worker, SLOT(sendFrameBatch(const QList*))); } motorctrlConfigWindow->show(); } void MainWindow::showUDSScanWindow() { if (!udsScanWindow) { udsScanWindow = new UDSScanWindow(model->getListReference()); } udsScanWindow->show(); } void MainWindow::showScriptingWindow() { if (!scriptingWindow) { scriptingWindow = new ScriptingWindow(model->getListReference()); } scriptingWindow->show(); } void MainWindow::showRangeWindow() { if (!rangeWindow) { rangeWindow = new RangeStateWindow(model->getListReference()); } rangeWindow->show(); } void MainWindow::showFuzzyScopeWindow() { //not done yet } 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(); } void MainWindow::showDBCFileWindow() { if (!dbcFileWindow) { dbcFileWindow = new DBCLoadSaveWindow(model->getListReference()); } dbcFileWindow->show(); } void MainWindow::showSignalViewer() { if (!signalViewerWindow) { if (!useFiltered) signalViewerWindow = new SignalViewerWindow(model->getListReference()); else signalViewerWindow = new SignalViewerWindow(model->getFilteredListReference()); } signalViewerWindow->show(); } void MainWindow::showConnectionSettingsWindow() { if (!connectionWindow) { connectionWindow = new ConnectionWindow(); } connectionWindow->show(); }