cabana: startup stream chooser dialog (#27938)
* new StreamDialog
* choose dbc file
* update last_dir
* move to /streams
* cleanup
* add stretch
* catch panda exception
* cleanup
* cleanup
* small cleanup
* fix pandaStream crash caused by a failed connection
* static function to create stream widget
* cleanup
old-commit-hash: 590b1bc206
beeps
parent
d4cea1f024
commit
1045c7d836
14 changed files with 310 additions and 114 deletions
@ -1,75 +0,0 @@ |
|||||||
#include "tools/cabana/route.h" |
|
||||||
|
|
||||||
#include <QFileDialog> |
|
||||||
#include <QGridLayout> |
|
||||||
#include <QLabel> |
|
||||||
#include <QMessageBox> |
|
||||||
#include <QPushButton> |
|
||||||
|
|
||||||
#include "tools/cabana/streams/replaystream.h" |
|
||||||
|
|
||||||
OpenRouteDialog::OpenRouteDialog(QWidget *parent) : QDialog(parent) { |
|
||||||
// TODO: get route list from api.comma.ai
|
|
||||||
QGridLayout *grid_layout = new QGridLayout(); |
|
||||||
grid_layout->addWidget(new QLabel(tr("Route")), 0, 0); |
|
||||||
grid_layout->addWidget(route_edit = new QLineEdit(this), 0, 1); |
|
||||||
route_edit->setPlaceholderText(tr("Enter remote route name or click browse to select a local route")); |
|
||||||
auto file_btn = new QPushButton(tr("Browse..."), this); |
|
||||||
grid_layout->addWidget(file_btn, 0, 2); |
|
||||||
|
|
||||||
grid_layout->addWidget(new QLabel(tr("Video")), 1, 0); |
|
||||||
grid_layout->addWidget(choose_video_cb = new QComboBox(this), 1, 1); |
|
||||||
QString items[] = {tr("No Video"), tr("Road Camera"), tr("Wide Road Camera"), tr("Driver Camera"), tr("QCamera")}; |
|
||||||
for (int i = 0; i < std::size(items); ++i) { |
|
||||||
choose_video_cb->addItem(items[i]); |
|
||||||
} |
|
||||||
choose_video_cb->setCurrentIndex(1); // default is road camera;
|
|
||||||
|
|
||||||
btn_box = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel); |
|
||||||
btn_box->button(QDialogButtonBox::Open)->setEnabled(false); |
|
||||||
|
|
||||||
QVBoxLayout *main_layout = new QVBoxLayout(this); |
|
||||||
main_layout->addLayout(grid_layout); |
|
||||||
main_layout->addWidget(btn_box); |
|
||||||
main_layout->addStretch(0); |
|
||||||
setMinimumSize({550, 120}); |
|
||||||
|
|
||||||
QObject::connect(btn_box, &QDialogButtonBox::accepted, this, &OpenRouteDialog::loadRoute); |
|
||||||
QObject::connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject); |
|
||||||
QObject::connect(route_edit, &QLineEdit::textChanged, [this]() { |
|
||||||
btn_box->button(QDialogButtonBox::Open)->setEnabled(!route_edit->text().isEmpty()); |
|
||||||
}); |
|
||||||
QObject::connect(file_btn, &QPushButton::clicked, [=]() { |
|
||||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Open Local Route"), settings.last_route_dir); |
|
||||||
if (!dir.isEmpty()) { |
|
||||||
route_edit->setText(dir); |
|
||||||
settings.last_route_dir = QFileInfo(dir).absolutePath(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
void OpenRouteDialog::loadRoute() { |
|
||||||
btn_box->setEnabled(false); |
|
||||||
|
|
||||||
QString route = route_edit->text(); |
|
||||||
QString data_dir; |
|
||||||
if (int idx = route.lastIndexOf('/'); idx != -1) { |
|
||||||
data_dir = route.mid(0, idx + 1); |
|
||||||
route = route.mid(idx + 1); |
|
||||||
} |
|
||||||
|
|
||||||
bool is_valid_format = Route::parseRoute(route).str.size() > 0; |
|
||||||
if (!is_valid_format) { |
|
||||||
QMessageBox::warning(nullptr, tr("Warning"), tr("Invalid route format: '%1'").arg(route)); |
|
||||||
} else { |
|
||||||
uint32_t flags[] = {REPLAY_FLAG_NO_VIPC, REPLAY_FLAG_NONE, REPLAY_FLAG_ECAM, REPLAY_FLAG_DCAM, REPLAY_FLAG_QCAMERA}; |
|
||||||
failed_to_load = !dynamic_cast<ReplayStream *>(can)->loadRoute(route, data_dir, flags[choose_video_cb->currentIndex()]); |
|
||||||
if (failed_to_load) { |
|
||||||
QMessageBox::warning(nullptr, tr("Warning"), tr("Failed to load route: '%1'").arg(route)); |
|
||||||
} else { |
|
||||||
accept(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
btn_box->setEnabled(true); |
|
||||||
} |
|
@ -1,21 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <QComboBox> |
|
||||||
#include <QDialogButtonBox> |
|
||||||
#include <QLineEdit> |
|
||||||
#include <QDialog> |
|
||||||
|
|
||||||
class OpenRouteDialog : public QDialog { |
|
||||||
Q_OBJECT |
|
||||||
|
|
||||||
public: |
|
||||||
OpenRouteDialog(QWidget *parent); |
|
||||||
void loadRoute(); |
|
||||||
inline bool failedToLoad() const { return failed_to_load; } |
|
||||||
|
|
||||||
private: |
|
||||||
QLineEdit *route_edit; |
|
||||||
QComboBox *choose_video_cb; |
|
||||||
QDialogButtonBox *btn_box; |
|
||||||
bool failed_to_load = false; |
|
||||||
}; |
|
@ -0,0 +1,52 @@ |
|||||||
|
#include "tools/cabana/streamselector.h" |
||||||
|
|
||||||
|
#include <QDialogButtonBox> |
||||||
|
#include <QFileDialog> |
||||||
|
#include <QFormLayout> |
||||||
|
#include <QLabel> |
||||||
|
#include <QPushButton> |
||||||
|
|
||||||
|
StreamSelector::StreamSelector(QWidget *parent) : QDialog(parent) { |
||||||
|
setWindowTitle(tr("Open stream")); |
||||||
|
QVBoxLayout *main_layout = new QVBoxLayout(this); |
||||||
|
|
||||||
|
tab = new QTabWidget(this); |
||||||
|
tab->setTabBarAutoHide(true); |
||||||
|
main_layout->addWidget(tab); |
||||||
|
|
||||||
|
QHBoxLayout *dbc_layout = new QHBoxLayout(); |
||||||
|
dbc_file = new QLineEdit(this); |
||||||
|
dbc_file->setReadOnly(true); |
||||||
|
dbc_file->setPlaceholderText(tr("Choose a dbc file to open")); |
||||||
|
QPushButton *file_btn = new QPushButton(tr("Browse...")); |
||||||
|
dbc_layout->addWidget(new QLabel(tr("dbc File"))); |
||||||
|
dbc_layout->addWidget(dbc_file); |
||||||
|
dbc_layout->addWidget(file_btn); |
||||||
|
main_layout->addLayout(dbc_layout); |
||||||
|
|
||||||
|
QFrame *line = new QFrame(this); |
||||||
|
line->setFrameStyle(QFrame::HLine | QFrame::Sunken); |
||||||
|
main_layout->addWidget(line); |
||||||
|
|
||||||
|
auto btn_box = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel); |
||||||
|
main_layout->addWidget(btn_box); |
||||||
|
|
||||||
|
QObject::connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject); |
||||||
|
QObject::connect(btn_box, &QDialogButtonBox::accepted, [=]() { |
||||||
|
success = ((AbstractOpenStreamWidget *)tab->currentWidget())->open(); |
||||||
|
if (success) { |
||||||
|
accept(); |
||||||
|
} |
||||||
|
}); |
||||||
|
QObject::connect(file_btn, &QPushButton::clicked, [this]() { |
||||||
|
QString fn = QFileDialog::getOpenFileName(this, tr("Open File"), settings.last_dir, "DBC (*.dbc)"); |
||||||
|
if (!fn.isEmpty()) { |
||||||
|
dbc_file->setText(fn); |
||||||
|
settings.last_dir = QFileInfo(fn).absolutePath(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
void StreamSelector::addStreamWidget(AbstractOpenStreamWidget *w) { |
||||||
|
tab->addTab(w, w->title()); |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QDialog> |
||||||
|
#include <QLineEdit> |
||||||
|
#include <QTabWidget> |
||||||
|
|
||||||
|
#include "tools/cabana/streams/abstractstream.h" |
||||||
|
|
||||||
|
class StreamSelector : public QDialog { |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
StreamSelector(QWidget *parent = nullptr); |
||||||
|
void addStreamWidget(AbstractOpenStreamWidget *w); |
||||||
|
QString dbcFile() const { return dbc_file->text(); } |
||||||
|
inline bool failed() const { return !success; } |
||||||
|
|
||||||
|
private: |
||||||
|
QLineEdit *dbc_file; |
||||||
|
QTabWidget *tab; |
||||||
|
bool success = true; |
||||||
|
}; |
Loading…
Reference in new issue