This commit is contained in:
deeaitch committed 2026-10-06 17:14:50 -04:00
1 parent e5d818d9b2
commit a533d9aa00
13 files changed
+527 -12

No files matched your search

+100 -9
View File
@@ -21,8 +21,8 @@ The implementation follows a simple and practical design:
- the same decode engine can be reused for live traffic and trace replay
The core library uses C++17 and has no Qt dependency. Qt Core and Qt Test are
required only for the regression tests. Live CAN acquisition, trace-file readers,
and a Qt model adapter are left to the consuming application.
used by the regression tests; the optional adapter requires Qt Core. Live CAN acquisition, trace-file readers,
are left to the consuming application. An optional Qt Core model adapter is provided in `qt/`.
See [changelog.md](changelog.md) for the release and development history,
[tests/README.md](tests/README.md) for test instructions, and
@@ -55,7 +55,7 @@ DbcTreeBuilder
↓
TreeNode hierarchy
↓
future Qt UI
DbcTreeModel → Qt views
```
### 2. Runtime decode path
@@ -114,7 +114,8 @@ This avoids forcing UI-oriented structures into a decode role they were not mean
```text
core/ C++17 parser, statement handlers, metadata, tree, and decoder
examples/ Command-line demo (built separately)
tests/ QtTest parser and decoder regression suites
qt/ Optional read-only Qt Core model adapter
tests/ Parser, decoder, tree, and optional model tests
docs/ Generated Doxygen documentation
dbc.pro Root qmake project: core + tests
Doxyfile API documentation configuration
@@ -235,7 +236,7 @@ has no metadata payload. The payload types are:
- `FrameInfo`
- `SignalInfo`
The tree is intended for browsing and later Qt model integration.
The tree supports browsing through the optional `DbcTreeModel` adapter.
It is **not** the primary runtime decode structure.
@@ -884,7 +885,7 @@ nonnegative `uint64_t`; when constructing mappings manually, normalize keys
with `NormalizeValueKey()` before insertion.
Named `VAL_TABLE_` tables, environment-variable mappings, multiline statements,
and Qt presentation are outside this implementation.
are outside this implementation; the optional Qt adapter exposes signal mappings.
---
@@ -942,9 +943,6 @@ A practical development order would be:
Recommended additions:
- parent pointer in `TreeNode`
- Qt model adapter
- better display strings for UI
- selective decoding of only chosen signals
### Stage 3
@@ -1009,6 +1007,99 @@ make -j
qmake is still the build tool; this target does not link Qt libraries.
### Optional Qt model adapter
Requires Qt 5.11 or newer (including Qt 6) for `QAbstractItemModelTester`.
The adapter itself links only Qt Core. Enable its library and focused QtTest suite:
```sh
mkdir -p build-qt
cd build-qt
qmake6 ../dbc.pro CONFIG+=dbc_qt
make -j
make check
```
Consumers include `qt/qt.pri` instead of `core/core.pri`, and set
`DBC_CORE_BUILD_DIR` and `DBC_QT_BUILD_DIR` to the corresponding library build
directories when building separately. A widget application also needs `QT += widgets`. The adapter integration enables
`no_keywords`, because core metadata has a `signals` member; use `Q_SIGNALS`,
`Q_SLOTS`, and `Q_EMIT` in consuming Qt classes.
```cpp
#include "dbc_parser.h"
#include "dbc_tree_builder.h"
#include "dbc_tree_model.h"
#include <QTreeView>
// Run after constructing QApplication; view owns the model through QObject.
QTreeView view;
auto *model = new DbcTreeModel(&view);
model->SetTree(DbcTreeBuilder().Build(DbcParser().ParseFile("example.dbc")));
view.setModel(model);
view.expandAll();
view.show();
// On reload, pass a newly built tree to SetTree(); to clear:
// model->SetTree(nullptr);
```
The root is invisible: frames are top-level rows, signals are their children.
Only column zero has children. `parent()` always returns column zero.
The model takes exclusive ownership of the tree; do not retain mutable aliases.
Metadata is copied by the tree builder, so the parsed database may be destroyed.
`TreeNode::GetParent()` is non-owning and `GetRow()` gives the zero-based sibling
position (zero for a detached node/root). Nodes cannot be copied or moved;
transferring their `unique_ptr` ownership preserves addresses and navigation.
Call `SetTree()` on the model's thread. It accepts a detached Root or nullptr,
uses `beginResetModel()`/`endResetModel()`, and destroys the previous tree during
reset. All ordinary QModelIndex values expire on reset and must not be reused;
QPersistentModelIndex values are invalidated by Qt. Destroying the model also
invalidates indexes. Invalid and foreign indexes return no data/flags/children.
Valid items are enabled and selectable, with no editing support.
| Column (zero-based enum) | Frame display | Signal display |
| --- | --- | --- |
| 0 `Name` | Name | Name |
| 1 `CanId` | Normalized hexadecimal ID | Empty |
| 2 `PayloadLength` | Bytes | Empty |
| 3 `StartBit` | Empty | DBC start bit |
| 4 `BitLength` | Empty | Bit count |
| 5 `ByteOrder` | Empty | Intel / Motorola |
| 6 `Signed` | Empty | Signed / Unsigned |
| 7 `Unit` | Empty | Unit |
| 8 `Comment` | Comment | Comment |
Horizontal DisplayRole headers describe these columns; other header requests
return invalid QVariant. ToolTipRole returns the comment on every column.
Custom roles also apply on every column; inapplicable roles return invalid QVariant:
| Role | Node types | QVariant content |
| --- | --- | --- |
| `NodeTypeRole` | Frame, signal | int corresponding to NodeType |
| `CanIdRole`, `PayloadLengthRole`, `ExtendedRole` | Frame | uint, int, bool |
| `StartBitRole`, `BitLengthRole` | Signal | uint |
| `LittleEndianRole`, `SignedRole` | Signal | bool |
| `UnitRole` | Signal | QString |
| `CommentRole` | Frame, signal | QString |
| `ValueDescriptionsRole` | Signal | QVariantList of QVariantMap entries |
Each value-description entry contains `value` (qlonglong for negative keys,
qulonglong for nonnegative keys) and `description` (QString). This preserves the
full signed/unsigned 64-bit range without converting through double. An unmapped
signal returns an empty list. Data comes from `SignalInfo::valueDescriptions`.
Unsupported roles return invalid QVariant.
### Standalone tree tests without Qt
From the repository root, use only a C++17 compiler:
```sh
c++ -std=c++17 -Icore tests/tree_node_test.cpp core/tree_node.cpp \
core/dbc_tree_builder.cpp -o /tmp/dbc_tree_node_test
/tmp/dbc_tree_node_test
```
### Build and run the demo
After building core, run these commands from the repository root: