Cabanba: new dialog to manage chart series (#26675)

* New dialog to manage chart series

* connect to signal currentIndexChanged

* cleanup

use cbegin/cend
old-commit-hash: 59ed74ae4a
taco
Dean Lee 3 years ago committed by GitHub
parent 9e61dbfeba
commit 78c649c60a
  1. 133
      tools/cabana/chartswidget.cc
  2. 23
      tools/cabana/chartswidget.h
  3. 1
      tools/cabana/dbcmanager.h

@ -196,6 +196,14 @@ ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) {
close_btn_proxy->setWidget(remove_btn); close_btn_proxy->setWidget(remove_btn);
close_btn_proxy->setZValue(chart->zValue() + 11); close_btn_proxy->setZValue(chart->zValue() + 11);
QToolButton *manage_btn = new QToolButton();
manage_btn->setText("🔧");
manage_btn->setAutoRaise(true);
manage_btn->setToolTip(tr("Manage series"));
manage_btn_proxy = new QGraphicsProxyWidget(chart);
manage_btn_proxy->setWidget(manage_btn);
manage_btn_proxy->setZValue(chart->zValue() + 11);
setChart(chart); setChart(chart);
setRenderHint(QPainter::Antialiasing); setRenderHint(QPainter::Antialiasing);
setRubberBand(QChartView::HorizontalRubberBand); setRubberBand(QChartView::HorizontalRubberBand);
@ -207,6 +215,7 @@ ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) {
QObject::connect(dbc(), &DBCManager::msgUpdated, this, &ChartView::msgUpdated); QObject::connect(dbc(), &DBCManager::msgUpdated, this, &ChartView::msgUpdated);
QObject::connect(&settings, &Settings::changed, this, &ChartView::updateFromSettings); QObject::connect(&settings, &Settings::changed, this, &ChartView::updateFromSettings);
QObject::connect(remove_btn, &QToolButton::clicked, this, &ChartView::remove); QObject::connect(remove_btn, &QToolButton::clicked, this, &ChartView::remove);
QObject::connect(manage_btn, &QToolButton::clicked, this, &ChartView::manageSeries);
} }
ChartView::~ChartView() { ChartView::~ChartView() {
@ -278,9 +287,41 @@ void ChartView::msgRemoved(uint32_t address) {
} }
} }
void ChartView::manageSeries() {
SeriesSelector dlg(this);
for (auto &s : sigs) {
dlg.addSeries(s.msg_id, msgName(s.msg_id), QString::fromStdString(s.sig->name));
}
int ret = dlg.exec();
if (ret == QDialog::Accepted) {
QList<QStringList> series_list = dlg.series();
if (series_list.isEmpty()) {
emit remove();
} else {
for (auto &s : series_list) {
if (auto m = dbc()->msg(s[0])) {
auto it = m->sigs.find(s[2]);
if (it != m->sigs.end() && !hasSeries(s[0], &(it->second))) {
addSeries(s[0], &(it->second));
}
}
}
for (auto it = sigs.begin(); it != sigs.end(); /**/) {
bool exists = std::any_of(series_list.cbegin(), series_list.cend(), [&](auto &s) {
return s[0] == it->msg_id && s[2] == it->sig->name.c_str();
});
it = exists ? ++it : removeSeries(it);
}
}
}
}
void ChartView::resizeEvent(QResizeEvent *event) { void ChartView::resizeEvent(QResizeEvent *event) {
QChartView::resizeEvent(event); QChartView::resizeEvent(event);
close_btn_proxy->setPos(event->size().width() - close_btn_proxy->size().width() - 11, 8); int x = event->size().width() - close_btn_proxy->size().width() - 11;
close_btn_proxy->setPos(x, 8);
manage_btn_proxy->setPos(x - manage_btn_proxy->size().width() - 5, 8);
} }
void ChartView::updateTitle() { void ChartView::updateTitle() {
@ -462,3 +503,93 @@ void ChartView::drawForeground(QPainter *painter, const QRectF &rect) {
painter->setPen(QPen(chart()->titleBrush().color(), 2)); painter->setPen(QPen(chart()->titleBrush().color(), 2));
painter->drawLine(QPointF{x, chart()->plotArea().top() - 2}, QPointF{x, chart()->plotArea().bottom() + 2}); painter->drawLine(QPointF{x, chart()->plotArea().top() - 2}, QPointF{x, chart()->plotArea().bottom() + 2});
} }
// SeriesSelector
SeriesSelector::SeriesSelector(QWidget *parent) {
setWindowTitle(tr("Manage Chart Series"));
QHBoxLayout *contents_layout = new QHBoxLayout();
QVBoxLayout *left_layout = new QVBoxLayout();
left_layout->addWidget(new QLabel(tr("Select Signals:")));
msgs_combo = new QComboBox(this);
left_layout->addWidget(msgs_combo);
sig_list = new QListWidget(this);
sig_list->setSortingEnabled(true);
sig_list->setToolTip(tr("Double click on an item to add signal to chart"));
left_layout->addWidget(sig_list);
QVBoxLayout *right_layout = new QVBoxLayout();
right_layout->addWidget(new QLabel(tr("Chart Signals:")));
chart_series = new QListWidget(this);
chart_series->setSortingEnabled(true);
chart_series->setToolTip(tr("Double click on an item to remove signal from chart"));
right_layout->addWidget(chart_series);
contents_layout->addLayout(left_layout);
contents_layout->addLayout(right_layout);
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->addLayout(contents_layout);
main_layout->addWidget(buttonBox);
for (auto it = can->can_msgs.cbegin(); it != can->can_msgs.cend(); ++it) {
if (auto m = dbc()->msg(it.key())) {
msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(it.key()), it.key());
}
}
msgs_combo->model()->sort(0);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
QObject::connect(msgs_combo, SIGNAL(currentIndexChanged(int)), SLOT(msgSelected(int)));
QObject::connect(sig_list, &QListWidget::itemDoubleClicked, this, &SeriesSelector::addSignal);
QObject::connect(chart_series, &QListWidget::itemDoubleClicked, [](QListWidgetItem *item) { delete item; });
if (int index = msgs_combo->currentIndex(); index >= 0) {
msgSelected(index);
}
}
void SeriesSelector::msgSelected(int index) {
QString msg_id = msgs_combo->itemData(index).toString();
sig_list->clear();
if (auto m = dbc()->msg(msg_id)) {
for (auto &[name, s] : m->sigs) {
QStringList data({msg_id, m->name, name});
QListWidgetItem *item = new QListWidgetItem(name, sig_list);
item->setData(Qt::UserRole, data);
sig_list->addItem(item);
}
}
}
void SeriesSelector::addSignal(QListWidgetItem *item) {
QStringList data = item->data(Qt::UserRole).toStringList();
addSeries(data[0], data[1], data[2]);
}
void SeriesSelector::addSeries(const QString &id, const QString& msg_name, const QString &sig_name) {
QStringList data({id, msg_name, sig_name});
for (int i = 0; i < chart_series->count(); ++i) {
if (chart_series->item(i)->data(Qt::UserRole).toStringList() == data) {
return;
}
}
QListWidgetItem *new_item = new QListWidgetItem(chart_series);
new_item->setData(Qt::UserRole, data);
chart_series->addItem(new_item);
QLabel *label = new QLabel(QString("%0 <font color=\"gray\">%1 %2</font>").arg(data[2]).arg(data[1]).arg(data[0]), chart_series);
label->setContentsMargins(5, 0, 5, 0);
new_item->setSizeHint(label->sizeHint());
chart_series->setItemWidget(new_item, label);
}
QList<QStringList> SeriesSelector::series() {
QList<QStringList> ret;
for (int i = 0; i < chart_series->count(); ++i) {
ret.push_back(chart_series->item(i)->data(Qt::UserRole).toStringList());
}
return ret;
}

@ -1,6 +1,9 @@
#pragma once #pragma once
#include <QComboBox>
#include <QDialogButtonBox>
#include <QLabel> #include <QLabel>
#include <QListWidget>
#include <QGraphicsEllipseItem> #include <QGraphicsEllipseItem>
#include <QGraphicsLineItem> #include <QGraphicsLineItem>
#include <QGraphicsProxyWidget> #include <QGraphicsProxyWidget>
@ -50,6 +53,7 @@ private slots:
void msgUpdated(uint32_t address); void msgUpdated(uint32_t address);
void signalUpdated(const Signal *sig); void signalUpdated(const Signal *sig);
void signalRemoved(const Signal *sig); void signalRemoved(const Signal *sig);
void manageSeries();
private: private:
QList<ChartView::SigItem>::iterator removeSeries(const QList<ChartView::SigItem>::iterator &it); QList<ChartView::SigItem>::iterator removeSeries(const QList<ChartView::SigItem>::iterator &it);
@ -70,6 +74,7 @@ private:
QGraphicsEllipseItem *track_ellipse; QGraphicsEllipseItem *track_ellipse;
QGraphicsTextItem *value_text; QGraphicsTextItem *value_text;
QGraphicsProxyWidget *close_btn_proxy; QGraphicsProxyWidget *close_btn_proxy;
QGraphicsProxyWidget *manage_btn_proxy;
std::pair<double, double> events_range = {0, 0}; std::pair<double, double> events_range = {0, 0};
QList<SigItem> sigs; QList<SigItem> sigs;
}; };
@ -114,3 +119,21 @@ private:
std::pair<double, double> zoomed_range; std::pair<double, double> zoomed_range;
bool use_dark_theme = false; bool use_dark_theme = false;
}; };
class SeriesSelector : public QDialog {
Q_OBJECT
public:
SeriesSelector(QWidget *parent);
void addSeries(const QString &id, const QString& msg_name, const QString &sig_name);
QList<QStringList> series();
private slots:
void msgSelected(int index);
void addSignal(QListWidgetItem *item);
private:
QComboBox *msgs_combo;
QListWidget *sig_list;
QListWidget *chart_series;
};

@ -28,6 +28,7 @@ public:
static std::pair<uint8_t, uint32_t> parseId(const QString &id); static std::pair<uint8_t, uint32_t> parseId(const QString &id);
inline static std::vector<std::string> allDBCNames() { return get_dbc_names(); } inline static std::vector<std::string> allDBCNames() { return get_dbc_names(); }
inline std::map<uint32_t, DBCMsg> &allMsgs() { return msgs; }
inline QString name() const { return dbc ? dbc->name.c_str() : ""; } inline QString name() const { return dbc ? dbc->name.c_str() : ""; }
void updateMsg(const QString &id, const QString &name, uint32_t size); void updateMsg(const QString &id, const QString &name, uint32_t size);

Loading…
Cancel
Save