#include "tools/cabana/detailwidget.h" #include #include #include #include #include "tools/cabana/canmessages.h" #include "tools/cabana/dbcmanager.h" // DetailWidget DetailWidget::DetailWidget(QWidget *parent) : QWidget(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); // title QHBoxLayout *title_layout = new QHBoxLayout(); title_layout->addWidget(new QLabel("time:")); time_label = new QLabel(this); title_layout->addWidget(time_label); time_label->setStyleSheet("font-weight:bold"); title_layout->addStretch(); name_label = new QLabel(this); name_label->setStyleSheet("font-weight:bold;"); title_layout->addWidget(name_label); title_layout->addStretch(); edit_btn = new QPushButton(tr("Edit"), this); edit_btn->setVisible(false); title_layout->addWidget(edit_btn); main_layout->addLayout(title_layout); // binary view binary_view = new BinaryView(this); main_layout->addWidget(binary_view, 0, Qt::AlignTop); // signals signals_container = new QWidget(this); signals_container->setLayout(new QVBoxLayout); signals_container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); scroll = new ScrollArea(this); scroll->setWidget(signals_container); scroll->setWidgetResizable(true); scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); main_layout->addWidget(scroll); // history log history_log = new HistoryLog(this); main_layout->addWidget(history_log); QObject::connect(edit_btn, &QPushButton::clicked, this, &DetailWidget::editMsg); QObject::connect(binary_view, &BinaryView::cellsSelected, this, &DetailWidget::addSignal); QObject::connect(can, &CANMessages::updated, this, &DetailWidget::updateState); QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &DetailWidget::dbcMsgChanged); } void DetailWidget::setMessage(const QString &message_id) { if (msg_id != message_id) { msg_id = message_id; dbcMsgChanged(); } } void DetailWidget::dbcMsgChanged() { if (msg_id.isEmpty()) return; qDeleteAll(signals_container->findChildren()); QString msg_name = tr("untitled"); if (auto msg = dbc()->msg(msg_id)) { for (int i = 0; i < msg->sigs.size(); ++i) { auto form = new SignalEdit(i, msg_id, msg->sigs[i]); signals_container->layout()->addWidget(form); QObject::connect(form, &SignalEdit::showChart, [this, sig = &msg->sigs[i]]() { emit showChart(msg_id, sig); }); QObject::connect(form, &SignalEdit::showFormClicked, this, &DetailWidget::showForm); QObject::connect(form, &SignalEdit::remove, this, &DetailWidget::removeSignal); QObject::connect(form, &SignalEdit::save, this, &DetailWidget::saveSignal); } msg_name = msg->name.c_str(); } edit_btn->setVisible(true); name_label->setText(msg_name); binary_view->setMessage(msg_id); history_log->setMessage(msg_id); } void DetailWidget::updateState() { time_label->setText(QString::number(can->currentSec(), 'f', 3)); if (msg_id.isEmpty()) return; binary_view->updateState(); history_log->updateState(); } void DetailWidget::showForm() { SignalEdit *sender = qobject_cast(QObject::sender()); for (auto f : signals_container->findChildren()) { f->setFormVisible(f == sender && !f->isFormVisible()); if (f == sender) { QTimer::singleShot(0, [=]() { scroll->ensureWidgetVisible(f); }); } } } void DetailWidget::editMsg() { auto msg = dbc()->msg(msg_id); QString name = msg ? msg->name.c_str() : "untitled"; int size = msg ? msg->size : can->lastMessage(msg_id).dat.size(); EditMessageDialog dlg(msg_id, name, size, this); if (dlg.exec()) { dbc()->updateMsg(msg_id, dlg.name_edit->text(), dlg.size_spin->value()); dbcMsgChanged(); } } void DetailWidget::addSignal(int start_bit, int size) { if (dbc()->msg(msg_id)) { AddSignalDialog dlg(msg_id, start_bit, size, this); if (dlg.exec()) { dbc()->addSignal(msg_id, dlg.form->getSignal()); dbcMsgChanged(); } } } void DetailWidget::saveSignal() { SignalEdit *sig_form = qobject_cast(QObject::sender()); auto s = sig_form->form->getSignal(); dbc()->updateSignal(msg_id, sig_form->sig_name, s); // update binary view and history log binary_view->setMessage(msg_id); history_log->setMessage(msg_id); } void DetailWidget::removeSignal() { SignalEdit *sig_form = qobject_cast(QObject::sender()); QString text = tr("Are you sure you want to remove signal '%1'").arg(sig_form->sig_name); if (QMessageBox::Yes == QMessageBox::question(this, tr("Remove signal"), text)) { dbc()->removeSignal(msg_id, sig_form->sig_name); dbcMsgChanged(); } } // EditMessageDialog EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Edit message")); QVBoxLayout *main_layout = new QVBoxLayout(this); QFormLayout *form_layout = new QFormLayout(); form_layout->addRow("ID", new QLabel(msg_id)); name_edit = new QLineEdit(title, this); form_layout->addRow(tr("Name"), name_edit); size_spin = new QSpinBox(this); // TODO: limit the maximum? size_spin->setMinimum(1); size_spin->setValue(size); form_layout->addRow(tr("Size"), size_spin); main_layout->addLayout(form_layout); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); main_layout->addWidget(buttonBox); setFixedWidth(parent->width() * 0.9); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); } // ScrollArea bool ScrollArea::eventFilter(QObject *obj, QEvent *ev) { if (obj == widget() && ev->type() == QEvent::Resize) { int height = widget()->height() + 4; setMinimumHeight(height > 480 ? 480 : height); setMaximumHeight(height); } return QScrollArea::eventFilter(obj, ev); } void ScrollArea::setWidget(QWidget *w) { QScrollArea::setWidget(w); w->installEventFilter(this); }