diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index 891bfc4bb1..2954824fd4 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -55,12 +55,9 @@ MainWindow::MainWindow() : QMainWindow() { main_win = this; qInstallMessageHandler(qLogMessageHandler); - for (const QString &fn : {"./dbc/car_fingerprint_to_dbc.json", "./tools/cabana/dbc/car_fingerprint_to_dbc.json"}) { - QFile json_file(fn); - if (json_file.open(QIODevice::ReadOnly)) { - fingerprint_to_dbc = QJsonDocument::fromJson(json_file.readAll()); - break; - } + QFile json_file(QApplication::applicationDirPath() + "/dbc/car_fingerprint_to_dbc.json"); + if (json_file.open(QIODevice::ReadOnly)) { + fingerprint_to_dbc = QJsonDocument::fromJson(json_file.readAll()); } setStyleSheet(QString(R"(QMainWindow::separator { @@ -72,11 +69,10 @@ MainWindow::MainWindow() : QMainWindow() { QObject::connect(this, &MainWindow::updateProgressBar, this, &MainWindow::updateDownloadProgress); QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, center_widget, &CenterWidget::setMessage); QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts); - QObject::connect(can, &AbstractStream::streamStarted, this, &MainWindow::loadDBCFromFingerprint); - QObject::connect(can, &AbstractStream::eventsMerged, this, &MainWindow::updateStatus); - QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &MainWindow::DBCFileChanged); + QObject::connect(can, &AbstractStream::streamStarted, this, &MainWindow::streamStarted); 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::indexChanged, this, &MainWindow::undoStackIndexChanged); QObject::connect(&settings, &Settings::changed, this, &MainWindow::updateStatus); @@ -89,8 +85,8 @@ void MainWindow::createActions() { file_menu->addSeparator(); } - file_menu->addAction(tr("New DBC File"), this, &MainWindow::newFile)->setShortcuts(QKeySequence::New); - file_menu->addAction(tr("Open DBC File..."), this, &MainWindow::openFile)->setShortcuts(QKeySequence::Open); + file_menu->addAction(tr("New DBC File"), [this]() { newFile(); })->setShortcuts(QKeySequence::New); + file_menu->addAction(tr("Open DBC File..."), [this]() { openFile(); })->setShortcuts(QKeySequence::Open); manage_dbcs_menu = file_menu->addMenu(tr("Manage &DBC Files")); @@ -109,7 +105,8 @@ void MainWindow::createActions() { auto dbc_names = allDBCNames(); std::sort(dbc_names.begin(), dbc_names.end()); 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(); }); @@ -139,10 +136,8 @@ void MainWindow::createActions() { edit_menu->addSeparator(); 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); - commands_act->setDefaultWidget(undo_view); + commands_act->setDefaultWidget(new QUndoView(UndoStack::instance())); commands_menu->addAction(commands_act); QMenu *tools_menu = menuBar()->addMenu(tr("&Tools")); @@ -257,39 +252,24 @@ void MainWindow::openRoute() { } } -void MainWindow::newFile() { - remindSaveChanges(); - dbc()->closeAll(); - dbc()->open(SOURCE_ALL, "", ""); - updateLoadSaveMenus(); +void MainWindow::newFile(SourceSet s) { + closeFile(s); + dbc()->open(s, "", ""); } -void MainWindow::openFile() { +void MainWindow::openFile(SourceSet s) { remindSaveChanges(); QString fn = QFileDialog::getOpenFileName(this, tr("Open File"), settings.last_dir, "DBC (*.dbc)"); if (!fn.isEmpty()) { - loadFile(fn); + loadFile(fn, s); } } -void MainWindow::openFileForSource(SourceSet s) { - QString fn = QFileDialog::getOpenFileName(this, tr("Open File"), settings.last_dir, "DBC (*.dbc)"); +void MainWindow::loadFile(const QString &fn, SourceSet s) { if (!fn.isEmpty()) { - loadFile(fn, s, false); - } -} - -void MainWindow::newFileForSource(SourceSet s) { - remindSaveChanges(); + closeFile(s); - dbc()->close(s); - dbc()->open(s, "", ""); -} - -void MainWindow::loadFile(const QString &fn, SourceSet s, bool close_all) { - if (!fn.isEmpty()) { QString dbc_fn = fn; - // Prompt user to load auto saved file if it exists. 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?")); @@ -299,16 +279,8 @@ void MainWindow::loadFile(const QString &fn, SourceSet s, bool close_all) { } } - auto dbc_name = QFileInfo(fn).baseName(); QString error; - - if (close_all) { - dbc()->closeAll(); - } - - dbc()->close(s); - bool ret = dbc()->open(s, dbc_fn, &error); - if (ret) { + if (dbc()->open(s, dbc_fn, &error)) { updateRecentFiles(fn); statusBar()->showMessage(tr("DBC File %1 loaded").arg(fn), 2000); } else { @@ -316,79 +288,54 @@ void MainWindow::loadFile(const QString &fn, SourceSet s, bool close_all) { msg_box.setDetailedText(error); msg_box.exec(); } - - updateLoadSaveMenus(); - } -} - -void MainWindow::openOpendbcFile() { - if (auto action = qobject_cast(sender())) { - remindSaveChanges(); - loadDBCFromOpendbc(action->text()); } } void MainWindow::openRecentFile() { if (auto action = qobject_cast(sender())) { - remindSaveChanges(); loadFile(action->data().toString()); } } void MainWindow::loadDBCFromOpendbc(const QString &name) { - remindSaveChanges(); - QString opendbc_file_path = QString("%1/%2.dbc").arg(OPENDBC_FILE_PATH, name); - - dbc()->closeAll(); - dbc()->open(SOURCE_ALL, opendbc_file_path); - - updateLoadSaveMenus(); + loadFile(opendbc_file_path); } void MainWindow::loadFromClipboard(SourceSet s, bool close_all) { - remindSaveChanges(); + closeFile(s); + QString dbc_str = QGuiApplication::clipboard()->text(); QString error; - - if (close_all) { - dbc()->closeAll(); - } - - dbc()->close(s); bool ret = dbc()->open(s, "", dbc_str, &error); if (ret && dbc()->msgCount() > 0) { QMessageBox::information(this, tr("Load From Clipboard"), tr("DBC Successfully Loaded!")); } else { 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(); } } -void MainWindow::loadDBCFromFingerprint() { - // Don't overwrite already loaded DBC - if (dbc()->msgCount()) { - return; - } - - remindSaveChanges(); +void MainWindow::streamStarted() { auto fingerprint = can->carFingerprint(); if (can->liveStreaming()) { video_dock->setWindowTitle(can->routeName()); } else { 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]; - if (dbc_name != QJsonValue::Undefined) { - loadDBCFromOpendbc(dbc_name.toString()); - return; + + // Don't overwrite already loaded DBC + if (!dbc()->msgCount()) { + if (!fingerprint.isEmpty()) { + auto dbc_name = fingerprint_to_dbc[fingerprint]; + if (dbc_name != QJsonValue::Undefined) { + loadDBCFromOpendbc(dbc_name.toString()); + return; + } } + newFile(); } - newFile(); } void MainWindow::save() { @@ -407,7 +354,6 @@ void MainWindow::saveAs() { } } - void MainWindow::autoSave() { if (!UndoStack::instance()->isClean()) { 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) { assert(dbc_file != nullptr); remindSaveChanges(); - dbc()->close(dbc_file); - // Ensure we always have at least one file open if (dbc()->dbcCount() == 0) { newFile(); @@ -438,43 +391,21 @@ void MainWindow::closeFile(DBCFile *dbc_file) { void MainWindow::saveFile(DBCFile *dbc_file) { 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()) { dbc_file->save(); - updateRecentFiles(dbc_file->filename); + updateLoadSaveMenus(); } 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)")); - if (!fn.isEmpty()) { - dbc_file->saveAs(fn); - updateRecentFiles(fn); - } + saveFileAs(dbc_file); } - UndoStack::instance()->setClean(); statusBar()->showMessage(tr("File saved"), 2000); - updateLoadSaveMenus(); } void MainWindow::saveFileAs(DBCFile *dbc_file) { - assert(dbc_file != nullptr); - - SourceSet s; - for (auto &[s_, dbc_file_] : dbc()->dbc_files) { - 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)")); + 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()); + QString title = tr("Save File (bus: %1)").arg(toString(it->first)); + QString fn = QFileDialog::getSaveFileName(this, title, QDir::cleanPath(settings.last_dir + "/untitled.dbc"), tr("DBC (*.dbc)")); if (!fn.isEmpty()) { dbc_file->saveAs(fn); updateRecentFiles(fn); @@ -486,10 +417,8 @@ void MainWindow::removeBusFromFile(DBCFile *dbc_file, uint8_t source) { assert(dbc_file != nullptr); SourceSet ss = {source, uint8_t(source + 128), uint8_t(source + 192)}; dbc()->removeSourcesFromFile(dbc_file, ss); - updateLoadSaveMenus(); } - void MainWindow::saveToClipboard() { // 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) { @@ -504,28 +433,20 @@ void MainWindow::saveFileToClipboard(DBCFile *dbc_file) { QMessageBox::information(this, tr("Copy To Clipboard"), tr("DBC Successfully copied!")); } -void MainWindow::updateSources(const SourceSet &s) { - sources = s; - updateLoadSaveMenus(); -} - void MainWindow::updateLoadSaveMenus() { int cnt = dbc()->nonEmptyDBCCount(); - save_dbc->setEnabled(cnt > 0); - if (cnt > 1) { save_dbc->setText(tr("Save %1 DBCs...").arg(dbc()->dbcCount())); } else { save_dbc->setText(tr("Save DBC...")); } - + save_dbc->setEnabled(cnt > 0); save_dbc_as->setEnabled(cnt == 1); // TODO: Support clipboard for multiple files copy_dbc_to_clipboard->setEnabled(cnt == 1); - - QList sources_sorted = sources.toList(); + QList sources_sorted = can->sources.toList(); std::sort(sources_sorted.begin(), sources_sorted.end()); manage_dbcs_menu->clear(); @@ -536,24 +457,9 @@ void MainWindow::updateLoadSaveMenus() { SourceSet ss = {source, uint8_t(source + 128), uint8_t(source + 192)}; QMenu *bus_menu = new QMenu(this); - - // New - QAction *new_action = new QAction(this); - 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); + bus_menu->addAction(tr("New DBC File..."), [=]() { newFile(ss); }); + bus_menu->addAction(tr("Open DBC File..."), [=]() { openFile(ss); }); + bus_menu->addAction(tr("Load DBC From Clipboard..."), [=]() { loadFromClipboard(ss, false); }); // Show sub-menu for each dbc for this source. QStringList bus_menu_fns; @@ -563,46 +469,15 @@ void MainWindow::updateLoadSaveMenus() { continue; } - QString fn = dbc_file->filename.isEmpty() ? "untitled" : QFileInfo(dbc_file->filename).baseName(); - // QMenu *manage_menu = bus_menu; - bus_menu->addSeparator(); - QAction *fn_action = new QAction(this); - fn_action->setText(fn + " (" + toString(src) + ")"); - fn_action->setEnabled(false); - bus_menu->addAction(fn_action); - - // Save - QAction *save_action = new QAction(this); - save_action->setText(tr("Save...")); - 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; + bus_menu->addAction(dbc_file->name() + " (" + toString(src) + ")")->setEnabled(false); + bus_menu->addAction(tr("Save..."), [=]() { saveFile(it.second); }); + bus_menu->addAction(tr("Save As..."), [=]() { saveFileAs(it.second); }); + bus_menu->addAction(tr("Copy to Clipboard..."), [=]() { saveFileToClipboard(it.second); }); + bus_menu->addAction(tr("Remove from this bus..."), [=]() { removeBusFromFile(it.second, source); }); + bus_menu->addAction(tr("Remove from all buses..."), [=]() { closeFile(it.second); }); + + bus_menu_fns << dbc_file->name(); } manage_dbcs_menu->addMenu(bus_menu); @@ -612,8 +487,7 @@ void MainWindow::updateLoadSaveMenus() { QStringList title; 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)).arg(fn)); + title.push_back(tr("(%1) %2").arg(toString(src), dbc_file->name())); } setWindowFilePath(title.join(" | ")); } @@ -646,9 +520,8 @@ void MainWindow::updateRecentFileActions() { void MainWindow::remindSaveChanges() { bool discard_changes = false; while (!UndoStack::instance()->isClean() && !discard_changes) { - int ret = (QMessageBox::question(this, tr("Unsaved Changes"), - tr("You have unsaved changes. Press ok to save them, cancel to discard."), - QMessageBox::Ok | QMessageBox::Cancel)); + QString text = 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)); if (ret == QMessageBox::Ok) { save(); } else { diff --git a/tools/cabana/mainwin.h b/tools/cabana/mainwin.h index 5e76d86e5c..0782c316bb 100644 --- a/tools/cabana/mainwin.h +++ b/tools/cabana/mainwin.h @@ -21,20 +21,18 @@ public: MainWindow(); void dockCharts(bool dock); void showStatusMessage(const QString &msg, int timeout = 0) { statusBar()->showMessage(msg, timeout); } - void loadFile(const QString &fn, SourceSet s = SOURCE_ALL, bool close_all = true); + void loadFile(const QString &fn, SourceSet s = SOURCE_ALL); public slots: void openRoute(); - void newFile(); - void openFile(); + void newFile(SourceSet s = SOURCE_ALL); + void openFile(SourceSet s = SOURCE_ALL); void openRecentFile(); - void openOpendbcFile(); void loadDBCFromOpendbc(const QString &name); - void loadDBCFromFingerprint(); + void streamStarted(); void save(); void saveAs(); void saveToClipboard(); - void updateSources(const SourceSet &s); signals: void showMessage(const QString &msg, int timeout); @@ -42,14 +40,13 @@ signals: protected: void remindSaveChanges(); + void closeFile(SourceSet s = SOURCE_ALL); void closeFile(DBCFile *dbc_file); void saveFile(DBCFile *dbc_file); void saveFileAs(DBCFile *dbc_file); void saveFileToClipboard(DBCFile *dbc_file); void removeBusFromFile(DBCFile *dbc_file, uint8_t source); void loadFromClipboard(SourceSet s = SOURCE_ALL, bool close_all = true); - void openFileForSource(SourceSet s); - void newFileForSource(SourceSet s); void autoSave(); void cleanupAutoSaveFile(); void updateRecentFiles(const QString &fn); @@ -90,7 +87,6 @@ protected: QAction *copy_dbc_to_clipboard = nullptr; int prev_undostack_index = 0; int prev_undostack_count = 0; - SourceSet sources; friend class OnlineHelp; };