Branch data Line data Source code
1 : : // SPDX-License-Identifier: MIT
2 : : #include "dbc_tree_model.h"
3 : : #include <QVariantList>
4 : : #include <QVariantMap>
5 : : #include <limits>
6 : : #include <stdexcept>
7 : :
8 : : namespace {
9 : 20 : QVariantList ToVariantList(const ValueDescriptions &values) {
10 : 20 : QVariantList descriptions;
11 [ + + ]: 50 : for (const ValueDescriptions::value_type &entry : values) {
12 : 30 : QVariantMap pair;
13 [ + + ]: 30 : if (const std::int64_t *number = std::get_if<std::int64_t>(&entry.first))
14 [ + - + - ]: 10 : pair.insert("value", QVariant::fromValue(static_cast<qlonglong>(*number)));
15 : : else
16 [ + - + - ]: 20 : pair.insert("value", QVariant::fromValue(
17 [ + - ]: 40 : static_cast<qulonglong>(std::get<std::uint64_t>(entry.first))));
18 [ + - + - : 30 : pair.insert("description", QString::fromStdString(entry.second));
+ - ]
19 [ + - ]: 30 : descriptions.append(pair);
20 : 30 : }
21 : 20 : return descriptions;
22 : 0 : }
23 : : } // namespace
24 : :
25 : 6 : DbcTreeModel::DbcTreeModel(QObject *parent) : QAbstractItemModel(parent) {}
26 : :
27 : 12 : void DbcTreeModel::SetTree(std::unique_ptr<TreeNode> root) {
28 [ + + + + : 12 : if (root && (root->GetType() != NodeType::Root || root->GetParent()))
- + + + ]
29 [ + - ]: 2 : throw std::invalid_argument("Model requires a detached root node");
30 : 10 : beginResetModel();
31 : 10 : m_root = std::move(root);
32 : 10 : endResetModel();
33 : 10 : }
34 : :
35 : 2110 : const TreeNode *DbcTreeModel::Node(const QModelIndex &index) const {
36 [ + + + - : 6258 : if (!index.isValid() || index.model() != this || index.column() < 0 ||
+ - ]
37 [ + + - + : 6258 : index.column() >= ColumnCount || index.row() < 0)
+ + ]
38 : 39 : return nullptr;
39 : 2071 : return static_cast<const TreeNode *>(index.internalPointer());
40 : : }
41 : :
42 : 1254 : QModelIndex DbcTreeModel::index(int row, int column, const QModelIndex &parentIndex) const {
43 [ + + + + : 3134 : if (row < 0 || column < 0 || column >= ColumnCount ||
+ + + + +
+ ]
44 [ + + ]: 1880 : (parentIndex.isValid() && parentIndex.column() != 0))
45 : 28 : return {};
46 [ + + ]: 1226 : const TreeNode *owner = parentIndex.isValid() ? Node(parentIndex) : m_root.get();
47 [ + + ]: 1226 : if (!owner)
48 : 2 : return {};
49 : 1224 : const TreeNode *child = owner->GetChild(static_cast<std::size_t>(row));
50 [ + + ]: 1224 : return child ? createIndex(row, column, const_cast<TreeNode *>(child)) : QModelIndex();
51 : : }
52 : :
53 : 783 : QModelIndex DbcTreeModel::parent(const QModelIndex &childIndex) const {
54 : 783 : const TreeNode *child = Node(childIndex);
55 [ + + ]: 783 : const TreeNode *owner = child ? child->GetParent() : nullptr;
56 [ + + + + : 783 : if (!owner || owner == m_root.get())
+ + ]
57 : 336 : return {};
58 : 447 : return createIndex(static_cast<int>(owner->GetRow()), 0, const_cast<TreeNode *>(owner));
59 : : }
60 : :
61 : 700 : int DbcTreeModel::rowCount(const QModelIndex &parentIndex) const {
62 [ + + + + : 700 : if (parentIndex.isValid() && parentIndex.column() != 0)
+ + ]
63 : 204 : return 0;
64 [ + + ]: 496 : const TreeNode *owner = parentIndex.isValid() ? Node(parentIndex) : m_root.get();
65 [ + + ]: 496 : if (!owner)
66 : 53 : return 0;
67 [ + - ]: 443 : return static_cast<int>(qMin(owner->GetChildCount(), static_cast<std::size_t>(std::numeric_limits<int>::max())));
68 : : }
69 : :
70 : 395 : int DbcTreeModel::columnCount(const QModelIndex &parentIndex) const {
71 [ + + + + ]: 395 : return parentIndex.isValid() && !Node(parentIndex) ? 0 : ColumnCount;
72 : : }
73 : :
74 : 240 : QVariant DbcTreeModel::data(const QModelIndex &item, int role) const {
75 [ + - ]: 240 : const TreeNode *node = Node(item);
76 [ + + ]: 240 : if (!node)
77 : 2 : return {};
78 [ + - ]: 238 : const FrameInfo *frame = node->GetFrame();
79 [ + - ]: 238 : const SignalInfo *signal = node->GetSignal();
80 : 238 : QString comment;
81 [ + + ]: 238 : if (frame != nullptr)
82 [ + - ]: 126 : comment = QString::fromStdString(frame->comment);
83 [ + - ]: 112 : else if (signal != nullptr)
84 [ + - ]: 112 : comment = QString::fromStdString(signal->comment);
85 [ + + + + ]: 238 : if (role == Qt::ToolTipRole || role == CommentRole)
86 : 41 : return comment;
87 [ + + ]: 197 : if (role == NodeTypeRole)
88 [ + - ]: 2 : return static_cast<int>(node->GetType());
89 [ + + + + ]: 195 : if (role == ValueDescriptionsRole && signal) {
90 [ + - ]: 20 : return ToVariantList(signal->valueDescriptions);
91 : : }
92 [ + + ]: 175 : if (frame) {
93 [ + + ]: 103 : if (role == CanIdRole)
94 : 10 : return frame->canId;
95 [ + + ]: 93 : if (role == PayloadLengthRole)
96 : 10 : return static_cast<int>(frame->dlc);
97 [ + + ]: 83 : if (role == ExtendedRole)
98 : 10 : return frame->isExtended;
99 : : }
100 [ + + ]: 145 : if (signal) {
101 [ + + ]: 72 : if (role == StartBitRole)
102 : 10 : return signal->startBit;
103 [ + + ]: 62 : if (role == BitLengthRole)
104 : 10 : return signal->length;
105 [ + + ]: 52 : if (role == LittleEndianRole)
106 : 10 : return signal->isLittleEndian;
107 [ + + ]: 42 : if (role == SignedRole)
108 : 10 : return signal->isSigned;
109 [ + + ]: 32 : if (role == UnitRole)
110 [ + - ]: 10 : return QString::fromStdString(signal->unit);
111 : : }
112 [ + + ]: 95 : if (role != Qt::DisplayRole)
113 : 66 : return {};
114 [ + + + + : 29 : switch (item.column()) {
+ + + + +
- ]
115 : 9 : case Name:
116 [ + - + - ]: 9 : return QString::fromStdString(node->GetName());
117 : 4 : case CanId:
118 [ + + + - : 8 : return frame ? QVariant(QString("0x%1").arg(frame->canId, 0, 16).toUpper()) : QVariant();
+ - + - +
+ + + + +
- - - - -
- ]
119 : 2 : case PayloadLength:
120 [ + + ]: 2 : return frame ? QVariant(static_cast<int>(frame->dlc)) : QVariant();
121 : 2 : case StartBit:
122 [ + + ]: 2 : return signal ? QVariant(signal->startBit) : QVariant();
123 : 2 : case BitLength:
124 [ + + ]: 2 : return signal ? QVariant(signal->length) : QVariant();
125 : 3 : case ByteOrder:
126 [ + + + + : 3 : return signal ? QVariant(signal->isLittleEndian ? "Intel" : "Motorola") : QVariant();
+ - ]
127 : 3 : case Signed:
128 [ + + + + : 3 : return signal ? QVariant(signal->isSigned ? "Signed" : "Unsigned") : QVariant();
+ - ]
129 : 2 : case Unit:
130 [ + + + - : 4 : return signal ? QVariant(QString::fromStdString(signal->unit)) : QVariant();
+ + - - ]
131 : 2 : case Comment:
132 : 2 : return comment;
133 : 0 : default:
134 : 0 : return {};
135 : : }
136 : 238 : }
137 : :
138 : 30 : QVariant DbcTreeModel::headerData(int section, Qt::Orientation orientation, int role) const {
139 : : static const char *const headers[] = {"Name", "CAN ID", "Payload (bytes)", "Start bit", "Length (bits)", "Byte order", "Signedness", "Unit", "Comment"};
140 [ + + + + : 30 : if (orientation != Qt::Horizontal || role != Qt::DisplayRole || section < 0 || section >= ColumnCount)
+ + + + ]
141 : 12 : return {};
142 [ + - ]: 18 : return QString::fromLatin1(headers[section]);
143 : : }
144 : :
145 : 39 : Qt::ItemFlags DbcTreeModel::flags(const QModelIndex &item) const {
146 [ + + ]: 39 : return Node(item) ? Qt::ItemIsEnabled | Qt::ItemIsSelectable : Qt::NoItemFlags;
147 : : }
|