#pragma once #include #include #include #include #include #include #include #include #include #include #include "tools/cabana/dbc/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" class MessageListModel : public QAbstractTableModel { Q_OBJECT public: enum Column { NAME = 0, SOURCE, ADDRESS, NODE, FREQ, COUNT, DATA, }; MessageListModel(QObject *parent) : QAbstractTableModel(parent) {} QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override { return Column::DATA + 1; } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; int rowCount(const QModelIndex &parent = QModelIndex()) const override { return items_.size(); } void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; void setFilterStrings(const QMap &filters); void showInactivemessages(bool show); void msgsReceived(const std::set *new_msgs, bool has_new_ids); bool filterAndSort(); void dbcModified(); struct Item { MessageId id; QString name; QString node; bool operator==(const Item &other) const { return id == other.id && name == other.name && node == other.node; } }; std::vector items_; bool show_inactive_messages = true; private: void sortItems(std::vector &items); bool match(const MessageListModel::Item &id); QMap filters_; std::set dbc_messages_; int sort_column = 0; Qt::SortOrder sort_order = Qt::AscendingOrder; int sort_threshold_ = 0; }; class MessageView : public QTreeView { Q_OBJECT public: MessageView(QWidget *parent) : QTreeView(parent) {} void updateBytesSectionSize(); protected: void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const override {} void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector()) override; void wheelEvent(QWheelEvent *event) override; }; class MessageViewHeader : public QHeaderView { // https://stackoverflow.com/a/44346317 Q_OBJECT public: MessageViewHeader(QWidget *parent); void updateHeaderPositions(); void updateGeometries() override; QSize sizeHint() const override; void updateFilters(); QMap editors; }; class MessagesWidget : public QWidget { Q_OBJECT public: MessagesWidget(QWidget *parent); void selectMessage(const MessageId &message_id); QByteArray saveHeaderState() const { return view->header()->saveState(); } bool restoreHeaderState(const QByteArray &state) const { return view->header()->restoreState(state); } void suppressHighlighted(); signals: void msgSelectionChanged(const MessageId &message_id); void titleChanged(const QString &title); protected: QWidget *createToolBar(); void headerContextMenuEvent(const QPoint &pos); void menuAboutToShow(); void setMultiLineBytes(bool multi); void updateTitle(); MessageView *view; MessageViewHeader *header; MessageBytesDelegate *delegate; std::optional current_msg_id; MessageListModel *model; QPushButton *suppress_add; QPushButton *suppress_clear; QMenu *menu; };