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