diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 9085bf310a..20edfd06ff 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -42,6 +42,21 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) { QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &BinaryView::refresh); addShortcuts(); + setWhatsThis(R"( + Binary View
+ + Shortcuts:
+ Delete Signal: + x , + Backspace , + Delete
+ Change endianness: e
+ Change singedness: s
+ Open chart: + c , + p , + g
+ )"); } void BinaryView::addShortcuts() { diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 9a085ec732..9c5ed097c6 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -94,6 +94,11 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { docking = !docking; updateToolBar(); }); + + setWhatsThis(tr(R"( + Chart view
+ + )")); } void ChartsWidget::eventsMerged() { diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index bf4c1e44f8..95ef975dd1 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -264,11 +264,12 @@ WelcomeWidget::WelcomeWidget(QWidget *parent) : QWidget(parent) { return hlayout; }; - auto lb = new QLabel(tr("<-Select a message to to view details")); + auto lb = new QLabel(tr("<-Select a message to view details")); lb->setAlignment(Qt::AlignHCenter); main_layout->addWidget(lb); main_layout->addLayout(newShortcutRow("Pause", "Space")); - main_layout->addLayout(newShortcutRow("Help", "Alt + H")); + main_layout->addLayout(newShortcutRow("Help", "F1")); + main_layout->addLayout(newShortcutRow("WhatsThis", "Shift+F1")); main_layout->addStretch(0); setStyleSheet("QLabel{color:darkGray;}"); diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index bce6d313c8..07d37df4e4 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -9,7 +9,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -20,7 +22,7 @@ static MainWindow *main_win = nullptr; void qLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { if (type == QtDebugMsg) std::cout << msg.toStdString() << std::endl; - if (main_win) emit main_win->showMessage(msg, 0); + if (main_win) emit main_win->showMessage(msg, 2000); } MainWindow::MainWindow() : QMainWindow() { @@ -43,7 +45,7 @@ MainWindow::MainWindow() : QMainWindow() { qRegisterMetaType("ReplyMsgType"); installMessageHandler([this](ReplyMsgType type, const std::string msg) { // use queued connection to recv the log messages from replay. - emit showMessage(QString::fromStdString(msg), 3000); + emit showMessage(QString::fromStdString(msg), 2000); }); installDownloadProgressHandler([this](uint64_t cur, uint64_t total, bool success) { emit updateProgressBar(cur, total, success); @@ -125,6 +127,7 @@ void MainWindow::createActions() { tools_menu->addAction(tr("Find &Similar Bits"), this, &MainWindow::findSimilarBits); QMenu *help_menu = menuBar()->addMenu(tr("&Help")); + help_menu->addAction(tr("Help"), this, &MainWindow::onlineHelp)->setShortcuts(QKeySequence::HelpContents); help_menu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); } @@ -173,6 +176,7 @@ void MainWindow::createStatusBar() { progress_bar->setTextVisible(true); progress_bar->setFixedSize({230, 16}); progress_bar->setVisible(false); + statusBar()->addWidget(new QLabel(tr("For Help,Press F1"))); statusBar()->addPermanentWidget(progress_bar); } @@ -422,3 +426,61 @@ void MainWindow::findSimilarBits() { QObject::connect(dlg, &FindSimilarBitsDlg::openMessage, messages_widget, &MessagesWidget::selectMessage); dlg->show(); } + +void MainWindow::onlineHelp() { + if (auto help = findChild()) { + help->close(); + } else { + help = new HelpOverlay(this); + help->setGeometry(rect()); + help->show(); + help->raise(); + } +} + +// HelpOverlay +HelpOverlay::HelpOverlay(MainWindow *parent) : QWidget(parent) { + setAttribute(Qt::WA_NoSystemBackground, true); + setAttribute(Qt::WA_TranslucentBackground, true); + setAttribute(Qt::WA_DeleteOnClose); + parent->installEventFilter(this); +} + +void HelpOverlay::paintEvent(QPaintEvent *event) { + QPainter painter(this); + painter.fillRect(rect(), QColor(0, 0, 0, 50)); + MainWindow *parent = (MainWindow *)parentWidget(); + drawHelpForWidget(painter, parent->findChild()); + drawHelpForWidget(painter, parent->findChild()); + drawHelpForWidget(painter, parent->findChild()); + drawHelpForWidget(painter, parent->findChild()); + drawHelpForWidget(painter, parent->findChild()); +} + +void HelpOverlay::drawHelpForWidget(QPainter &painter, QWidget *w) { + if (w && w->isVisible() && !w->whatsThis().isEmpty()) { + QPoint pt = mapFromGlobal(w->mapToGlobal(w->rect().center())); + if (rect().contains(pt)) { + QTextDocument document; + document.setHtml(w->whatsThis()); + QSize doc_size = document.size().toSize(); + QPoint topleft = {pt.x() - doc_size.width() / 2, pt.y() - doc_size.height() / 2}; + painter.translate(topleft); + painter.fillRect(QRect{{0, 0}, doc_size}, palette().toolTipBase()); + document.drawContents(&painter); + painter.translate(-topleft); + } + } +} + +bool HelpOverlay::eventFilter(QObject *obj, QEvent *event) { + if (obj == parentWidget() && event->type() == QEvent::Resize) { + QResizeEvent *resize_event = (QResizeEvent *)(event); + setGeometry(QRect{QPoint(0, 0), resize_event->size()}); + } + return false; +} + +void HelpOverlay::mouseReleaseEvent(QMouseEvent *event) { + close(); +} diff --git a/tools/cabana/mainwin.h b/tools/cabana/mainwin.h index 5e627df58b..e7a39adab7 100644 --- a/tools/cabana/mainwin.h +++ b/tools/cabana/mainwin.h @@ -54,6 +54,7 @@ protected: void setOption(); void findSimilarBits(); void undoStackCleanChanged(bool clean); + void onlineHelp(); VideoWidget *video_widget = nullptr; QDockWidget *video_dock; @@ -69,4 +70,17 @@ protected: enum { MAX_RECENT_FILES = 15 }; QAction *recent_files_acts[MAX_RECENT_FILES] = {}; QMenu *open_recent_menu = nullptr; + friend class OnlineHelp; +}; + +class HelpOverlay : public QWidget { + Q_OBJECT +public: + HelpOverlay(MainWindow *parent); + +protected: + void drawHelpForWidget(QPainter &painter, QWidget *w); + void paintEvent(QPaintEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + bool eventFilter(QObject *obj, QEvent *event) override; }; diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index 4f6bb92375..1cf85ed740 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -65,6 +65,15 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { }); updateSuppressedButtons(); + + setWhatsThis(tr(R"( + Message View
+ + Byte color:
+ constant changing
+ increasing
+ decreasing
+ )")); } void MessagesWidget::selectMessage(const MessageId &msg_id) { diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index 98dd39204f..e2be5c85d0 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -365,6 +365,11 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts), QObject::connect(model, &QAbstractItemModel::rowsInserted, this, &SignalView::rowsChanged); QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &SignalView::rowsChanged); QObject::connect(dbc(), &DBCManager::signalAdded, [this](uint32_t address, const Signal *sig) { expandSignal(sig); }); + + setWhatsThis(tr(R"( + Signal view
+ + )")); } void SignalView::setMessage(const MessageId &id) { diff --git a/tools/cabana/videowidget.cc b/tools/cabana/videowidget.cc index cd3dc0b516..f77f7c306d 100644 --- a/tools/cabana/videowidget.cc +++ b/tools/cabana/videowidget.cc @@ -53,6 +53,13 @@ VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent) { QObject::connect(can, &AbstractStream::paused, this, &VideoWidget::updatePlayBtnState); QObject::connect(can, &AbstractStream::resume, this, &VideoWidget::updatePlayBtnState); updatePlayBtnState(); + + setWhatsThis(tr(R"( + Video
+ + Shortcuts:
+ Pause/Resume: space
+ )")); } QWidget *VideoWidget::createCameraWidget() {