dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
uavobjecttreemodel.cpp
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  *
30  * Additional note on redistribution: The copyright and license notices above
31  * must be maintained in each individual source file that is a derivative work
32  * of this source file; otherwise redistribution is prohibited.
33  */
34 
35 #include "uavobjecttreemodel.h"
36 #include "fieldtreeitem.h"
42 #include <QColor>
43 #include <QtCore/QTimer>
44 #include <QtCore/QSignalMapper>
45 #include <QtCore/QDebug>
46 #include <math.h>
47 
48 #include <QApplication>
49 
50 UAVObjectTreeModel::UAVObjectTreeModel(QObject *parent, bool useScientificNotation)
51  : QAbstractItemModel(parent)
52  , m_rootItem(NULL)
53  , m_recentlyUpdatedColor(QColor(255, 230, 230))
54  , m_manuallyChangedColor(QColor(230, 230, 255))
55  , m_updatedOnlyColor(QColor(174, 207, 250, 255))
56  , m_isPresentOnHwColor(QApplication::palette().text().color())
57  , m_notPresentOnHwColor(QColor(174, 207, 250, 255))
58  , m_useScientificFloatNotation(useScientificNotation)
59  , m_hideNotPresent(false)
60  , m_highlightManager(NULL)
61  , isInitialized(false)
62 {
63  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
64  objManager = pm->getObject<UAVObjectManager>();
65 
66  QFont font;
67  m_defaultValueFont = font;
68  font.setWeight(QFont::Bold);
69  m_nonDefaultValueFont = font;
70 }
71 
73 {
74  delete m_highlightManager;
75  delete m_rootItem;
76 }
77 
85 void UAVObjectTreeModel::setupModelData(UAVObjectManager *objManager,
86  bool useScientificFloatNotation)
87 {
88  m_useScientificFloatNotation = useScientificFloatNotation;
89  // root
90  if (m_rootItem) {
91  disconnect(objManager, &UAVObjectManager::newObject, this, &UAVObjectTreeModel::newObject);
92  disconnect(objManager, &UAVObjectManager::newInstance, this,
94  disconnect(objManager, &UAVObjectManager::instanceRemoved, this,
96  disconnect(m_highlightManager, &HighLightManager::updateHighlight, this,
97  &UAVObjectTreeModel::updateHighlight);
98 
99  delete m_highlightManager;
100  int count = m_rootItem->childCount();
101  beginRemoveRows(index(m_rootItem), 0, count);
102  delete m_rootItem;
103  endRemoveRows();
104  }
105 
106  // Create highlight manager, let it run every 200 ms.
107  m_highlightManager = new HighLightManager(200);
108  QList<QVariant> rootData;
109  rootData << tr("Property") << tr("Value") << tr("Unit");
110  m_rootItem = new TreeItem(rootData);
111 
112  m_settingsTree = new TopTreeItem(tr("Settings"), m_rootItem);
113  m_settingsTree->setHighlightManager(m_highlightManager);
114  m_rootItem->appendChild(m_settingsTree);
115  m_nonSettingsTree = new TopTreeItem(tr("Data Objects"), m_rootItem);
116  m_nonSettingsTree->setHighlightManager(m_highlightManager);
117  m_rootItem->appendChild(m_nonSettingsTree);
118  m_rootItem->setHighlightManager(m_highlightManager);
119  connect(m_highlightManager, &HighLightManager::updateHighlight, this,
120  &UAVObjectTreeModel::updateHighlight);
121 
122  QVector<QVector<UAVDataObject *>> objList = objManager->getDataObjectsVector();
123  foreach (QVector<UAVDataObject *> list, objList) {
124  foreach (UAVDataObject *obj, list) {
125  addDataObject(obj);
126  }
127  }
128  connect(objManager, &UAVObjectManager::newObject, this, &UAVObjectTreeModel::newObject,
129  Qt::UniqueConnection);
131  Qt::UniqueConnection);
132  connect(objManager, &UAVObjectManager::instanceRemoved, this,
134 }
135 
137 {
138  UAVDataObject *dobj = qobject_cast<UAVDataObject *>(obj);
139  if (dobj) {
140  addDataObject(dobj);
141  }
142 }
143 
144 void UAVObjectTreeModel::initializeModel(bool useScientificFloatNotation)
145 {
146  setupModelData(objManager, useScientificFloatNotation);
147 }
148 
150 {
151  UAVDataObject *dobj = dynamic_cast<UAVDataObject *>(obj);
152  if (!dobj)
153  return;
154 
155  TopTreeItem *root = dobj->isSettings() ? m_settingsTree : m_nonSettingsTree;
156 
157  ObjectTreeItem *existing = root->findDataObjectTreeItemByObjectId(obj->getObjID());
158  if (existing) {
159  int itemIdx = 0;
160  foreach (TreeItem *item, existing->treeChildren()) {
161  InstanceTreeItem *inst = dynamic_cast<InstanceTreeItem *>(item);
162  if (inst && inst->object() == obj) {
163  printf("removing an instance\n");
164 
165  beginRemoveRows(index(inst->parent()), itemIdx, itemIdx);
166  inst->parent()->removeChild(inst);
167  inst->deleteLater();
168  endRemoveRows();
169  }
170  ++itemIdx;
171  }
172  }
173 }
174 
175 void UAVObjectTreeModel::addDataObject(UAVDataObject *obj)
176 {
177  // Determine if the root tree is the settings or dynamic data tree
178  TopTreeItem *root = obj->isSettings() ? m_settingsTree : m_nonSettingsTree;
179 
180  TreeItem *parent = root;
181 
182  ObjectTreeItem *existing = root->findDataObjectTreeItemByObjectId(obj->getObjID());
183  if (existing) {
184  addInstance(obj, existing);
185  } else {
186  DataObjectTreeItem *dataTreeItem = new DataObjectTreeItem(
187  obj->getName() + " (" + QString::number(obj->getNumBytes()) + " bytes)");
188  dataTreeItem->setHighlightManager(m_highlightManager);
189  parent->insertChild(dataTreeItem);
190  root->addObjectTreeItem(obj->getObjID(), dataTreeItem);
191  UAVMetaObject *meta = obj->getMetaObject();
192  MetaObjectTreeItem *metaTreeItem = addMetaObject(meta, dataTreeItem);
193  root->addMetaObjectTreeItem(meta->getObjID(), metaTreeItem);
194  addInstance(obj, dataTreeItem);
195  }
196 }
197 
198 MetaObjectTreeItem *UAVObjectTreeModel::addMetaObject(UAVMetaObject *obj, TreeItem *parent)
199 {
200  connect(obj, &UAVObject::objectUpdated, this, &UAVObjectTreeModel::highlightUpdatedObject);
201  MetaObjectTreeItem *meta = new MetaObjectTreeItem(obj, tr("Meta Data"));
202 
203  meta->setHighlightManager(m_highlightManager);
204  foreach (UAVObjectField *field, obj->getFields()) {
205  if (field->getNumElements() > 1) {
206  addArrayField(field, meta);
207  } else {
208  addSingleField(0, field, meta);
209  }
210  }
211  parent->appendChild(meta);
212  return meta;
213 }
214 
215 void UAVObjectTreeModel::addInstance(UAVObject *obj, TreeItem *parent)
216 {
217  connect(obj, &UAVObject::objectUpdated, this, &UAVObjectTreeModel::highlightUpdatedObject);
218  TreeItem *item;
219  DataObjectTreeItem *p = static_cast<DataObjectTreeItem *>(parent);
220  if (obj->isSingleInstance()) {
221  item = parent;
222  p->setObject(obj);
223  } else {
224  p->setObject(NULL);
225  QString name = tr("Instance") + " " + QString::number(obj->getInstID());
226  item = new InstanceTreeItem(obj, name);
227  item->setHighlightManager(m_highlightManager);
228 
229  // Inform the model that we will add a row
230  beginInsertRows(index(parent), parent->childCount(), parent->childCount());
231 
232  // Add the row
233  parent->appendChild(item);
234 
235  // Inform the model that the row addition is complete
236  endInsertRows();
237  }
238  foreach (UAVObjectField *field, obj->getFields()) {
239  if (field->getNumElements() > 1) {
240  addArrayField(field, item);
241  } else {
242  addSingleField(0, field, item);
243  }
244  }
245  UAVDataObject *dobj = dynamic_cast<UAVDataObject *>(obj);
246  if (dobj) {
247  connect(dobj, QOverload<UAVDataObject *>::of(&UAVDataObject::presentOnHardwareChanged),
248  this, &UAVObjectTreeModel::presentOnHardwareChangedCB, Qt::UniqueConnection);
249  }
250 }
251 
252 void UAVObjectTreeModel::addArrayField(UAVObjectField *field, TreeItem *parent)
253 {
254  TreeItem *item = new ArrayFieldTreeItem(field->getName());
255  item->setHighlightManager(m_highlightManager);
256  for (auto i = 0; i < field->getNumElements(); ++i) {
257  addSingleField(i, field, item);
258  }
259  item->setDescription(field->getDescription());
260  parent->appendChild(item);
261 }
262 
263 void UAVObjectTreeModel::addSingleField(int index, UAVObjectField *field, TreeItem *parent)
264 {
266  if (field->getNumElements() == 1)
267  data.append(field->getName());
268  else
269  data.append(QString("[%1]").arg((field->getElementNames())[index]));
270 
271  FieldTreeItem *item = NULL;
272  UAVObjectField::FieldType type = field->getType();
273  switch (type) {
275  case UAVObjectField::ENUM: {
276  QStringList options = field->getOptions();
277  QVariant value = field->getValue();
278  data.append(options.indexOf(value.toString()));
279  data.append(field->getUnits());
280  item = new EnumFieldTreeItem(field, index, data);
281  break;
282  }
289  data.append(field->getValue(index));
290  data.append(field->getUnits());
291  item = new IntFieldTreeItem(field, index, data);
292  break;
294  data.append(field->getValue(index));
295  data.append(field->getUnits());
296  item = new FloatFieldTreeItem(field, index, data, m_useScientificFloatNotation);
297  break;
298  default:
299  Q_ASSERT(false);
300  }
301  item->setDescription(field->getDescription());
302  item->setHighlightManager(m_highlightManager);
303  parent->appendChild(item);
304 }
305 
306 QModelIndex UAVObjectTreeModel::index(int row, int column, const QModelIndex &parent) const
307 {
308  if (!hasIndex(row, column, parent))
309  return QModelIndex();
310 
311  TreeItem *parentItem;
312 
313  if (!parent.isValid())
314  parentItem = m_rootItem;
315  else
316  parentItem = static_cast<TreeItem *>(parent.internalPointer());
317 
318  TreeItem *childItem = parentItem->getChild(row);
319  if (childItem)
320  return createIndex(row, column, childItem);
321  else
322  return QModelIndex();
323 }
324 
325 QModelIndex UAVObjectTreeModel::index(TreeItem *item)
326 {
327  if (item->parent() == nullptr)
328  return QModelIndex();
329 
330  QModelIndex root = index(item->parent());
331 
332  for (int i = 0; i < rowCount(root); ++i) {
333  QModelIndex childIndex = index(i, 0, root);
334  TreeItem *child = static_cast<TreeItem *>(childIndex.internalPointer());
335  if (child == item)
336  return childIndex;
337  }
338  Q_ASSERT(false);
339  return QModelIndex();
340 }
341 
342 QModelIndex UAVObjectTreeModel::parent(const QModelIndex &index) const
343 {
344  if (!index.isValid())
345  return QModelIndex();
346 
347  TreeItem *childItem = static_cast<TreeItem *>(index.internalPointer());
348  TreeItem *parentItem = childItem->parent();
349  if (parentItem == m_rootItem)
350  return QModelIndex();
351 
352  return createIndex(parentItem->row(), 0, parentItem);
353 }
354 
355 int UAVObjectTreeModel::rowCount(const QModelIndex &parent) const
356 {
357  TreeItem *parentItem;
358  if (parent.column() > 0)
359  return 0;
360 
361  if (!parent.isValid())
362  parentItem = m_rootItem;
363  else
364  parentItem = static_cast<TreeItem *>(parent.internalPointer());
365 
366  return parentItem->childCount();
367 }
368 
369 int UAVObjectTreeModel::columnCount(const QModelIndex &parent) const
370 {
371  if (parent.isValid())
372  return static_cast<TreeItem *>(parent.internalPointer())->columnCount();
373  else
374  return m_rootItem->columnCount();
375 }
376 
378 {
379  QList<QModelIndex> metaIndexes;
380  foreach (MetaObjectTreeItem *metaItem, m_settingsTree->getMetaObjectItems()) {
381  metaIndexes.append(index(metaItem));
382  }
383 
384  foreach (MetaObjectTreeItem *metaItem, m_nonSettingsTree->getMetaObjectItems()) {
385  metaIndexes.append(index(metaItem));
386  }
387  return metaIndexes;
388 }
389 
391 {
392  QList<QModelIndex> dataIndexes;
393  foreach (DataObjectTreeItem *dataItem, m_settingsTree->getDataObjectItems()) {
394  dataIndexes.append(index(dataItem));
395  }
396 
397  foreach (DataObjectTreeItem *dataItem, m_nonSettingsTree->getDataObjectItems()) {
398  dataIndexes.append(index(dataItem));
399  }
400  return dataIndexes;
401 }
402 
403 QVariant UAVObjectTreeModel::data(const QModelIndex &index, int role) const
404 {
405  if (!index.isValid())
406  return QVariant();
407 
408  if (index.column() == TreeItem::dataColumn && role == Qt::EditRole) {
409  TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
410  return item->data(index.column());
411  }
412 
413  if (role == Qt::ToolTipRole) {
414  TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
415  return item->description();
416  }
417 
418  TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
419 
420  if (index.column() == 0 && role == Qt::BackgroundRole) {
421  if (!dynamic_cast<TopTreeItem *>(item) && item->highlighted())
422  return QVariant(m_recentlyUpdatedColor);
423  if (!dynamic_cast<TopTreeItem *>(item) && item->updatedOnly())
424  return QVariant(m_updatedOnlyColor);
425  }
426 
427  if (role == Qt::TextColorRole) {
428  if (item) {
429  if (item->getIsPresentOnHardware())
430  return QVariant(m_isPresentOnHwColor);
431  else
432  return QVariant(m_notPresentOnHwColor);
433  }
434  }
435 
436  if (role == Qt::FontRole) {
437  if (!item->isDefaultValue())
438  return m_nonDefaultValueFont;
439  return m_defaultValueFont;
440  }
441 
442  if (index.column() == TreeItem::dataColumn && role == Qt::BackgroundRole) {
443  FieldTreeItem *fieldItem = dynamic_cast<FieldTreeItem *>(item);
444  if (fieldItem && fieldItem->highlighted())
445  return QVariant(m_recentlyUpdatedColor);
446 
447  if (fieldItem && fieldItem->changed())
448  return QVariant(m_manuallyChangedColor);
449 
450  if (fieldItem && fieldItem->updatedOnly())
451  return QVariant(m_updatedOnlyColor);
452  }
453 
454  if (role != Qt::DisplayRole)
455  return QVariant();
456 
457  if (index.column() == TreeItem::dataColumn) {
458  EnumFieldTreeItem *fieldItem = dynamic_cast<EnumFieldTreeItem *>(item);
459  if (fieldItem) {
460  int enumIndex = fieldItem->data(index.column()).toInt();
461  return fieldItem->enumOptions(enumIndex);
462  }
463  IntFieldTreeItem *intFieldItem = dynamic_cast<IntFieldTreeItem *>(item);
464  if (intFieldItem)
465  return intFieldItem->formattedData();
466  }
467 
468  return item->data(index.column());
469 }
470 
471 bool UAVObjectTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
472 {
473  Q_UNUSED(role)
474  TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
475  item->setData(value, index.column());
476  return true;
477 }
478 
479 Qt::ItemFlags UAVObjectTreeModel::flags(const QModelIndex &index) const
480 {
481  if (!index.isValid())
482  return nullptr;
483 
484  if (index.column() == TreeItem::dataColumn) {
485  TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
486  if (item->isEditable())
487  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
488  }
489 
490  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
491 }
492 
493 QVariant UAVObjectTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
494 {
495  if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
496  return m_rootItem->data(section);
497 
498  return QVariant();
499 }
500 
501 void UAVObjectTreeModel::highlightUpdatedObject(UAVObject *obj)
502 {
503  Q_ASSERT(obj);
504  ObjectTreeItem *item = findObjectTreeItem(obj);
505  Q_ASSERT(item);
506  if (!m_onlyHighlightChangedValues) {
507  item->setHighlight();
508  }
509  item->update();
510  if (!m_onlyHighlightChangedValues) {
511  QModelIndex itemIndex = index(item);
512  Q_ASSERT(itemIndex != QModelIndex());
513  emit dataChanged(itemIndex, itemIndex);
514  }
515 }
516 
517 ObjectTreeItem *UAVObjectTreeModel::findObjectTreeItem(UAVObject *object)
518 {
519  UAVDataObject *dataObject = qobject_cast<UAVDataObject *>(object);
520  UAVMetaObject *metaObject = qobject_cast<UAVMetaObject *>(object);
521  Q_ASSERT(dataObject || metaObject);
522  if (dataObject) {
523  return findDataObjectTreeItem(dataObject);
524  } else {
525  return findMetaObjectTreeItem(metaObject);
526  }
527  return nullptr;
528 }
529 
530 DataObjectTreeItem *UAVObjectTreeModel::findDataObjectTreeItem(UAVDataObject *obj)
531 {
532  // Determine if the root tree is the settings or dynamic data tree
533  TopTreeItem *root = obj->isSettings() ? m_settingsTree : m_nonSettingsTree;
534  return root->findDataObjectTreeItemByObjectId(obj->getObjID());
535 }
536 
537 MetaObjectTreeItem *UAVObjectTreeModel::findMetaObjectTreeItem(UAVMetaObject *obj)
538 {
539  UAVDataObject *dataObject = qobject_cast<UAVDataObject *>(obj->getParentObject());
540  Q_ASSERT(dataObject);
541 
542  // Determine if the root tree is the settings or dynamic data tree
543  TopTreeItem *root = dataObject->isSettings() ? m_settingsTree : m_nonSettingsTree;
544  return root->findMetaObjectTreeItemByObjectId(obj->getObjID());
545 }
546 
547 void UAVObjectTreeModel::updateHighlight(TreeItem *item)
548 {
549  if (item == m_rootItem) {
550  return;
551  }
552 
553  QModelIndex itemIndex = index(item);
554  Q_ASSERT(itemIndex.isValid());
555  emit dataChanged(itemIndex, itemIndex.sibling(itemIndex.row(), TreeItem::dataColumn));
556 }
557 
558 void UAVObjectTreeModel::presentOnHardwareChangedCB(UAVDataObject *obj)
559 {
560  Q_UNUSED(obj);
562 }
563 
UAVObjectTreeModel(QObject *parent=nullptr, bool useScientificNotation=false)
MetaObjectTreeItem * findMetaObjectTreeItemByObjectId(quint32 objectId)
Definition: treeitem.h:238
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
void updateHighlight(TreeItem *)
void insertChild(TreeItem *child)
Definition: treeitem.cpp:138
bool highlighted()
Definition: treeitem.h:138
int columnCount(const QModelIndex &parent=QModelIndex()) const
int columnCount() const
Definition: treeitem.cpp:163
QList< MetaObjectTreeItem * > getMetaObjectItems()
Definition: treeitem.cpp:241
UAVObject * getParentObject()
void instanceRemoved(UAVObject *obj)
Core plugin system that manages the plugins, their life cycle and their registered objects...
Definition: pluginmanager.h:53
void newInstance(UAVObject *obj)
QVariant getValue(int index=0) const
void newObject(UAVObject *obj)
bool updatedOnly()
Definition: treeitem.h:142
int getNumElements() const
for i
Definition: OPPlots.m:140
UAVObject * object()
Definition: treeitem.h:271
QVariant data(const QModelIndex &index, int role) const
TreeItem * parent()
Definition: treeitem.h:132
int row() const
Definition: treeitem.cpp:155
void objectUpdated(UAVObject *obj)
Signal sent whenever any field of the object is updated.
quint32 getInstID()
Definition: uavobject.cpp:115
virtual bool isEditable()
Definition: treeitem.h:134
QModelIndex parent(const QModelIndex &index) const
virtual void removeChild(TreeItem *child)
Definition: treeitem.cpp:133
virtual void setObject(UAVObject *obj) override
Definition: treeitem.h:326
int rowCount(const QModelIndex &parent=QModelIndex()) const
QList< QModelIndex > getMetaDataIndexes()
UAVMetaObject * getMetaObject()
QString getDescription() const
QStringList getOptions() const
QString formattedData()
bool isSingleInstance()
Definition: uavobject.cpp:123
QList< QModelIndex > getDataObjectIndexes()
QList< TreeItem * > treeChildren() const
Definition: treeitem.h:112
void addObjectTreeItem(quint32 objectId, DataObjectTreeItem *oti)
Definition: treeitem.h:221
void instanceRemove(UAVObject *)
virtual bool getIsPresentOnHardware() const
Definition: treeitem.h:143
Qt::ItemFlags flags(const QModelIndex &index) const
virtual void setHighlightManager(HighLightManager *mgr)
Definition: treeitem.cpp:236
QString getName() const
QList< DataObjectTreeItem * > getDataObjectItems()
Definition: treeitem.cpp:246
bool setData(const QModelIndex &index, const QVariant &value, int role)
quint32 getObjID()
Definition: uavobject.cpp:107
QList< UAVObjectField * > getFields()
Definition: uavobject.cpp:196
virtual void appendChild(TreeItem *child)
Definition: treeitem.cpp:127
virtual void setData(QVariant value, int column=1)
Definition: treeitem.cpp:173
QStringList getElementNames() const
QString getUnits() const
quint32 getNumBytes()
Definition: uavobject.cpp:155
TreeItem * getChild(int index)
Definition: treeitem.cpp:145
QString getName()
Definition: uavobject.cpp:131
QVariant data(int column=1) const
Definition: treeitem.cpp:168
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
virtual void update()
Definition: treeitem.cpp:178
DataObjectTreeItem * findDataObjectTreeItemByObjectId(quint32 objectId)
Definition: treeitem.h:226
void initializeModel(bool useScientificFloatNotation=true)
void setDescription(QString d)
Definition: treeitem.h:117
void addMetaObjectTreeItem(quint32 objectId, MetaObjectTreeItem *oti)
Definition: treeitem.h:233
void presentOnHardwareChanged()
QVector< QVector< UAVDataObject * > > getDataObjectsVector()
void setHighlight()
Definition: treeitem.cpp:193
int childCount() const
Definition: treeitem.cpp:150
virtual bool isDefaultValue() const
Definition: treeitem.h:177
QString enumOptions(int index)
QString description()
Definition: treeitem.h:116
FieldType getType() const
static const int dataColumn
Definition: treeitem.h:202
void presentOnHardwareChanged(UAVDataObject *)
bool changed()
Definition: treeitem.h:141
void newObject(UAVObject *obj)