| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -55,12 +55,9 @@ MainWindow::MainWindow() : QMainWindow() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  main_win = this; | 
					 | 
					 | 
					 | 
					  main_win = this; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  qInstallMessageHandler(qLogMessageHandler); | 
					 | 
					 | 
					 | 
					  qInstallMessageHandler(qLogMessageHandler); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (const QString &fn : {"./dbc/car_fingerprint_to_dbc.json", "./tools/cabana/dbc/car_fingerprint_to_dbc.json"}) { | 
					 | 
					 | 
					 | 
					  QFile json_file(QApplication::applicationDirPath() + "/dbc/car_fingerprint_to_dbc.json"); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QFile json_file(fn); | 
					 | 
					 | 
					 | 
					  if (json_file.open(QIODevice::ReadOnly)) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (json_file.open(QIODevice::ReadOnly)) { | 
					 | 
					 | 
					 | 
					    fingerprint_to_dbc = QJsonDocument::fromJson(json_file.readAll()); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      fingerprint_to_dbc = QJsonDocument::fromJson(json_file.readAll()); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  setStyleSheet(QString(R"(QMainWindow::separator { | 
					 | 
					 | 
					 | 
					  setStyleSheet(QString(R"(QMainWindow::separator { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -72,11 +69,10 @@ MainWindow::MainWindow() : QMainWindow() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(this, &MainWindow::updateProgressBar, this, &MainWindow::updateDownloadProgress); | 
					 | 
					 | 
					 | 
					  QObject::connect(this, &MainWindow::updateProgressBar, this, &MainWindow::updateDownloadProgress); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, center_widget, &CenterWidget::setMessage); | 
					 | 
					 | 
					 | 
					  QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, center_widget, &CenterWidget::setMessage); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts); | 
					 | 
					 | 
					 | 
					  QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(can, &AbstractStream::streamStarted, this, &MainWindow::loadDBCFromFingerprint); | 
					 | 
					 | 
					 | 
					  QObject::connect(can, &AbstractStream::streamStarted, this, &MainWindow::streamStarted); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(can, &AbstractStream::eventsMerged, this, &MainWindow::updateStatus); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &MainWindow::DBCFileChanged); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(can, &AbstractStream::sourcesUpdated, dbc(), &DBCManager::updateSources); | 
					 | 
					 | 
					 | 
					  QObject::connect(can, &AbstractStream::sourcesUpdated, dbc(), &DBCManager::updateSources); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(can, &AbstractStream::sourcesUpdated, this, &MainWindow::updateSources); | 
					 | 
					 | 
					 | 
					  QObject::connect(can, &AbstractStream::sourcesUpdated, this, &MainWindow::updateLoadSaveMenus); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &MainWindow::DBCFileChanged); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(UndoStack::instance(), &QUndoStack::cleanChanged, this, &MainWindow::undoStackCleanChanged); | 
					 | 
					 | 
					 | 
					  QObject::connect(UndoStack::instance(), &QUndoStack::cleanChanged, this, &MainWindow::undoStackCleanChanged); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &MainWindow::undoStackIndexChanged); | 
					 | 
					 | 
					 | 
					  QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &MainWindow::undoStackIndexChanged); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QObject::connect(&settings, &Settings::changed, this, &MainWindow::updateStatus); | 
					 | 
					 | 
					 | 
					  QObject::connect(&settings, &Settings::changed, this, &MainWindow::updateStatus); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -89,8 +85,8 @@ void MainWindow::createActions() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    file_menu->addSeparator(); | 
					 | 
					 | 
					 | 
					    file_menu->addSeparator(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  file_menu->addAction(tr("New DBC File"), this, &MainWindow::newFile)->setShortcuts(QKeySequence::New); | 
					 | 
					 | 
					 | 
					  file_menu->addAction(tr("New DBC File"), [this]() { newFile(); })->setShortcuts(QKeySequence::New); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  file_menu->addAction(tr("Open DBC File..."), this, &MainWindow::openFile)->setShortcuts(QKeySequence::Open); | 
					 | 
					 | 
					 | 
					  file_menu->addAction(tr("Open DBC File..."), [this]() { openFile(); })->setShortcuts(QKeySequence::Open); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  manage_dbcs_menu = file_menu->addMenu(tr("Manage &DBC Files")); | 
					 | 
					 | 
					 | 
					  manage_dbcs_menu = file_menu->addMenu(tr("Manage &DBC Files")); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -109,7 +105,8 @@ void MainWindow::createActions() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  auto dbc_names = allDBCNames(); | 
					 | 
					 | 
					 | 
					  auto dbc_names = allDBCNames(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  std::sort(dbc_names.begin(), dbc_names.end()); | 
					 | 
					 | 
					 | 
					  std::sort(dbc_names.begin(), dbc_names.end()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (const auto &name : dbc_names) { | 
					 | 
					 | 
					 | 
					  for (const auto &name : dbc_names) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    load_opendbc_menu->addAction(QString::fromStdString(name), this, &MainWindow::openOpendbcFile); | 
					 | 
					 | 
					 | 
					    QString dbc_name = QString::fromStdString(name); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    load_opendbc_menu->addAction(dbc_name, [=]() { loadDBCFromOpendbc(dbc_name); }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  file_menu->addAction(tr("Load DBC From Clipboard"), [=]() { loadFromClipboard(); }); | 
					 | 
					 | 
					 | 
					  file_menu->addAction(tr("Load DBC From Clipboard"), [=]() { loadFromClipboard(); }); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -139,10 +136,8 @@ void MainWindow::createActions() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  edit_menu->addSeparator(); | 
					 | 
					 | 
					 | 
					  edit_menu->addSeparator(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QMenu *commands_menu = edit_menu->addMenu(tr("Command &List")); | 
					 | 
					 | 
					 | 
					  QMenu *commands_menu = edit_menu->addMenu(tr("Command &List")); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  auto undo_view = new QUndoView(UndoStack::instance()); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  undo_view->setWindowTitle(tr("Command List")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QWidgetAction *commands_act = new QWidgetAction(this); | 
					 | 
					 | 
					 | 
					  QWidgetAction *commands_act = new QWidgetAction(this); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  commands_act->setDefaultWidget(undo_view); | 
					 | 
					 | 
					 | 
					  commands_act->setDefaultWidget(new QUndoView(UndoStack::instance())); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  commands_menu->addAction(commands_act); | 
					 | 
					 | 
					 | 
					  commands_menu->addAction(commands_act); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QMenu *tools_menu = menuBar()->addMenu(tr("&Tools")); | 
					 | 
					 | 
					 | 
					  QMenu *tools_menu = menuBar()->addMenu(tr("&Tools")); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -257,39 +252,24 @@ void MainWindow::openRoute() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::newFile() { | 
					 | 
					 | 
					 | 
					void MainWindow::newFile(SourceSet s) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
					 | 
					 | 
					 | 
					  closeFile(s); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->closeAll(); | 
					 | 
					 | 
					 | 
					  dbc()->open(s, "", ""); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->open(SOURCE_ALL, "", ""); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  updateLoadSaveMenus(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::openFile() { | 
					 | 
					 | 
					 | 
					void MainWindow::openFile(SourceSet s) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QString fn = QFileDialog::getOpenFileName(this, tr("Open File"), settings.last_dir, "DBC (*.dbc)"); | 
					 | 
					 | 
					 | 
					  QString fn = QFileDialog::getOpenFileName(this, tr("Open File"), settings.last_dir, "DBC (*.dbc)"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!fn.isEmpty()) { | 
					 | 
					 | 
					 | 
					  if (!fn.isEmpty()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    loadFile(fn); | 
					 | 
					 | 
					 | 
					    loadFile(fn, s); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::openFileForSource(SourceSet s) { | 
					 | 
					 | 
					 | 
					void MainWindow::loadFile(const QString &fn, SourceSet s) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QString fn = QFileDialog::getOpenFileName(this, tr("Open File"), settings.last_dir, "DBC (*.dbc)"); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!fn.isEmpty()) { | 
					 | 
					 | 
					 | 
					  if (!fn.isEmpty()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    loadFile(fn, s, false); | 
					 | 
					 | 
					 | 
					    closeFile(s); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::newFileForSource(SourceSet s) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->close(s); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->open(s, "", ""); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::loadFile(const QString &fn, SourceSet s, bool close_all) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!fn.isEmpty()) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QString dbc_fn = fn; | 
					 | 
					 | 
					 | 
					    QString dbc_fn = fn; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // Prompt user to load auto saved file if it exists.
 | 
					 | 
					 | 
					 | 
					    // Prompt user to load auto saved file if it exists.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (QFile::exists(fn + AUTO_SAVE_EXTENSION)) { | 
					 | 
					 | 
					 | 
					    if (QFile::exists(fn + AUTO_SAVE_EXTENSION)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      auto ret = QMessageBox::question(this, tr("Auto saved DBC found"), tr("Auto saved DBC file from previous session found. Do you want to load it instead?")); | 
					 | 
					 | 
					 | 
					      auto ret = QMessageBox::question(this, tr("Auto saved DBC found"), tr("Auto saved DBC file from previous session found. Do you want to load it instead?")); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -299,16 +279,8 @@ void MainWindow::loadFile(const QString &fn, SourceSet s, bool close_all) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      } | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    auto dbc_name = QFileInfo(fn).baseName(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QString error; | 
					 | 
					 | 
					 | 
					    QString error; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					    if (dbc()->open(s, dbc_fn, &error)) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (close_all) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      dbc()->closeAll(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    dbc()->close(s); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    bool ret = dbc()->open(s, dbc_fn, &error); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (ret) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      updateRecentFiles(fn); | 
					 | 
					 | 
					 | 
					      updateRecentFiles(fn); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      statusBar()->showMessage(tr("DBC File %1 loaded").arg(fn), 2000); | 
					 | 
					 | 
					 | 
					      statusBar()->showMessage(tr("DBC File %1 loaded").arg(fn), 2000); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } else { | 
					 | 
					 | 
					 | 
					    } else { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -316,79 +288,54 @@ void MainWindow::loadFile(const QString &fn, SourceSet s, bool close_all) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      msg_box.setDetailedText(error); | 
					 | 
					 | 
					 | 
					      msg_box.setDetailedText(error); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      msg_box.exec(); | 
					 | 
					 | 
					 | 
					      msg_box.exec(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    updateLoadSaveMenus(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::openOpendbcFile() { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (auto action = qobject_cast<QAction *>(sender())) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    remindSaveChanges(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    loadDBCFromOpendbc(action->text()); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::openRecentFile() { | 
					 | 
					 | 
					 | 
					void MainWindow::openRecentFile() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (auto action = qobject_cast<QAction *>(sender())) { | 
					 | 
					 | 
					 | 
					  if (auto action = qobject_cast<QAction *>(sender())) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    remindSaveChanges(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    loadFile(action->data().toString()); | 
					 | 
					 | 
					 | 
					    loadFile(action->data().toString()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::loadDBCFromOpendbc(const QString &name) { | 
					 | 
					 | 
					 | 
					void MainWindow::loadDBCFromOpendbc(const QString &name) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QString opendbc_file_path = QString("%1/%2.dbc").arg(OPENDBC_FILE_PATH, name); | 
					 | 
					 | 
					 | 
					  QString opendbc_file_path = QString("%1/%2.dbc").arg(OPENDBC_FILE_PATH, name); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					  loadFile(opendbc_file_path); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->closeAll(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->open(SOURCE_ALL, opendbc_file_path); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  updateLoadSaveMenus(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::loadFromClipboard(SourceSet s, bool close_all) { | 
					 | 
					 | 
					 | 
					void MainWindow::loadFromClipboard(SourceSet s, bool close_all) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
					 | 
					 | 
					 | 
					  closeFile(s); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QString dbc_str = QGuiApplication::clipboard()->text(); | 
					 | 
					 | 
					 | 
					  QString dbc_str = QGuiApplication::clipboard()->text(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QString error; | 
					 | 
					 | 
					 | 
					  QString error; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (close_all) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    dbc()->closeAll(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->close(s); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  bool ret = dbc()->open(s, "", dbc_str, &error); | 
					 | 
					 | 
					 | 
					  bool ret = dbc()->open(s, "", dbc_str, &error); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (ret && dbc()->msgCount() > 0) { | 
					 | 
					 | 
					 | 
					  if (ret && dbc()->msgCount() > 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QMessageBox::information(this, tr("Load From Clipboard"), tr("DBC Successfully Loaded!")); | 
					 | 
					 | 
					 | 
					    QMessageBox::information(this, tr("Load From Clipboard"), tr("DBC Successfully Loaded!")); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } else { | 
					 | 
					 | 
					 | 
					  } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QMessageBox msg_box(QMessageBox::Warning, tr("Failed to load DBC from clipboard"), tr("Make sure that you paste the text with correct format.")); | 
					 | 
					 | 
					 | 
					    QMessageBox msg_box(QMessageBox::Warning, tr("Failed to load DBC from clipboard"), tr("Make sure that you paste the text with correct format.")); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (!error.isEmpty()) { | 
					 | 
					 | 
					 | 
					    msg_box.setDetailedText(error); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      msg_box.setDetailedText(error); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    msg_box.exec(); | 
					 | 
					 | 
					 | 
					    msg_box.exec(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::loadDBCFromFingerprint() { | 
					 | 
					 | 
					 | 
					void MainWindow::streamStarted() { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Don't overwrite already loaded DBC
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (dbc()->msgCount()) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  auto fingerprint = can->carFingerprint(); | 
					 | 
					 | 
					 | 
					  auto fingerprint = can->carFingerprint(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (can->liveStreaming()) { | 
					 | 
					 | 
					 | 
					  if (can->liveStreaming()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    video_dock->setWindowTitle(can->routeName()); | 
					 | 
					 | 
					 | 
					    video_dock->setWindowTitle(can->routeName()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } else { | 
					 | 
					 | 
					 | 
					  } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    video_dock->setWindowTitle(tr("ROUTE: %1  FINGERPRINT: %2").arg(can->routeName()).arg(fingerprint.isEmpty() ? tr("Unknown Car") : fingerprint)); | 
					 | 
					 | 
					 | 
					    video_dock->setWindowTitle(tr("ROUTE: %1  FINGERPRINT: %2").arg(can->routeName()).arg(fingerprint.isEmpty() ? tr("Unknown Car") : fingerprint)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!fingerprint.isEmpty()) { | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    auto dbc_name = fingerprint_to_dbc[fingerprint]; | 
					 | 
					 | 
					 | 
					  // Don't overwrite already loaded DBC
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (dbc_name != QJsonValue::Undefined) { | 
					 | 
					 | 
					 | 
					  if (!dbc()->msgCount()) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      loadDBCFromOpendbc(dbc_name.toString()); | 
					 | 
					 | 
					 | 
					    if (!fingerprint.isEmpty()) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      return; | 
					 | 
					 | 
					 | 
					      auto dbc_name = fingerprint_to_dbc[fingerprint]; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (dbc_name != QJsonValue::Undefined) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        loadDBCFromOpendbc(dbc_name.toString()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newFile(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  newFile(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::save() { | 
					 | 
					 | 
					 | 
					void MainWindow::save() { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -407,7 +354,6 @@ void MainWindow::saveAs() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::autoSave() { | 
					 | 
					 | 
					 | 
					void MainWindow::autoSave() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!UndoStack::instance()->isClean()) { | 
					 | 
					 | 
					 | 
					  if (!UndoStack::instance()->isClean()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for (auto &[_, dbc_file] : dbc()->dbc_files) { | 
					 | 
					 | 
					 | 
					    for (auto &[_, dbc_file] : dbc()->dbc_files) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -424,12 +370,19 @@ void MainWindow::cleanupAutoSaveFile() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					void MainWindow::closeFile(SourceSet s) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (s == SOURCE_ALL) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    dbc()->closeAll(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    dbc()->close(s); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::closeFile(DBCFile *dbc_file) { | 
					 | 
					 | 
					 | 
					void MainWindow::closeFile(DBCFile *dbc_file) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  assert(dbc_file != nullptr); | 
					 | 
					 | 
					 | 
					  assert(dbc_file != nullptr); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
					 | 
					 | 
					 | 
					  remindSaveChanges(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->close(dbc_file); | 
					 | 
					 | 
					 | 
					  dbc()->close(dbc_file); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Ensure we always have at least one file open
 | 
					 | 
					 | 
					 | 
					  // Ensure we always have at least one file open
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (dbc()->dbcCount() == 0) { | 
					 | 
					 | 
					 | 
					  if (dbc()->dbcCount() == 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    newFile(); | 
					 | 
					 | 
					 | 
					    newFile(); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -438,43 +391,21 @@ void MainWindow::closeFile(DBCFile *dbc_file) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::saveFile(DBCFile *dbc_file) { | 
					 | 
					 | 
					 | 
					void MainWindow::saveFile(DBCFile *dbc_file) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  assert(dbc_file != nullptr); | 
					 | 
					 | 
					 | 
					  assert(dbc_file != nullptr); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  SourceSet s; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (auto &[s_, dbc_file_] : dbc()->dbc_files) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (dbc_file_ == dbc_file) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      s = s_; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!dbc_file->filename.isEmpty()) { | 
					 | 
					 | 
					 | 
					  if (!dbc_file->filename.isEmpty()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    dbc_file->save(); | 
					 | 
					 | 
					 | 
					    dbc_file->save(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    updateRecentFiles(dbc_file->filename); | 
					 | 
					 | 
					 | 
					    updateLoadSaveMenus(); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } else if (!dbc_file->isEmpty()) { | 
					 | 
					 | 
					 | 
					  } else if (!dbc_file->isEmpty()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QString fn = QFileDialog::getSaveFileName(this, tr("Save File (bus: %1)").arg(toString(s)), QDir::cleanPath(settings.last_dir + "/untitled.dbc"), tr("DBC (*.dbc)")); | 
					 | 
					 | 
					 | 
					    saveFileAs(dbc_file); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (!fn.isEmpty()) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      dbc_file->saveAs(fn); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      updateRecentFiles(fn); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  UndoStack::instance()->setClean(); | 
					 | 
					 | 
					 | 
					  UndoStack::instance()->setClean(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  statusBar()->showMessage(tr("File saved"), 2000); | 
					 | 
					 | 
					 | 
					  statusBar()->showMessage(tr("File saved"), 2000); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  updateLoadSaveMenus(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::saveFileAs(DBCFile *dbc_file) { | 
					 | 
					 | 
					 | 
					void MainWindow::saveFileAs(DBCFile *dbc_file) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  assert(dbc_file != nullptr); | 
					 | 
					 | 
					 | 
					  auto it = std::find_if(dbc()->dbc_files.begin(), dbc()->dbc_files.end(), [=](auto &f) { return f.second == dbc_file; }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					  assert(it != dbc()->dbc_files.end()); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  SourceSet s; | 
					 | 
					 | 
					 | 
					  QString title = tr("Save File (bus: %1)").arg(toString(it->first)); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (auto &[s_, dbc_file_] : dbc()->dbc_files) { | 
					 | 
					 | 
					 | 
					  QString fn = QFileDialog::getSaveFileName(this, title, QDir::cleanPath(settings.last_dir + "/untitled.dbc"), tr("DBC (*.dbc)")); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (dbc_file_ == dbc_file) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      s = s_; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QString fn = QFileDialog::getSaveFileName(this, tr("Save File (bus: %1)").arg(toString(s)), QDir::cleanPath(settings.last_dir + "/untitled.dbc"), tr("DBC (*.dbc)")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!fn.isEmpty()) { | 
					 | 
					 | 
					 | 
					  if (!fn.isEmpty()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    dbc_file->saveAs(fn); | 
					 | 
					 | 
					 | 
					    dbc_file->saveAs(fn); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    updateRecentFiles(fn); | 
					 | 
					 | 
					 | 
					    updateRecentFiles(fn); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -486,10 +417,8 @@ void MainWindow::removeBusFromFile(DBCFile *dbc_file, uint8_t source) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  assert(dbc_file != nullptr); | 
					 | 
					 | 
					 | 
					  assert(dbc_file != nullptr); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  SourceSet ss = {source, uint8_t(source + 128), uint8_t(source + 192)}; | 
					 | 
					 | 
					 | 
					  SourceSet ss = {source, uint8_t(source + 128), uint8_t(source + 192)}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  dbc()->removeSourcesFromFile(dbc_file, ss); | 
					 | 
					 | 
					 | 
					  dbc()->removeSourcesFromFile(dbc_file, ss); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  updateLoadSaveMenus(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::saveToClipboard() { | 
					 | 
					 | 
					 | 
					void MainWindow::saveToClipboard() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Copy all open DBC files to clipboard. Should not be called with more than 1 file open
 | 
					 | 
					 | 
					 | 
					  // Copy all open DBC files to clipboard. Should not be called with more than 1 file open
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (auto &[s, dbc_file] : dbc()->dbc_files) { | 
					 | 
					 | 
					 | 
					  for (auto &[s, dbc_file] : dbc()->dbc_files) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -504,28 +433,20 @@ void MainWindow::saveFileToClipboard(DBCFile *dbc_file) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QMessageBox::information(this, tr("Copy To Clipboard"), tr("DBC Successfully copied!")); | 
					 | 
					 | 
					 | 
					  QMessageBox::information(this, tr("Copy To Clipboard"), tr("DBC Successfully copied!")); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::updateSources(const SourceSet &s) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  sources = s; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  updateLoadSaveMenus(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::updateLoadSaveMenus() { | 
					 | 
					 | 
					 | 
					void MainWindow::updateLoadSaveMenus() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int cnt = dbc()->nonEmptyDBCCount(); | 
					 | 
					 | 
					 | 
					  int cnt = dbc()->nonEmptyDBCCount(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  save_dbc->setEnabled(cnt > 0); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (cnt > 1) { | 
					 | 
					 | 
					 | 
					  if (cnt > 1) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    save_dbc->setText(tr("Save %1 DBCs...").arg(dbc()->dbcCount())); | 
					 | 
					 | 
					 | 
					    save_dbc->setText(tr("Save %1 DBCs...").arg(dbc()->dbcCount())); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } else { | 
					 | 
					 | 
					 | 
					  } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    save_dbc->setText(tr("Save DBC...")); | 
					 | 
					 | 
					 | 
					    save_dbc->setText(tr("Save DBC...")); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					  save_dbc->setEnabled(cnt > 0); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  save_dbc_as->setEnabled(cnt == 1); | 
					 | 
					 | 
					 | 
					  save_dbc_as->setEnabled(cnt == 1); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // TODO: Support clipboard for multiple files
 | 
					 | 
					 | 
					 | 
					  // TODO: Support clipboard for multiple files
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  copy_dbc_to_clipboard->setEnabled(cnt == 1); | 
					 | 
					 | 
					 | 
					  copy_dbc_to_clipboard->setEnabled(cnt == 1); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					  QList<uint8_t> sources_sorted = can->sources.toList(); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QList<uint8_t> sources_sorted = sources.toList(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  std::sort(sources_sorted.begin(), sources_sorted.end()); | 
					 | 
					 | 
					 | 
					  std::sort(sources_sorted.begin(), sources_sorted.end()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  manage_dbcs_menu->clear(); | 
					 | 
					 | 
					 | 
					  manage_dbcs_menu->clear(); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -536,24 +457,9 @@ void MainWindow::updateLoadSaveMenus() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    SourceSet ss = {source, uint8_t(source + 128), uint8_t(source + 192)}; | 
					 | 
					 | 
					 | 
					    SourceSet ss = {source, uint8_t(source + 128), uint8_t(source + 192)}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QMenu *bus_menu = new QMenu(this); | 
					 | 
					 | 
					 | 
					    QMenu *bus_menu = new QMenu(this); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					    bus_menu->addAction(tr("New DBC File..."), [=]() { newFile(ss); }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // New
 | 
					 | 
					 | 
					 | 
					    bus_menu->addAction(tr("Open DBC File..."), [=]() { openFile(ss); }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QAction *new_action = new QAction(this); | 
					 | 
					 | 
					 | 
					    bus_menu->addAction(tr("Load DBC From Clipboard..."), [=]() { loadFromClipboard(ss, false); }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    new_action->setText(tr("New DBC File...")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QObject::connect(new_action, &QAction::triggered, [=]() { newFileForSource(ss); }); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    bus_menu->addAction(new_action); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // Open
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QAction *open_action = new QAction(this); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    open_action->setText(tr("Open DBC File...")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QObject::connect(open_action, &QAction::triggered, [=]() { openFileForSource(ss); }); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    bus_menu->addAction(open_action); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // Open
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QAction *load_clipboard_action = new QAction(this); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    load_clipboard_action->setText(tr("Load DBC From Clipboard...")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QObject::connect(load_clipboard_action, &QAction::triggered, [=]() { loadFromClipboard(ss, false); }); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    bus_menu->addAction(load_clipboard_action); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // Show sub-menu for each dbc for this source.
 | 
					 | 
					 | 
					 | 
					    // Show sub-menu for each dbc for this source.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QStringList bus_menu_fns; | 
					 | 
					 | 
					 | 
					    QStringList bus_menu_fns; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -563,46 +469,15 @@ void MainWindow::updateLoadSaveMenus() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        continue; | 
					 | 
					 | 
					 | 
					        continue; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      } | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QString fn = dbc_file->filename.isEmpty() ? "untitled" : QFileInfo(dbc_file->filename).baseName(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      // QMenu *manage_menu = bus_menu;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bus_menu->addSeparator(); | 
					 | 
					 | 
					 | 
					      bus_menu->addSeparator(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QAction *fn_action = new QAction(this); | 
					 | 
					 | 
					 | 
					      bus_menu->addAction(dbc_file->name() + " (" + toString(src) + ")")->setEnabled(false); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      fn_action->setText(fn + " (" + toString(src) + ")"); | 
					 | 
					 | 
					 | 
					      bus_menu->addAction(tr("Save..."), [=]() { saveFile(it.second); }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      fn_action->setEnabled(false); | 
					 | 
					 | 
					 | 
					      bus_menu->addAction(tr("Save As..."), [=]() { saveFileAs(it.second); }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bus_menu->addAction(fn_action); | 
					 | 
					 | 
					 | 
					      bus_menu->addAction(tr("Copy to Clipboard..."), [=]() { saveFileToClipboard(it.second); }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					      bus_menu->addAction(tr("Remove from this bus..."), [=]() { removeBusFromFile(it.second, source); }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      // Save
 | 
					 | 
					 | 
					 | 
					      bus_menu->addAction(tr("Remove from all buses..."), [=]() { closeFile(it.second); }); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QAction *save_action = new QAction(this); | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      save_action->setText(tr("Save...")); | 
					 | 
					 | 
					 | 
					      bus_menu_fns << dbc_file->name(); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bus_menu->addAction(save_action); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QObject::connect(save_action, &QAction::triggered, [=](){ saveFile(it.second); }); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      // Save as
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QAction *save_as_action = new QAction(this); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      save_as_action->setText(tr("Save As...")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bus_menu->addAction(save_as_action); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QObject::connect(save_as_action, &QAction::triggered, [=](){ saveFileAs(it.second); }); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      // Copy to clipboard
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QAction *save_clipboard_action = new QAction(this); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      save_clipboard_action->setText(tr("Copy to Clipboard...")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bus_menu->addAction(save_clipboard_action); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QObject::connect(save_clipboard_action, &QAction::triggered, [=](){ saveFileToClipboard(it.second); }); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      // Remove from this bus
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QAction *remove_action = new QAction(this); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      remove_action->setText(tr("Remove from this bus...")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bus_menu->addAction(remove_action); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QObject::connect(remove_action, &QAction::triggered, [=](){ removeBusFromFile(it.second, source); }); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      // Close/Remove from all buses
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QAction *close_action = new QAction(this); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      close_action->setText(tr("Remove from all buses...")); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bus_menu->addAction(close_action); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      QObject::connect(close_action, &QAction::triggered, [=](){ closeFile(it.second); }); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bus_menu_fns << fn; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    manage_dbcs_menu->addMenu(bus_menu); | 
					 | 
					 | 
					 | 
					    manage_dbcs_menu->addMenu(bus_menu); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -612,8 +487,7 @@ void MainWindow::updateLoadSaveMenus() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QStringList title; | 
					 | 
					 | 
					 | 
					  QStringList title; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (auto &[src, dbc_file] : dbc()->dbc_files) { | 
					 | 
					 | 
					 | 
					  for (auto &[src, dbc_file] : dbc()->dbc_files) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    QString fn = dbc_file->filename.isEmpty() ? "untitled" : QFileInfo(dbc_file->filename).baseName(); | 
					 | 
					 | 
					 | 
					    title.push_back(tr("(%1) %2").arg(toString(src), dbc_file->name())); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    title.push_back(tr("(%1) %2").arg(toString(src)).arg(fn)); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  setWindowFilePath(title.join(" | ")); | 
					 | 
					 | 
					 | 
					  setWindowFilePath(title.join(" | ")); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -646,9 +520,8 @@ void MainWindow::updateRecentFileActions() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void MainWindow::remindSaveChanges() { | 
					 | 
					 | 
					 | 
					void MainWindow::remindSaveChanges() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  bool discard_changes = false; | 
					 | 
					 | 
					 | 
					  bool discard_changes = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  while (!UndoStack::instance()->isClean() && !discard_changes) { | 
					 | 
					 | 
					 | 
					  while (!UndoStack::instance()->isClean() && !discard_changes) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    int ret = (QMessageBox::question(this, tr("Unsaved Changes"), | 
					 | 
					 | 
					 | 
					    QString text = tr("You have unsaved changes. Press ok to save them, cancel to discard."); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                     tr("You have unsaved changes. Press ok to save them, cancel to discard."), | 
					 | 
					 | 
					 | 
					    int ret = (QMessageBox::question(this, tr("Unsaved Changes"), text, QMessageBox::Ok | QMessageBox::Cancel)); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                     QMessageBox::Ok | QMessageBox::Cancel)); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (ret == QMessageBox::Ok) { | 
					 | 
					 | 
					 | 
					    if (ret == QMessageBox::Ok) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      save(); | 
					 | 
					 | 
					 | 
					      save(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } else { | 
					 | 
					 | 
					 | 
					    } else { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |