Closes #9
This commit is contained in:
1 parent
e5d818d9b2
commit
a533d9aa00
13 files changed
+527
-12
No files matched your search
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user