Cabana: make all panels dockable into each other (#26838)

old-commit-hash: 7ae8792386
beeps
Dean Lee 3 years ago committed by GitHub
parent 6ccaa89961
commit 7f783e79d5
  1. 4
      tools/cabana/cabana.cc
  2. 4
      tools/cabana/chartswidget.cc
  3. 100
      tools/cabana/mainwin.cc
  4. 6
      tools/cabana/mainwin.h
  5. 6
      tools/cabana/settings.cc
  6. 2
      tools/cabana/settings.h
  7. 13
      tools/cabana/videowidget.cc
  8. 2
      tools/cabana/videowidget.h

@ -6,6 +6,8 @@
#include "tools/cabana/mainwin.h"
int main(int argc, char *argv[]) {
QCoreApplication::setApplicationName("Cabana");
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
initApp(argc, argv);
QApplication app(argc, argv);
@ -36,7 +38,7 @@ int main(int argc, char *argv[]) {
int ret = 0;
if (p.loadRoute(route, cmd_parser.value("data_dir"), replay_flags)) {
MainWindow w;
w.showMaximized();
w.show();
ret = app.exec();
}
return ret;

@ -1,5 +1,6 @@
#include "tools/cabana/chartswidget.h"
#include <QApplication>
#include <QCompleter>
#include <QLineEdit>
#include <QFutureSynchronizer>
@ -42,7 +43,8 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
main_layout->addWidget(charts_scroll);
max_chart_range = settings.max_chart_x_range;
use_dark_theme = palette().color(QPalette::WindowText).value() > palette().color(QPalette::Background).value();
use_dark_theme = QApplication::style()->standardPalette().color(QPalette::WindowText).value() >
QApplication::style()->standardPalette().color(QPalette::Background).value();
updateToolBar();
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &ChartsWidget::removeAll);

@ -1,19 +1,16 @@
#include "tools/cabana/mainwin.h"
#include <iostream>
#include <QApplication>
#include <QClipboard>
#include <QCompleter>
#include <QDesktopWidget>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QHBoxLayout>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QShortcut>
#include <QScreen>
#include <QToolBar>
#include <QUndoView>
#include <QVBoxLayout>
#include <QWidgetAction>
@ -25,58 +22,20 @@ void qLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const
}
MainWindow::MainWindow() : QMainWindow() {
setWindowTitle("Cabana");
QWidget *central_widget = new QWidget(this);
QHBoxLayout *main_layout = new QHBoxLayout(central_widget);
main_layout->setContentsMargins(11, 11, 11, 0);
main_layout->setSpacing(0);
splitter = new QSplitter(Qt::Horizontal, this);
splitter->setHandleWidth(11);
QWidget *messages_container = new QWidget(this);
QVBoxLayout *messages_layout = new QVBoxLayout(messages_container);
messages_layout->setContentsMargins(0, 0, 0, 0);
// left panel
dbc_combo = createDBCSelector();
messages_layout->addWidget(dbc_combo);
messages_widget = new MessagesWidget(this);
messages_layout->addWidget(messages_widget);
splitter->addWidget(messages_container);
charts_widget = new ChartsWidget(this);
createDockWindows();
detail_widget = new DetailWidget(charts_widget, this);
splitter->addWidget(detail_widget);
if (!settings.splitter_state.isEmpty()) {
splitter->restoreState(settings.splitter_state);
}
main_layout->addWidget(splitter);
// right widgets
QWidget *right_container = new QWidget(this);
right_container->setFixedWidth(640);
r_layout = new QVBoxLayout(right_container);
r_layout->setContentsMargins(11, 0, 0, 0);
QHBoxLayout *right_hlayout = new QHBoxLayout();
fingerprint_label = new QLabel(this);
right_hlayout->addWidget(fingerprint_label, 0, Qt::AlignLeft);
// TODO: click to select another route.
right_hlayout->addWidget(new QLabel(can->routeName()), 0, Qt::AlignRight);
r_layout->addLayout(right_hlayout);
video_widget = new VideoWidget(this);
r_layout->addWidget(video_widget, 0, Qt::AlignTop);
r_layout->addWidget(charts_widget, 1);
r_layout->addStretch(0);
main_layout->addWidget(right_container);
setCentralWidget(central_widget);
detail_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
setCentralWidget(detail_widget);
createActions();
createStatusBar();
createShortcuts();
restoreGeometry(settings.geometry);
if (isMaximized()) {
setGeometry(QApplication::desktop()->availableGeometry(this));
}
restoreState(settings.window_state);
qRegisterMetaType<uint64_t>("uint64_t");
qRegisterMetaType<ReplyMsgType>("ReplyMsgType");
installMessageHandler([this](ReplyMsgType type, const std::string msg) {
@ -140,6 +99,39 @@ void MainWindow::createActions() {
help_menu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
}
void MainWindow::createDockWindows() {
// left panel
QWidget *messages_container = new QWidget(this);
QVBoxLayout *messages_layout = new QVBoxLayout(messages_container);
dbc_combo = createDBCSelector();
messages_layout->addWidget(dbc_combo);
messages_widget = new MessagesWidget(this);
messages_layout->addWidget(messages_widget);
QDockWidget *dock = new QDockWidget(tr("MESSAGES"), this);
dock->setObjectName("MessagesPanel");
dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
dock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
dock->setWidget(messages_container);
addDockWidget(Qt::LeftDockWidgetArea, dock);
// right panel
QWidget *right_container = new QWidget(this);
r_layout = new QVBoxLayout(right_container);
charts_widget = new ChartsWidget(this);
video_widget = new VideoWidget(this);
r_layout->addWidget(video_widget, 0, Qt::AlignTop);
r_layout->addWidget(charts_widget, 1);
r_layout->addStretch(0);
video_dock = new QDockWidget(can->routeName(), this);
video_dock->setObjectName(tr("VideoPanel"));
video_dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
video_dock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
video_dock->setWidget(right_container);
addDockWidget(Qt::RightDockWidgetArea, video_dock);
}
QComboBox *MainWindow::createDBCSelector() {
QComboBox *c = new QComboBox(this);
c->setEditable(true);
@ -205,7 +197,7 @@ void MainWindow::loadDBCFromClipboard() {
void MainWindow::loadDBCFromFingerprint() {
auto fingerprint = can->carFingerprint();
fingerprint_label->setText(fingerprint.isEmpty() ? tr("Unknown Car") : fingerprint);
video_dock->setWindowTitle(tr("ROUTE: %1 FINGERPINT: %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) {
@ -257,7 +249,6 @@ void MainWindow::dockCharts(bool dock) {
floating_window->setLayout(new QVBoxLayout());
floating_window->layout()->addWidget(charts_widget);
floating_window->installEventFilter(charts_widget);
floating_window->setMinimumSize(QGuiApplication::primaryScreen()->size() / 2);
floating_window->showMaximized();
}
}
@ -277,7 +268,8 @@ void MainWindow::closeEvent(QCloseEvent *event) {
if (floating_window)
floating_window->deleteLater();
settings.splitter_state = splitter->saveState();
settings.geometry = saveGeometry();
settings.window_state = saveState();
settings.save();
QWidget::closeEvent(event);
}

@ -1,10 +1,10 @@
#pragma once
#include <QComboBox>
#include <QDockWidget>
#include <QJsonDocument>
#include <QMainWindow>
#include <QProgressBar>
#include <QSplitter>
#include <QStatusBar>
#include "tools/cabana/chartswidget.h"
@ -35,6 +35,7 @@ signals:
protected:
void createActions();
void createDockWindows();
QComboBox *createDBCSelector();
void createStatusBar();
void createShortcuts();
@ -45,14 +46,13 @@ protected:
void findSimilarBits();
VideoWidget *video_widget;
QDockWidget *video_dock;
MessagesWidget *messages_widget;
DetailWidget *detail_widget;
ChartsWidget *charts_widget;
QSplitter *splitter;
QWidget *floating_window = nullptr;
QVBoxLayout *r_layout;
QProgressBar *progress_bar;
QLabel *fingerprint_label;
QJsonDocument fingerprint_to_dbc;
QComboBox *dbc_combo;
};

@ -19,7 +19,8 @@ void Settings::save() {
s.setValue("chart_height", chart_height);
s.setValue("max_chart_x_range", max_chart_x_range);
s.setValue("last_dir", last_dir);
s.setValue("splitter_state", splitter_state);
s.setValue("window_state", window_state);
s.setValue("geometry", geometry);
}
void Settings::load() {
@ -29,7 +30,8 @@ void Settings::load() {
chart_height = s.value("chart_height", 200).toInt();
max_chart_x_range = s.value("max_chart_x_range", 3 * 60).toInt();
last_dir = s.value("last_dir", QDir::homePath()).toString();
splitter_state = s.value("splitter_state").toByteArray();
window_state = s.value("window_state").toByteArray();
geometry = s.value("geometry").toByteArray();
}
// SettingsDlg

@ -18,7 +18,7 @@ public:
int chart_height = 200;
int max_chart_x_range = 3 * 60; // 3 minutes
QString last_dir;
QByteArray splitter_state;
QByteArray window_state, geometry;
signals:
void changed();

@ -17,10 +17,17 @@ inline QString formatTime(int seconds) {
return QDateTime::fromTime_t(seconds).toString(seconds > 60 * 60 ? "hh:mm:ss" : "mm:ss");
}
VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) {
setFrameShape(QFrame::StyledPanel);
setFrameShadow(QFrame::Sunken);
QHBoxLayout *containter_layout = new QHBoxLayout(this);
QVBoxLayout *main_layout = new QVBoxLayout();
main_layout->setContentsMargins(0, 0, 0, 0);
containter_layout->addStretch(1);
containter_layout->addLayout(main_layout);
containter_layout->addStretch(1);
cam_widget = new CameraWidget("camerad", can->visionStreamType(), false, this);
cam_widget->setFixedSize(parent->width(), parent->width() / 1.596);
main_layout->addWidget(cam_widget);
@ -56,8 +63,6 @@ VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent) {
}
main_layout->addLayout(control_layout);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QObject::connect(can, &CANMessages::updated, this, &VideoWidget::updateState);
QObject::connect(slider, &QSlider::sliderReleased, [this]() { can->seekTo(slider->value() / 1000.0); });
QObject::connect(slider, &QSlider::valueChanged, [=](int value) { time_label->setText(formatTime(value / 1000)); });

@ -35,7 +35,7 @@ private:
QSize thumbnail_size = {};
};
class VideoWidget : public QWidget {
class VideoWidget : public QFrame {
Q_OBJECT
public:

Loading…
Cancel
Save