2010-04-07 18:38:20 +00:00
|
|
|
/**
|
|
|
|
******************************************************************************
|
|
|
|
*
|
|
|
|
* @file uavobjecttreemodel.cpp
|
|
|
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
|
|
|
* @brief
|
|
|
|
* @see The GNU Public License (GPL) Version 3
|
|
|
|
* @defgroup uavobjectbrowser
|
|
|
|
* @{
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "uavobjecttreemodel.h"
|
|
|
|
#include "treeitem.h"
|
|
|
|
#include "uavobjects/uavobjectmanager.h"
|
|
|
|
#include "uavobjects/uavdataobject.h"
|
|
|
|
#include "uavobjects/uavmetaobject.h"
|
2010-04-09 15:27:15 +00:00
|
|
|
#include "uavobjects/uavobjectfields.h"
|
2010-04-07 18:38:20 +00:00
|
|
|
#include "extensionsystem/pluginmanager.h"
|
|
|
|
#include <QtGui/QColor>
|
2010-04-12 05:54:54 +00:00
|
|
|
#include <QtCore/QTimer>
|
|
|
|
#include <QtCore/QSignalMapper>
|
2010-04-07 18:38:20 +00:00
|
|
|
#include <QtCore/QDebug>
|
|
|
|
|
|
|
|
UAVObjectTreeModel::UAVObjectTreeModel(QObject *parent) :
|
|
|
|
QAbstractItemModel(parent)
|
|
|
|
{
|
|
|
|
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
|
|
|
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
|
|
|
|
2010-04-12 05:54:54 +00:00
|
|
|
m_signalMapper = new QSignalMapper();
|
|
|
|
connect(m_signalMapper, SIGNAL(mapped(QObject*)), this, SLOT(resetHighlightObject(QObject*)));
|
2010-04-07 18:38:20 +00:00
|
|
|
connect(objManager, SIGNAL(newObject(UAVObject*)), this, SLOT(newObject(UAVObject*)));
|
|
|
|
connect(objManager, SIGNAL(newInstance(UAVObject*)), this, SLOT(newObject(UAVObject*)));
|
|
|
|
|
|
|
|
setupModelData(objManager);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAVObjectTreeModel::setupModelData(UAVObjectManager *objManager)
|
|
|
|
{
|
|
|
|
// root
|
|
|
|
QList<QVariant> rootData;
|
|
|
|
rootData << tr("Property") << tr("Value") << tr("Unit");
|
|
|
|
rootItem = new TreeItem(rootData);
|
|
|
|
|
|
|
|
m_settingsTree = new TopTreeItem(tr("Settings"), rootItem);
|
|
|
|
rootItem->appendChild(m_settingsTree);
|
|
|
|
m_nonSettingsTree = new TopTreeItem(tr("Data Objects"), rootItem);
|
|
|
|
rootItem->appendChild(m_nonSettingsTree);
|
|
|
|
|
|
|
|
QList< QList<UAVDataObject*> > objList = objManager->getDataObjects();
|
|
|
|
foreach (QList<UAVDataObject*> list, objList) {
|
|
|
|
foreach (UAVDataObject* obj, list) {
|
|
|
|
addDataObject(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAVObjectTreeModel::newObject(UAVObject *obj)
|
|
|
|
{
|
|
|
|
UAVDataObject *dobj = qobject_cast<UAVDataObject*>(obj);
|
|
|
|
if (dobj)
|
|
|
|
addDataObject(dobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAVObjectTreeModel::addDataObject(UAVDataObject *obj)
|
|
|
|
{
|
|
|
|
TopTreeItem *root = obj->isSettings() ? m_settingsTree : m_nonSettingsTree;
|
|
|
|
if (root->objIds().contains(obj->getObjID())) {
|
|
|
|
int index = root->objIds().indexOf(obj->getObjID());
|
|
|
|
addInstance(obj, root->child(index));
|
|
|
|
} else {
|
|
|
|
DataObjectTreeItem *data = new DataObjectTreeItem(obj->getName());
|
|
|
|
int index = root->nameIndex(obj->getName());
|
|
|
|
root->insert(index, data);
|
|
|
|
root->insertObjId(index, obj->getObjID());
|
|
|
|
UAVMetaObject *meta = obj->getMetaObject();
|
|
|
|
addMetaObject(meta, data);
|
|
|
|
addInstance(obj, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAVObjectTreeModel::addMetaObject(UAVMetaObject *obj, TreeItem *parent)
|
|
|
|
{
|
|
|
|
MetaObjectTreeItem *meta = new MetaObjectTreeItem(tr("Meta Data"));
|
2010-04-11 07:58:31 +00:00
|
|
|
foreach (UAVObjectField *field, obj->getFields()) {
|
|
|
|
if (field->getNumElements() > 1) {
|
|
|
|
addArrayField(field, meta);
|
|
|
|
} else {
|
|
|
|
addSingleField(0, field, meta);
|
|
|
|
}
|
|
|
|
}
|
2010-04-07 18:38:20 +00:00
|
|
|
parent->appendChild(meta);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAVObjectTreeModel::addInstance(UAVObject *obj, TreeItem *parent)
|
|
|
|
{
|
2010-04-12 05:54:54 +00:00
|
|
|
connect(obj, SIGNAL(objectUpdatedAuto(UAVObject*)), this, SLOT(highlightUpdatedObject(UAVObject*)));
|
2010-04-07 18:38:20 +00:00
|
|
|
TreeItem *item;
|
2010-04-12 05:54:54 +00:00
|
|
|
if (obj->isSingleInstance()) {
|
|
|
|
item = parent;
|
|
|
|
DataObjectTreeItem *p = static_cast<DataObjectTreeItem*>(parent);
|
|
|
|
p->setObject(obj);
|
|
|
|
} else {
|
2010-04-07 18:38:20 +00:00
|
|
|
QString name = tr("Instance") + " " + QString::number(obj->getInstID());
|
2010-04-12 05:54:54 +00:00
|
|
|
item = new InstanceTreeItem(obj, name);
|
2010-04-11 07:58:31 +00:00
|
|
|
parent->appendChild(item);
|
2010-04-07 18:38:20 +00:00
|
|
|
}
|
|
|
|
foreach (UAVObjectField *field, obj->getFields()) {
|
|
|
|
if (field->getNumElements() > 1) {
|
|
|
|
addArrayField(field, item);
|
|
|
|
} else {
|
|
|
|
addSingleField(0, field, item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UAVObjectTreeModel::addArrayField(UAVObjectField *field, TreeItem *parent)
|
|
|
|
{
|
|
|
|
TreeItem *item = new ArrayFieldTreeItem(field->getName());
|
|
|
|
for (uint i = 0; i < field->getNumElements(); ++i) {
|
|
|
|
addSingleField(i, field, item);
|
|
|
|
}
|
|
|
|
parent->appendChild(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAVObjectTreeModel::addSingleField(int index, UAVObjectField *field, TreeItem *parent)
|
|
|
|
{
|
|
|
|
QList<QVariant> data;
|
|
|
|
if (field->getNumElements() == 1)
|
|
|
|
data.append(field->getName());
|
|
|
|
else
|
|
|
|
data.append(QString("[%1]").arg(index));
|
|
|
|
UAVObjectFieldEnum *enumField = dynamic_cast<UAVObjectFieldEnum*>(field);
|
|
|
|
UAVObjectFieldInt8 *int8Field = dynamic_cast<UAVObjectFieldInt8*>(field);
|
|
|
|
UAVObjectFieldInt16 *int16Field = dynamic_cast<UAVObjectFieldInt16*>(field);
|
|
|
|
UAVObjectFieldInt32 *int32Field = dynamic_cast<UAVObjectFieldInt32*>(field);
|
|
|
|
UAVObjectFieldUInt8 *uInt8Field = dynamic_cast<UAVObjectFieldUInt8*>(field);
|
|
|
|
UAVObjectFieldUInt16 *uInt16Field = dynamic_cast<UAVObjectFieldUInt16*>(field);
|
|
|
|
UAVObjectFieldUInt32 *uInt32Field = dynamic_cast<UAVObjectFieldUInt32*>(field);
|
|
|
|
UAVObjectFieldFloat *floatField = dynamic_cast<UAVObjectFieldFloat*>(field);
|
|
|
|
|
|
|
|
FieldTreeItem *item;
|
|
|
|
if (enumField) {
|
2010-04-09 09:05:23 +00:00
|
|
|
data.append(enumField->getSelectedIndex(index));
|
2010-04-07 18:38:20 +00:00
|
|
|
data.append(field->getUnits());
|
2010-04-11 07:58:31 +00:00
|
|
|
item = new EnumFieldTreeItem(enumField, index, data);
|
2010-04-07 18:38:20 +00:00
|
|
|
} else if (int8Field) {
|
2010-04-11 07:58:31 +00:00
|
|
|
data.append(int8Field->getValue(index));
|
2010-04-07 18:38:20 +00:00
|
|
|
data.append(field->getUnits());
|
2010-04-11 07:58:31 +00:00
|
|
|
item = new Int8FieldTreeItem(int8Field, index, data);
|
2010-04-07 18:38:20 +00:00
|
|
|
} else if (int16Field) {
|
2010-04-11 07:58:31 +00:00
|
|
|
data.append(int16Field->getValue(index));
|
2010-04-07 18:38:20 +00:00
|
|
|
data.append(field->getUnits());
|
2010-04-11 07:58:31 +00:00
|
|
|
item = new Int16FieldTreeItem(int16Field, index, data);
|
2010-04-07 18:38:20 +00:00
|
|
|
} else if (int32Field) {
|
2010-04-11 07:58:31 +00:00
|
|
|
data.append(int32Field->getValue(index));
|
2010-04-07 18:38:20 +00:00
|
|
|
data.append(field->getUnits());
|
2010-04-11 07:58:31 +00:00
|
|
|
item = new Int32FieldTreeItem(int32Field, index, data);
|
2010-04-07 18:38:20 +00:00
|
|
|
} else if (uInt8Field) {
|
2010-04-11 07:58:31 +00:00
|
|
|
data.append(uInt8Field->getValue(index));
|
2010-04-07 18:38:20 +00:00
|
|
|
data.append(field->getUnits());
|
2010-04-11 07:58:31 +00:00
|
|
|
item = new UInt8FieldTreeItem(uInt8Field, index, data);
|
2010-04-07 18:38:20 +00:00
|
|
|
} else if (uInt16Field) {
|
2010-04-11 07:58:31 +00:00
|
|
|
data.append(uInt16Field->getValue(index));
|
2010-04-07 18:38:20 +00:00
|
|
|
data.append(field->getUnits());
|
2010-04-11 07:58:31 +00:00
|
|
|
item = new UInt16FieldTreeItem(uInt16Field, index, data);
|
2010-04-07 18:38:20 +00:00
|
|
|
} else if (uInt32Field) {
|
2010-04-11 07:58:31 +00:00
|
|
|
data.append(uInt32Field->getValue(index));
|
2010-04-07 18:38:20 +00:00
|
|
|
data.append(field->getUnits());
|
2010-04-11 07:58:31 +00:00
|
|
|
item = new UInt32FieldTreeItem(uInt32Field, index, data);
|
2010-04-07 18:38:20 +00:00
|
|
|
} else if (floatField) {
|
2010-04-11 07:58:31 +00:00
|
|
|
data.append(floatField->getValue(index));
|
2010-04-07 18:38:20 +00:00
|
|
|
data.append(field->getUnits());
|
2010-04-09 09:05:23 +00:00
|
|
|
item = new FloatFieldTreeItem(floatField, index, data);
|
2010-04-07 18:38:20 +00:00
|
|
|
} else {
|
|
|
|
data.append("Data Error");
|
|
|
|
data.append(field->getUnits());
|
|
|
|
item = new FieldTreeItem(index, data);
|
|
|
|
}
|
|
|
|
parent->appendChild(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
QModelIndex UAVObjectTreeModel::index(int row, int column, const QModelIndex &parent)
|
|
|
|
const
|
|
|
|
{
|
|
|
|
if (!hasIndex(row, column, parent))
|
|
|
|
return QModelIndex();
|
|
|
|
|
|
|
|
TreeItem *parentItem;
|
|
|
|
|
|
|
|
if (!parent.isValid())
|
|
|
|
parentItem = rootItem;
|
|
|
|
else
|
|
|
|
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
|
|
|
|
|
|
|
TreeItem *childItem = parentItem->child(row);
|
|
|
|
if (childItem)
|
|
|
|
return createIndex(row, column, childItem);
|
|
|
|
else
|
|
|
|
return QModelIndex();
|
|
|
|
}
|
|
|
|
|
|
|
|
QModelIndex UAVObjectTreeModel::parent(const QModelIndex &index) const
|
|
|
|
{
|
|
|
|
if (!index.isValid())
|
|
|
|
return QModelIndex();
|
|
|
|
|
|
|
|
TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
|
|
|
|
TreeItem *parentItem = childItem->parent();
|
|
|
|
|
|
|
|
if (parentItem == rootItem)
|
|
|
|
return QModelIndex();
|
|
|
|
|
|
|
|
return createIndex(parentItem->row(), 0, parentItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
int UAVObjectTreeModel::rowCount(const QModelIndex &parent) const
|
|
|
|
{
|
|
|
|
TreeItem *parentItem;
|
|
|
|
if (parent.column() > 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!parent.isValid())
|
|
|
|
parentItem = rootItem;
|
|
|
|
else
|
|
|
|
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
|
|
|
|
|
|
|
return parentItem->childCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
int UAVObjectTreeModel::columnCount(const QModelIndex &parent) const
|
|
|
|
{
|
|
|
|
if (parent.isValid())
|
|
|
|
return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
|
|
|
|
else
|
|
|
|
return rootItem->columnCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant UAVObjectTreeModel::data(const QModelIndex &index, int role) const
|
|
|
|
{
|
|
|
|
if (!index.isValid())
|
|
|
|
return QVariant();
|
|
|
|
|
|
|
|
if (index.column() == 1 && role == Qt::EditRole) {
|
|
|
|
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
|
|
return item->data(index.column());
|
|
|
|
}
|
|
|
|
|
2010-04-09 10:58:38 +00:00
|
|
|
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
2010-04-07 18:38:20 +00:00
|
|
|
|
2010-04-12 05:54:54 +00:00
|
|
|
if (index.column() == 0 && role == Qt::BackgroundRole) {
|
|
|
|
DataObjectTreeItem *dataItem = dynamic_cast<DataObjectTreeItem*>(item);
|
|
|
|
if (dataItem && dataItem->highlight())
|
|
|
|
return QVariant(QColor(255, 230, 230));
|
|
|
|
}
|
2010-04-09 10:58:38 +00:00
|
|
|
if (index.column() == 1 && role == Qt::BackgroundRole) {
|
|
|
|
FieldTreeItem *fieldItem = dynamic_cast<FieldTreeItem*>(item);
|
2010-04-12 05:54:54 +00:00
|
|
|
if (fieldItem && fieldItem->highlight())
|
|
|
|
return QVariant(QColor(255, 230, 230));
|
2010-04-09 10:58:38 +00:00
|
|
|
if (fieldItem && fieldItem->isChanged())
|
|
|
|
return QVariant(QColor(230, 230, 255));
|
|
|
|
}
|
2010-04-07 18:38:20 +00:00
|
|
|
|
|
|
|
if (role != Qt::DisplayRole)
|
|
|
|
return QVariant();
|
|
|
|
|
|
|
|
if (index.column() == 1) {
|
|
|
|
EnumFieldTreeItem *fieldItem = dynamic_cast<EnumFieldTreeItem*>(item);
|
|
|
|
if (fieldItem) {
|
|
|
|
int enumIndex = fieldItem->data(index.column()).toInt();
|
|
|
|
return fieldItem->enumOptions.at(enumIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return item->data(index.column());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool UAVObjectTreeModel::setData(const QModelIndex &index, const QVariant & value, int role)
|
|
|
|
{
|
|
|
|
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
2010-04-12 05:54:54 +00:00
|
|
|
item->setData(value, index.column());
|
2010-04-07 18:38:20 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Qt::ItemFlags UAVObjectTreeModel::flags(const QModelIndex &index) const
|
|
|
|
{
|
|
|
|
if (!index.isValid())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (index.column() == 1) {
|
|
|
|
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
|
|
if (item->isEditable())
|
|
|
|
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant UAVObjectTreeModel::headerData(int section, Qt::Orientation orientation,
|
|
|
|
int role) const
|
|
|
|
{
|
|
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
|
|
|
return rootItem->data(section);
|
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
2010-04-12 05:54:54 +00:00
|
|
|
void UAVObjectTreeModel::highlightUpdatedObject(UAVObject *object)
|
|
|
|
{
|
|
|
|
UAVDataObject *obj = qobject_cast<UAVDataObject*>(object);
|
|
|
|
if (!obj)
|
|
|
|
return;
|
|
|
|
DataObjectTreeItem * dobj = findDataObjectTreeItem(obj);
|
|
|
|
if (dobj) {
|
|
|
|
dobj->setHighlight(true);
|
|
|
|
dobj->update();
|
|
|
|
emit dataChanged(QModelIndex(), QModelIndex());
|
|
|
|
}
|
|
|
|
|
|
|
|
// any updates while highlighted will not reset timer
|
|
|
|
if (m_timerMap.contains(obj))
|
|
|
|
return;
|
|
|
|
|
|
|
|
QTimer *timer = new QTimer(this);
|
|
|
|
timer->setSingleShot(true);
|
|
|
|
|
|
|
|
m_timerMap.insert(obj, timer);
|
|
|
|
connect(timer, SIGNAL(timeout()), m_signalMapper, SLOT(map()));
|
|
|
|
m_signalMapper->setMapping(timer, obj);
|
|
|
|
timer->start(500);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAVObjectTreeModel::resetHighlightObject(QObject *object)
|
|
|
|
{
|
|
|
|
UAVDataObject *obj = qobject_cast<UAVDataObject*>(object);
|
|
|
|
if (!obj)
|
|
|
|
return;
|
|
|
|
QTimer *timer = m_timerMap.value(obj);
|
|
|
|
delete timer;
|
|
|
|
m_timerMap.remove(obj);
|
|
|
|
|
|
|
|
DataObjectTreeItem * dobj = findDataObjectTreeItem(obj);
|
|
|
|
if (dobj) {
|
|
|
|
dobj->setHighlight(false);
|
|
|
|
dobj->update();
|
|
|
|
emit dataChanged(QModelIndex(), QModelIndex());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DataObjectTreeItem *UAVObjectTreeModel::findDataObjectTreeItem(UAVDataObject *obj)
|
|
|
|
{
|
|
|
|
TopTreeItem *root = obj->isSettings() ? m_settingsTree : m_nonSettingsTree;
|
|
|
|
foreach (TreeItem *child, root->children()) {
|
|
|
|
DataObjectTreeItem *dobj = dynamic_cast<DataObjectTreeItem*>(child);
|
|
|
|
if (dobj && dobj->object() && dobj->object()->isSingleInstance()) {
|
|
|
|
if(dobj->object() == obj) {
|
|
|
|
return dobj;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach (TreeItem *c, dobj->children()) {
|
|
|
|
DataObjectTreeItem *d = dynamic_cast<DataObjectTreeItem*>(c);
|
|
|
|
if (d && d->object() == obj)
|
|
|
|
return dobj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|