QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
LoggingCategoryModel.cc
Go to the documentation of this file.
2
4
5// ---------------------------------------------------------------------------
6// LoggingCategoryFlatModel
7// ---------------------------------------------------------------------------
8
9LoggingCategoryFlatModel::LoggingCategoryFlatModel(QObject* parent) : QAbstractListModel(parent) {}
10
11int LoggingCategoryFlatModel::rowCount(const QModelIndex& parent) const
12{
13 return parent.isValid() ? 0 : _items.count();
14}
15
16QVariant LoggingCategoryFlatModel::data(const QModelIndex& index, int role) const
17{
18 using enum Roles;
19
20 if (!index.isValid() || index.row() >= _items.count()) {
21 return {};
22 }
23
24 const auto* item = _items.at(index.row());
25
26 switch (role) {
27 case Qt::DisplayRole:
28 case static_cast<int>(FullNameRole):
29 return item->fullCategory;
30 case static_cast<int>(ShortNameRole):
31 return item->shortCategory;
32 case static_cast<int>(EnabledRole):
33 return item->enabled();
34 }
35
36 return {};
37}
38
39bool LoggingCategoryFlatModel::setData(const QModelIndex& index, const QVariant& value, int role)
40{
41 using enum Roles;
42
43 if (!index.isValid() || index.row() >= _items.count()) {
44 return false;
45 }
46
47 auto* item = _items.at(index.row());
48
49 if (role == static_cast<int>(EnabledRole)) {
50 item->setEnabled(value.toBool());
51 emit dataChanged(index, index, {static_cast<int>(EnabledRole)});
52 return true;
53 }
54
55 return false;
56}
57
58Qt::ItemFlags LoggingCategoryFlatModel::flags(const QModelIndex& index) const
59{
60 auto f = QAbstractListModel::flags(index);
61 if (index.isValid()) {
62 f |= Qt::ItemIsEditable;
63 }
64 return f;
65}
66
67QHash<int, QByteArray> LoggingCategoryFlatModel::roleNames() const
68{
69 using enum Roles;
70 return {
71 {Qt::DisplayRole, "display"},
72 {static_cast<int>(ShortNameRole), "shortName"},
73 {static_cast<int>(FullNameRole), "fullName"},
74 {static_cast<int>(EnabledRole), "categoryEnabled"},
75 };
76}
77
79{
80 using enum Roles;
81
82 int pos = 0;
83 while (pos < _items.count() && _items.at(pos)->fullCategory < item->fullCategory) {
84 ++pos;
85 }
86 beginInsertRows(QModelIndex(), pos, pos);
87 _items.insert(pos, item);
88 endInsertRows();
89
90 connect(item, &QGCLoggingCategoryItem::enabledChanged, this, [this, item]() {
91 const int row = _items.indexOf(item);
92 if (row >= 0) {
93 const QModelIndex idx = index(row);
94 emit dataChanged(idx, idx, {static_cast<int>(EnabledRole)});
95 }
96 });
97}
98
100{
101 for (auto* item : _items) {
102 if (item->fullCategory == fullName) {
103 return item;
104 }
105 }
106 return nullptr;
107}
108
109// ---------------------------------------------------------------------------
110// LoggingCategoryTreeModel (QAbstractItemModel for TreeView)
111// ---------------------------------------------------------------------------
112
113LoggingCategoryTreeModel::LoggingCategoryTreeModel(QObject* parent) : QAbstractItemModel(parent) {}
114
116
117LoggingCategoryTreeNode* LoggingCategoryTreeModel::nodeFromIndex(const QModelIndex& index) const
118{
119 if (!index.isValid()) {
120 return const_cast<LoggingCategoryTreeNode*>(&_root);
121 }
122 return static_cast<LoggingCategoryTreeNode*>(index.internalPointer());
123}
124
125QModelIndex LoggingCategoryTreeModel::index(int row, int column, const QModelIndex& parent) const
126{
127 if (column != 0) {
128 return {};
129 }
130 auto* parentNode = nodeFromIndex(parent);
131 if (row < 0 || row >= parentNode->children.count()) {
132 return {};
133 }
134 return createIndex(row, 0, parentNode->children.at(row));
135}
136
137QModelIndex LoggingCategoryTreeModel::parent(const QModelIndex& child) const
138{
139 if (!child.isValid()) {
140 return {};
141 }
142 auto* node = static_cast<LoggingCategoryTreeNode*>(child.internalPointer());
143 auto* parentNode = node->parent;
144 if (!parentNode || parentNode == &_root) {
145 return {};
146 }
147 auto* grandparent = parentNode->parent ? parentNode->parent : const_cast<LoggingCategoryTreeNode*>(&_root);
148 const int row = grandparent->children.indexOf(parentNode);
149 return createIndex(row, 0, parentNode);
150}
151
152int LoggingCategoryTreeModel::rowCount(const QModelIndex& parent) const
153{
154 return nodeFromIndex(parent)->children.count();
155}
156
157int LoggingCategoryTreeModel::columnCount(const QModelIndex& parent) const
158{
160 return 1;
161}
162
163bool LoggingCategoryTreeModel::hasChildren(const QModelIndex& parent) const
164{
165 return !nodeFromIndex(parent)->children.isEmpty();
166}
167
168QVariant LoggingCategoryTreeModel::data(const QModelIndex& index, int role) const
169{
170 using enum Roles;
171
172 if (!index.isValid()) {
173 return {};
174 }
175
176 auto* node = static_cast<LoggingCategoryTreeNode*>(index.internalPointer());
177 auto* item = node->item;
178 if (!item) {
179 return {};
180 }
181
182 switch (role) {
183 case Qt::DisplayRole:
184 case static_cast<int>(ShortNameRole):
185 return item->shortCategory;
186 case static_cast<int>(FullNameRole):
187 return item->fullCategory;
188 case static_cast<int>(EnabledRole):
189 return item->enabled();
190 }
191
192 return {};
193}
194
195bool LoggingCategoryTreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
196{
197 using enum Roles;
198
199 if (!index.isValid()) {
200 return false;
201 }
202
203 auto* node = static_cast<LoggingCategoryTreeNode*>(index.internalPointer());
204 auto* item = node->item;
205 if (!item) {
206 return false;
207 }
208
209 if (role == static_cast<int>(EnabledRole)) {
210 item->setEnabled(value.toBool());
211 emit dataChanged(index, index, {static_cast<int>(EnabledRole)});
212 return true;
213 }
214
215 return false;
216}
217
218Qt::ItemFlags LoggingCategoryTreeModel::flags(const QModelIndex& index) const
219{
220 auto f = QAbstractItemModel::flags(index);
221 if (index.isValid()) {
222 f |= Qt::ItemIsEditable;
223 }
224 return f;
225}
226
227QHash<int, QByteArray> LoggingCategoryTreeModel::roleNames() const
228{
229 using enum Roles;
230 return {
231 {Qt::DisplayRole, "display"},
232 {static_cast<int>(ShortNameRole), "shortName"},
233 {static_cast<int>(FullNameRole), "fullName"},
234 {static_cast<int>(EnabledRole), "categoryEnabled"},
235 };
236}
237
239{
240 std::function<void(LoggingCategoryTreeNode*)> walk = [&](LoggingCategoryTreeNode* node) {
241 if (node->item) {
242 fn(node->item);
243 }
244 for (auto* child : std::as_const(node->children)) {
245 walk(child);
246 }
247 };
248 for (auto* child : std::as_const(_root.children)) {
249 walk(child);
250 }
251}
252
253int LoggingCategoryTreeModel::insertionIndex(LoggingCategoryTreeNode* parent, const QString& name) const
254{
255 int pos = 0;
256 while (pos < parent->children.count()) {
257 auto* existing = parent->children.at(pos)->item;
258 if (existing && existing->shortCategory >= name) {
259 break;
260 }
261 ++pos;
262 }
263 return pos;
264}
265
266LoggingCategoryTreeNode* LoggingCategoryTreeModel::findOrCreateIntermediateNode(
267 LoggingCategoryTreeNode* parentNode, const QString& segment, const QString& fullPrefix)
268{
269 for (auto* child : std::as_const(parentNode->children)) {
270 if (child->item && child->item->shortCategory == segment) {
271 return child;
272 }
273 }
274
275 // Create intermediate (group) node
276 auto* item = new QGCLoggingCategoryItem(segment, fullPrefix, false, this);
277 auto* node = new LoggingCategoryTreeNode;
278 node->item = item;
279 node->parent = parentNode;
280
281 const QModelIndex parentIndex = (parentNode == &_root) ? QModelIndex() : createIndex(
282 parentNode->parent ? parentNode->parent->children.indexOf(parentNode) : 0, 0, parentNode);
283 const int pos = insertionIndex(parentNode, segment);
284
285 beginInsertRows(parentIndex, pos, pos);
286 parentNode->children.insert(pos, node);
288
289 connect(item, &QGCLoggingCategoryItem::enabledChanged, this, [this, node]() {
290 auto* p = node->parent ? node->parent : &_root;
291 const int row = p->children.indexOf(node);
292 if (row >= 0) {
293 const QModelIndex idx = createIndex(row, 0, node);
294 emit dataChanged(idx, idx, {static_cast<int>(Roles::EnabledRole)});
295 }
296 });
297
298 return node;
299}
300
301void LoggingCategoryTreeModel::insertCategory(const QStringList& pathSegments, const QString& fullCategory,
303{
305
306 // Create/find intermediate nodes for all segments except the last
308 for (int i = 0; i < pathSegments.size() - 1; ++i) {
309 if (!prefix.isEmpty()) {
310 prefix += QLatin1Char('.');
311 }
313 currentParent = findOrCreateIntermediateNode(currentParent, pathSegments[i], prefix + QLatin1Char('.'));
314 }
315
316 // Insert the leaf node
317 auto* node = new LoggingCategoryTreeNode;
318 node->item = item;
319 node->parent = currentParent;
320
321 const QModelIndex parentIndex = (currentParent == &_root) ? QModelIndex() : createIndex(
322 currentParent->parent ? currentParent->parent->children.indexOf(currentParent) : 0, 0, currentParent);
323 const int pos = insertionIndex(currentParent, pathSegments.last());
324
325 beginInsertRows(parentIndex, pos, pos);
326 currentParent->children.insert(pos, node);
328
329 connect(item, &QGCLoggingCategoryItem::enabledChanged, this, [this, node]() {
330 auto* p = node->parent ? node->parent : &_root;
331 const int row = p->children.indexOf(node);
332 if (row >= 0) {
333 const QModelIndex idx = createIndex(row, 0, node);
334 emit dataChanged(idx, idx, {static_cast<int>(Roles::EnabledRole)});
335 }
336 });
337}
int rowCount(const QModelIndex &parent=QModelIndex()) const override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QHash< int, QByteArray > roleNames() const override
void insertSorted(QGCLoggingCategoryItem *item)
QGCLoggingCategoryItem * findByFullName(const QString &fullName) const
LoggingCategoryFlatModel(QObject *parent=nullptr)
Qt::ItemFlags flags(const QModelIndex &index) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
QModelIndex parent(const QModelIndex &child) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
~LoggingCategoryTreeModel() override
void forEachItem(const std::function< void(QGCLoggingCategoryItem *)> &fn)
LoggingCategoryTreeModel(QObject *parent=nullptr)
QHash< int, QByteArray > roleNames() const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
void insertCategory(const QStringList &pathSegments, const QString &fullCategory, QGCLoggingCategoryItem *item)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
LoggingCategoryTreeNode * parent
QList< LoggingCategoryTreeNode * > children
QGCLoggingCategoryItem * item