Closes #9
This commit is contained in:
1 parent
e5d818d9b2
commit
a533d9aa00
13 files changed
+527
-12
No files matched your search
@@ -0,0 +1,128 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "dbc_tree_model.h"
|
||||
#include <QVariantList>
|
||||
#include <QVariantMap>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
DbcTreeModel::DbcTreeModel(QObject *parent) : QAbstractItemModel(parent) {}
|
||||
|
||||
void DbcTreeModel::SetTree(std::unique_ptr<TreeNode> root) {
|
||||
if (root && (root->GetType() != NodeType::Root || root->GetParent()))
|
||||
throw std::invalid_argument("Model requires a detached root node");
|
||||
beginResetModel();
|
||||
m_root = std::move(root);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
const TreeNode *DbcTreeModel::Node(const QModelIndex &index) const {
|
||||
if (!index.isValid() || index.model() != this || index.column() < 0 ||
|
||||
index.column() >= ColumnCount || index.row() < 0)
|
||||
return nullptr;
|
||||
return static_cast<const TreeNode *>(index.internalPointer());
|
||||
}
|
||||
|
||||
QModelIndex DbcTreeModel::index(int row, int column, const QModelIndex &parentIndex) const {
|
||||
if (row < 0 || column < 0 || column >= ColumnCount ||
|
||||
(parentIndex.isValid() && parentIndex.column() != 0))
|
||||
return {};
|
||||
const TreeNode *owner = parentIndex.isValid() ? Node(parentIndex) : m_root.get();
|
||||
if (!owner)
|
||||
return {};
|
||||
const TreeNode *child = owner->GetChild(static_cast<std::size_t>(row));
|
||||
return child ? createIndex(row, column, const_cast<TreeNode *>(child)) : QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex DbcTreeModel::parent(const QModelIndex &childIndex) const {
|
||||
const TreeNode *child = Node(childIndex);
|
||||
const TreeNode *owner = child ? child->GetParent() : nullptr;
|
||||
if (!owner || owner == m_root.get())
|
||||
return {};
|
||||
return createIndex(static_cast<int>(owner->GetRow()), 0, const_cast<TreeNode *>(owner));
|
||||
}
|
||||
|
||||
int DbcTreeModel::rowCount(const QModelIndex &parentIndex) const {
|
||||
if (parentIndex.isValid() && parentIndex.column() != 0)
|
||||
return 0;
|
||||
const TreeNode *owner = parentIndex.isValid() ? Node(parentIndex) : m_root.get();
|
||||
if (!owner)
|
||||
return 0;
|
||||
return static_cast<int>(qMin(owner->GetChildCount(), static_cast<std::size_t>(std::numeric_limits<int>::max())));
|
||||
}
|
||||
|
||||
int DbcTreeModel::columnCount(const QModelIndex &parentIndex) const {
|
||||
return parentIndex.isValid() && !Node(parentIndex) ? 0 : ColumnCount;
|
||||
}
|
||||
|
||||
QVariant DbcTreeModel::data(const QModelIndex &item, int role) const {
|
||||
const TreeNode *node = Node(item);
|
||||
if (!node)
|
||||
return {};
|
||||
const FrameInfo *frame = node->GetFrame();
|
||||
const SignalInfo *signal = node->GetSignal();
|
||||
const QString comment = QString::fromStdString(frame ? frame->comment : signal ? signal->comment
|
||||
: "");
|
||||
if (role == Qt::ToolTipRole || role == CommentRole)
|
||||
return comment;
|
||||
if (role == NodeTypeRole)
|
||||
return static_cast<int>(node->GetType());
|
||||
if (role == ValueDescriptionsRole && signal) {
|
||||
QVariantList descriptions;
|
||||
for (const auto &entry: signal->valueDescriptions) {
|
||||
QVariantMap pair;
|
||||
if (const auto *number = std::get_if<std::int64_t>(&entry.first))
|
||||
pair.insert("value", QVariant::fromValue(static_cast<qlonglong>(*number)));
|
||||
else
|
||||
pair.insert("value", QVariant::fromValue(static_cast<qulonglong>(std::get<std::uint64_t>(entry.first))));
|
||||
pair.insert("description", QString::fromStdString(entry.second));
|
||||
descriptions.append(pair);
|
||||
}
|
||||
return descriptions;
|
||||
}
|
||||
if (frame) {
|
||||
if (role == CanIdRole) return frame->canId;
|
||||
if (role == PayloadLengthRole) return static_cast<int>(frame->dlc);
|
||||
if (role == ExtendedRole) return frame->isExtended;
|
||||
}
|
||||
if (signal) {
|
||||
if (role == StartBitRole) return signal->startBit;
|
||||
if (role == BitLengthRole) return signal->length;
|
||||
if (role == LittleEndianRole) return signal->isLittleEndian;
|
||||
if (role == SignedRole) return signal->isSigned;
|
||||
if (role == UnitRole) return QString::fromStdString(signal->unit);
|
||||
}
|
||||
if (role != Qt::DisplayRole) return {};
|
||||
switch (item.column()) {
|
||||
case Name:
|
||||
return QString::fromStdString(node->GetName());
|
||||
case CanId:
|
||||
return frame ? QVariant(QString("0x%1").arg(frame->canId, 0, 16).toUpper()) : QVariant();
|
||||
case PayloadLength:
|
||||
return frame ? QVariant(static_cast<int>(frame->dlc)) : QVariant();
|
||||
case StartBit:
|
||||
return signal ? QVariant(signal->startBit) : QVariant();
|
||||
case BitLength:
|
||||
return signal ? QVariant(signal->length) : QVariant();
|
||||
case ByteOrder:
|
||||
return signal ? QVariant(signal->isLittleEndian ? "Intel" : "Motorola") : QVariant();
|
||||
case Signed:
|
||||
return signal ? QVariant(signal->isSigned ? "Signed" : "Unsigned") : QVariant();
|
||||
case Unit:
|
||||
return signal ? QVariant(QString::fromStdString(signal->unit)) : QVariant();
|
||||
case Comment:
|
||||
return comment;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
QVariant DbcTreeModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
static const char *const headers[] = {"Name", "CAN ID", "Payload (bytes)", "Start bit", "Length (bits)", "Byte order", "Signedness", "Unit", "Comment"};
|
||||
if (orientation != Qt::Horizontal || role != Qt::DisplayRole || section < 0 || section >= ColumnCount)
|
||||
return {};
|
||||
return QString::fromLatin1(headers[section]);
|
||||
}
|
||||
|
||||
Qt::ItemFlags DbcTreeModel::flags(const QModelIndex &item) const {
|
||||
return Node(item) ? Qt::ItemIsEnabled | Qt::ItemIsSelectable : Qt::NoItemFlags;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#ifndef DBC_TREE_MODEL_H
|
||||
#define DBC_TREE_MODEL_H
|
||||
|
||||
#include "tree_node.h"
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
/** Read-only model. Owns an immutable tree; all indexes expire on SetTree().
|
||||
* Use QPersistentModelIndex to observe reset invalidation. Call on the model thread.
|
||||
*/
|
||||
class DbcTreeModel : public QAbstractItemModel {
|
||||
public:
|
||||
enum Column { Name,
|
||||
CanId,
|
||||
PayloadLength,
|
||||
StartBit,
|
||||
BitLength,
|
||||
ByteOrder,
|
||||
Signed,
|
||||
Unit,
|
||||
Comment,
|
||||
ColumnCount };
|
||||
// Metadata roles apply on every column; inapplicable roles return invalid QVariant.
|
||||
enum Role { NodeTypeRole = Qt::UserRole + 1,
|
||||
CanIdRole,
|
||||
PayloadLengthRole,
|
||||
StartBitRole,
|
||||
BitLengthRole,
|
||||
LittleEndianRole,
|
||||
SignedRole,
|
||||
UnitRole,
|
||||
CommentRole,
|
||||
ValueDescriptionsRole,
|
||||
ExtendedRole };
|
||||
|
||||
explicit DbcTreeModel(QObject *parent = nullptr);
|
||||
void SetTree(std::unique_ptr<TreeNode> root);
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
const TreeNode *Node(const QModelIndex &index) const;
|
||||
std::unique_ptr<TreeNode> m_root;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
include($$PWD/../core/core.pri)
|
||||
QT += core
|
||||
INCLUDEPATH += $$PWD
|
||||
isEmpty(DBC_QT_BUILD_DIR): DBC_QT_BUILD_DIR = $$clean_path($$OUT_PWD/../qt)
|
||||
# Put the adapter before core for static linker dependency ordering.
|
||||
LIBS = -L$$DBC_QT_BUILD_DIR -ldbc_qt $$LIBS
|
||||
win32-msvc*: DBC_QT_LIBRARY = $$DBC_QT_BUILD_DIR/dbc_qt.lib
|
||||
else: DBC_QT_LIBRARY = $$DBC_QT_BUILD_DIR/libdbc_qt.a
|
||||
PRE_TARGETDEPS += $$DBC_QT_LIBRARY
|
||||
|
||||
CONFIG += no_keywords
|
||||
Reference in new issue
Block a user