1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-19 04:52:12 +01:00

Merge branch 'next' into LP-295_OP-1900_fixedwingautotakeoff_rebasenext

This commit is contained in:
Corvus Corax 2016-04-25 17:22:21 +02:00
commit 5bd491ac57
7 changed files with 333 additions and 132 deletions

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file browseritemdelegate.cpp * @file browseritemdelegate.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup UAVObjectBrowserPlugin UAVObject Browser Plugin * @addtogroup UAVObjectBrowserPlugin UAVObject Browser Plugin
@ -34,20 +35,19 @@ BrowserItemDelegate::BrowserItemDelegate(QObject *parent) :
QWidget *BrowserItemDelegate::createEditor(QWidget *parent, QWidget *BrowserItemDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem & option, const QStyleOptionViewItem & option,
const QModelIndex & index) const const QModelIndex &index) const
{ {
Q_UNUSED(option) Q_UNUSED(option)
FieldTreeItem * item = static_cast<FieldTreeItem *>(index.internalPointer()); FieldTreeItem * item = static_cast<FieldTreeItem *>(index.data(Qt::UserRole).value<void *>());
QWidget *editor = item->createEditor(parent); QWidget *editor = item->createEditor(parent);
Q_ASSERT(editor); Q_ASSERT(editor);
return editor; return editor;
} }
void BrowserItemDelegate::setEditorData(QWidget *editor, void BrowserItemDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const const QModelIndex &index) const
{ {
FieldTreeItem *item = static_cast<FieldTreeItem *>(index.internalPointer()); FieldTreeItem *item = static_cast<FieldTreeItem *>(index.data(Qt::UserRole).value<void *>());
QVariant value = index.model()->data(index, Qt::EditRole); QVariant value = index.model()->data(index, Qt::EditRole);
item->setEditorValue(editor, value); item->setEditorValue(editor, value);
@ -56,15 +56,18 @@ void BrowserItemDelegate::setEditorData(QWidget *editor,
void BrowserItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, void BrowserItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const const QModelIndex &index) const
{ {
FieldTreeItem *item = static_cast<FieldTreeItem *>(index.internalPointer()); FieldTreeItem *item = static_cast<FieldTreeItem *>(index.data(Qt::UserRole).value<void *>());
QVariant value = item->getEditorValue(editor); QVariant value = item->getEditorValue(editor);
model->setData(index, value, Qt::EditRole); bool ret = model->setData(index, value, Qt::EditRole);
Q_ASSERT(ret);
} }
void BrowserItemDelegate::updateEditorGeometry(QWidget *editor, void BrowserItemDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex & /* index */) const const QStyleOptionViewItem &option, const QModelIndex &index) const
{ {
Q_UNUSED(index);
editor->setGeometry(option.rect); editor->setGeometry(option.rect);
} }

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file browseritemdelegate.h * @file browseritemdelegate.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup UAVObjectBrowserPlugin UAVObject Browser Plugin * @addtogroup UAVObjectBrowserPlugin UAVObject Browser Plugin
@ -46,11 +47,6 @@ public:
const QStyleOptionViewItem &option, const QModelIndex &index) const; const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem & option, QSize sizeHint(const QStyleOptionViewItem & option,
const QModelIndex &index) const; const QModelIndex &index) const;
signals:
public slots:
}; };
#endif // BROWSERITEMDELEGATE_H #endif // BROWSERITEMDELEGATE_H

View File

@ -259,7 +259,7 @@ public:
DataObjectTreeItem *findDataObjectTreeItemByObjectId(quint32 objectId) DataObjectTreeItem *findDataObjectTreeItemByObjectId(quint32 objectId)
{ {
return m_objectTreeItemsPerObjectIds.contains(objectId) ? m_objectTreeItemsPerObjectIds[objectId] : 0; return m_objectTreeItemsPerObjectIds.value(objectId, 0);
} }
void addMetaObjectTreeItem(quint32 objectId, MetaObjectTreeItem *oti) void addMetaObjectTreeItem(quint32 objectId, MetaObjectTreeItem *oti)
@ -269,7 +269,7 @@ public:
MetaObjectTreeItem *findMetaObjectTreeItemByObjectId(quint32 objectId) MetaObjectTreeItem *findMetaObjectTreeItemByObjectId(quint32 objectId)
{ {
return m_metaObjectTreeItemsPerObjectIds.contains(objectId) ? m_metaObjectTreeItemsPerObjectIds[objectId] : 0; return m_metaObjectTreeItemsPerObjectIds.value(objectId, 0);
} }
QList<MetaObjectTreeItem *> getMetaObjectItems(); QList<MetaObjectTreeItem *> getMetaObjectItems();

View File

@ -204,6 +204,40 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="searchLine">
<property name="placeholderText">
<string>type filter text</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="searchClearButton">
<property name="text">
<string>Clear</string>
</property>
<property name="icon">
<iconset theme="fileclose">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_3"> <spacer name="horizontalSpacer_3">
<property name="orientation"> <property name="orientation">
@ -273,6 +307,7 @@
<string>This space shows a description of the selected UAVObject.</string> <string>This space shows a description of the selected UAVObject.</string>
</property> </property>
</widget> </widget>
<widget class="QLineEdit" name="lineEdit"/>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -2,7 +2,9 @@
****************************************************************************** ******************************************************************************
* *
* @file uavobjectbrowserwidget.cpp * @file uavobjectbrowserwidget.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
* Tau Labs, http://taulabs.org, Copyright (C) 2013
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup UAVObjectBrowserPlugin UAVObject Browser Plugin * @addtogroup UAVObjectBrowserPlugin UAVObject Browser Plugin
@ -43,39 +45,54 @@
UAVObjectBrowserWidget::UAVObjectBrowserWidget(QWidget *parent) : QWidget(parent) UAVObjectBrowserWidget::UAVObjectBrowserWidget(QWidget *parent) : QWidget(parent)
{ {
m_browser = new Ui_UAVObjectBrowser();
m_viewoptions = new Ui_viewoptions();
m_viewoptionsDialog = new QDialog(this); m_viewoptionsDialog = new QDialog(this);
m_viewoptions = new Ui_viewoptions();
m_viewoptions->setupUi(m_viewoptionsDialog); m_viewoptions->setupUi(m_viewoptionsDialog);
m_model = new UAVObjectTreeModel(this);
m_modelProxy = new TreeSortFilterProxyModel(this);
m_modelProxy->setSourceModel(m_model);
m_modelProxy->setDynamicSortFilter(true);
m_browser = new Ui_UAVObjectBrowser();
m_browser->setupUi(this); m_browser->setupUi(this);
m_model = new UAVObjectTreeModel(); m_browser->treeView->setModel(m_modelProxy);
m_browser->treeView->setModel(m_model);
m_browser->treeView->setColumnWidth(0, 300); m_browser->treeView->setColumnWidth(0, 300);
BrowserItemDelegate *m_delegate = new BrowserItemDelegate(); m_browser->treeView->setItemDelegate(new BrowserItemDelegate());
m_browser->treeView->setItemDelegate(m_delegate);
m_browser->treeView->setEditTriggers(QAbstractItemView::AllEditTriggers); m_browser->treeView->setEditTriggers(QAbstractItemView::AllEditTriggers);
m_browser->treeView->setSelectionBehavior(QAbstractItemView::SelectItems); m_browser->treeView->setSelectionBehavior(QAbstractItemView::SelectItems);
m_mustacheTemplate = loadFileIntoString(QString(":/uavobjectbrowser/resources/uavodescription.mustache")); m_mustacheTemplate = loadFileIntoString(QString(":/uavobjectbrowser/resources/uavodescription.mustache"));
showMetaData(m_viewoptions->cbMetaData->isChecked()); showMetaData(m_viewoptions->cbMetaData->isChecked());
showDescription(m_viewoptions->cbDescription->isChecked()); showDescription(m_viewoptions->cbDescription->isChecked());
connect(m_browser->treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), connect(m_browser->treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
this, SLOT(currentChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection); this, SLOT(currentChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection);
connect(m_viewoptions->cbMetaData, SIGNAL(toggled(bool)), this, SLOT(showMetaData(bool)));
connect(m_viewoptions->cbCategorized, SIGNAL(toggled(bool)), this, SLOT(categorize(bool)));
connect(m_viewoptions->cbDescription, SIGNAL(toggled(bool)), this, SLOT(showDescription(bool)));
connect(m_browser->saveSDButton, SIGNAL(clicked()), this, SLOT(saveObject())); connect(m_browser->saveSDButton, SIGNAL(clicked()), this, SLOT(saveObject()));
connect(m_browser->readSDButton, SIGNAL(clicked()), this, SLOT(loadObject())); connect(m_browser->readSDButton, SIGNAL(clicked()), this, SLOT(loadObject()));
connect(m_browser->eraseSDButton, SIGNAL(clicked()), this, SLOT(eraseObject()));
connect(m_browser->sendButton, SIGNAL(clicked()), this, SLOT(sendUpdate())); connect(m_browser->sendButton, SIGNAL(clicked()), this, SLOT(sendUpdate()));
connect(m_browser->requestButton, SIGNAL(clicked()), this, SLOT(requestUpdate())); connect(m_browser->requestButton, SIGNAL(clicked()), this, SLOT(requestUpdate()));
connect(m_browser->eraseSDButton, SIGNAL(clicked()), this, SLOT(eraseObject()));
connect(m_browser->tbView, SIGNAL(clicked()), this, SLOT(viewSlot())); connect(m_browser->tbView, SIGNAL(clicked()), this, SLOT(viewSlot()));
connect(m_browser->splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(splitterMoved()));
connect(m_viewoptions->cbMetaData, SIGNAL(toggled(bool)), this, SLOT(showMetaData(bool)));
connect(m_viewoptions->cbMetaData, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
connect(m_viewoptions->cbCategorized, SIGNAL(toggled(bool)), this, SLOT(categorize(bool)));
connect(m_viewoptions->cbCategorized, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
connect(m_viewoptions->cbDescription, SIGNAL(toggled(bool)), this, SLOT(showDescription(bool)));
connect(m_viewoptions->cbDescription, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
connect(m_viewoptions->cbScientific, SIGNAL(toggled(bool)), this, SLOT(useScientificNotation(bool))); connect(m_viewoptions->cbScientific, SIGNAL(toggled(bool)), this, SLOT(useScientificNotation(bool)));
connect(m_viewoptions->cbScientific, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot())); connect(m_viewoptions->cbScientific, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
connect(m_viewoptions->cbMetaData, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
connect(m_viewoptions->cbCategorized, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot())); // search field and button
connect(m_viewoptions->cbDescription, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot())); connect(m_browser->searchLine, SIGNAL(textChanged(QString)), this, SLOT(searchLineChanged(QString)));
connect(m_browser->splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(splitterMoved())); connect(m_browser->searchClearButton, SIGNAL(clicked(bool)), this, SLOT(searchTextCleared()));
enableSendRequest(false); enableSendRequest(false);
} }
@ -99,9 +116,12 @@ void UAVObjectBrowserWidget::setSplitterState(QByteArray state)
void UAVObjectBrowserWidget::showMetaData(bool show) void UAVObjectBrowserWidget::showMetaData(bool show)
{ {
// TODO update the model directly instead of hiding rows...
QList<QModelIndex> metaIndexes = m_model->getMetaDataIndexes(); QList<QModelIndex> metaIndexes = m_model->getMetaDataIndexes();
foreach(QModelIndex index, metaIndexes) { foreach(QModelIndex modelIndex, metaIndexes) {
m_browser->treeView->setRowHidden(index.row(), index.parent(), !show); QModelIndex proxyModelIndex = m_modelProxy->mapFromSource(modelIndex);
m_browser->treeView->setRowHidden(proxyModelIndex.row(), proxyModelIndex.parent(), !show);
} }
} }
@ -112,62 +132,82 @@ void UAVObjectBrowserWidget::showDescription(bool show)
void UAVObjectBrowserWidget::categorize(bool categorize) void UAVObjectBrowserWidget::categorize(bool categorize)
{ {
// TODO we should update the model instead of rebuilding it
// a side effect of rebuilding is that some state is lost (expand state, ...)
UAVObjectTreeModel *model = new UAVObjectTreeModel(0, categorize, m_viewoptions->cbScientific->isChecked());
model->setRecentlyUpdatedColor(m_recentlyUpdatedColor);
model->setManuallyChangedColor(m_manuallyChangedColor);
model->setRecentlyUpdatedTimeout(m_recentlyUpdatedTimeout);
model->setOnlyHilightChangedValues(m_onlyHilightChangedValues);
model->setUnknowObjectColor(m_unknownObjectColor);
UAVObjectTreeModel *tmpModel = m_model; UAVObjectTreeModel *tmpModel = m_model;
m_model = model;
m_model = new UAVObjectTreeModel(0, categorize, m_viewoptions->cbScientific->isChecked()); m_modelProxy->setSourceModel(m_model);
m_model->setRecentlyUpdatedColor(m_recentlyUpdatedColor);
m_model->setManuallyChangedColor(m_manuallyChangedColor);
m_model->setRecentlyUpdatedTimeout(m_recentlyUpdatedTimeout);
m_model->setOnlyHilightChangedValues(m_onlyHilightChangedValues);
m_model->setUnknowObjectColor(m_unknownObjectColor);
m_browser->treeView->setModel(m_model);
showMetaData(m_viewoptions->cbMetaData->isChecked());
connect(m_browser->treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection);
delete tmpModel; delete tmpModel;
showMetaData(m_viewoptions->cbMetaData->isChecked());
// force an expand all if search text is not empty
if (!m_browser->searchLine->text().isEmpty()) {
searchLineChanged(m_browser->searchLine->text());
}
} }
void UAVObjectBrowserWidget::useScientificNotation(bool scientific) void UAVObjectBrowserWidget::useScientificNotation(bool scientific)
{ {
// TODO we should update the model instead of rebuilding it
// a side effect of rebuilding is that some state is lost (expand state, ...)
UAVObjectTreeModel *model = new UAVObjectTreeModel(0, m_viewoptions->cbCategorized->isChecked(), scientific);
model->setManuallyChangedColor(m_manuallyChangedColor);
model->setRecentlyUpdatedTimeout(m_recentlyUpdatedTimeout);
model->setUnknowObjectColor(m_unknownObjectColor);
UAVObjectTreeModel *tmpModel = m_model; UAVObjectTreeModel *tmpModel = m_model;
m_model = model;
m_model = new UAVObjectTreeModel(0, m_viewoptions->cbCategorized->isChecked(), scientific); m_modelProxy->setSourceModel(m_model);
m_model->setRecentlyUpdatedColor(m_recentlyUpdatedColor);
m_model->setManuallyChangedColor(m_manuallyChangedColor);
m_model->setRecentlyUpdatedTimeout(m_recentlyUpdatedTimeout);
m_model->setUnknowObjectColor(m_unknownObjectColor);
m_browser->treeView->setModel(m_model);
showMetaData(m_viewoptions->cbMetaData->isChecked());
connect(m_browser->treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection);
delete tmpModel; delete tmpModel;
showMetaData(m_viewoptions->cbMetaData->isChecked());
// force an expand all if search text is not empty
if (!m_browser->searchLine->text().isEmpty()) {
searchLineChanged(m_browser->searchLine->text());
}
} }
void UAVObjectBrowserWidget::sendUpdate() void UAVObjectBrowserWidget::sendUpdate()
{ {
// TODO why steal focus ?
this->setFocus(); this->setFocus();
ObjectTreeItem *objItem = findCurrentObjectTreeItem(); ObjectTreeItem *objItem = findCurrentObjectTreeItem();
Q_ASSERT(objItem);
objItem->apply(); if (objItem != NULL) {
UAVObject *obj = objItem->object(); objItem->apply();
Q_ASSERT(obj); UAVObject *obj = objItem->object();
obj->updated(); Q_ASSERT(obj);
obj->updated();
}
} }
void UAVObjectBrowserWidget::requestUpdate() void UAVObjectBrowserWidget::requestUpdate()
{ {
ObjectTreeItem *objItem = findCurrentObjectTreeItem(); ObjectTreeItem *objItem = findCurrentObjectTreeItem();
Q_ASSERT(objItem); if (objItem != NULL) {
UAVObject *obj = objItem->object(); UAVObject *obj = objItem->object();
Q_ASSERT(obj); Q_ASSERT(obj);
obj->requestUpdate(); obj->requestUpdate();
}
} }
ObjectTreeItem *UAVObjectBrowserWidget::findCurrentObjectTreeItem() ObjectTreeItem *UAVObjectBrowserWidget::findCurrentObjectTreeItem()
{ {
QModelIndex current = m_browser->treeView->currentIndex(); QModelIndex current = m_browser->treeView->currentIndex();
TreeItem *item = static_cast<TreeItem *>(current.internalPointer()); TreeItem *item = static_cast<TreeItem *>(current.data(Qt::UserRole).value<void *>());
ObjectTreeItem *objItem = 0; ObjectTreeItem *objItem = 0;
while (item) { while (item) {
@ -193,15 +233,20 @@ QString UAVObjectBrowserWidget::loadFileIntoString(QString fileName)
void UAVObjectBrowserWidget::saveObject() void UAVObjectBrowserWidget::saveObject()
{ {
// TODO why steal focus ?
this->setFocus(); this->setFocus();
// Send update so that the latest value is saved // Send update so that the latest value is saved
sendUpdate(); sendUpdate();
// Save object // Save object
ObjectTreeItem *objItem = findCurrentObjectTreeItem(); ObjectTreeItem *objItem = findCurrentObjectTreeItem();
Q_ASSERT(objItem);
UAVObject *obj = objItem->object(); if (objItem != NULL) {
Q_ASSERT(obj); UAVObject *obj = objItem->object();
updateObjectPersistance(ObjectPersistence::OPERATION_SAVE, obj); Q_ASSERT(obj);
updateObjectPersistance(ObjectPersistence::OPERATION_SAVE, obj);
}
} }
void UAVObjectBrowserWidget::loadObject() void UAVObjectBrowserWidget::loadObject()
@ -209,22 +254,24 @@ void UAVObjectBrowserWidget::loadObject()
// Load object // Load object
ObjectTreeItem *objItem = findCurrentObjectTreeItem(); ObjectTreeItem *objItem = findCurrentObjectTreeItem();
Q_ASSERT(objItem); if (objItem != NULL) {
UAVObject *obj = objItem->object(); UAVObject *obj = objItem->object();
Q_ASSERT(obj); Q_ASSERT(obj);
updateObjectPersistance(ObjectPersistence::OPERATION_LOAD, obj); updateObjectPersistance(ObjectPersistence::OPERATION_LOAD, obj);
// Retrieve object so that latest value is displayed // Retrieve object so that latest value is displayed
requestUpdate(); requestUpdate();
}
} }
void UAVObjectBrowserWidget::eraseObject() void UAVObjectBrowserWidget::eraseObject()
{ {
ObjectTreeItem *objItem = findCurrentObjectTreeItem(); ObjectTreeItem *objItem = findCurrentObjectTreeItem();
Q_ASSERT(objItem); if (objItem != NULL) {
UAVObject *obj = objItem->object(); UAVObject *obj = objItem->object();
Q_ASSERT(obj); Q_ASSERT(obj);
updateObjectPersistance(ObjectPersistence::OPERATION_DELETE, obj); updateObjectPersistance(ObjectPersistence::OPERATION_DELETE, obj);
}
} }
void UAVObjectBrowserWidget::updateObjectPersistance(ObjectPersistence::OperationOptions op, UAVObject *obj) void UAVObjectBrowserWidget::updateObjectPersistance(ObjectPersistence::OperationOptions op, UAVObject *obj)
@ -248,9 +295,9 @@ void UAVObjectBrowserWidget::currentChanged(const QModelIndex &current, const QM
{ {
Q_UNUSED(previous); Q_UNUSED(previous);
TreeItem *item = static_cast<TreeItem *>(current.internalPointer()); TreeItem *item = static_cast<TreeItem *>(current.data(Qt::UserRole).value<void *>());
bool enable = true; bool enable = true;
if (current == QModelIndex()) { if (!current.isValid()) {
enable = false; enable = false;
} }
TopTreeItem *top = dynamic_cast<TopTreeItem *>(item); TopTreeItem *top = dynamic_cast<TopTreeItem *>(item);
@ -388,3 +435,94 @@ void UAVObjectBrowserWidget::updateDescription()
} }
m_browser->descriptionText->setText(""); m_browser->descriptionText->setText("");
} }
/**
* @brief UAVObjectBrowserWidget::searchTextChanged Looks for matching text in the UAVO fields
*/
void UAVObjectBrowserWidget::searchLineChanged(QString searchText)
{
m_modelProxy->setFilterRegExp(QRegExp(searchText, Qt::CaseInsensitive, QRegExp::FixedString));
if (!searchText.isEmpty()) {
m_browser->treeView->expandAll();
} else {
m_browser->treeView->collapseAll();
}
}
void UAVObjectBrowserWidget::searchTextCleared()
{
m_browser->searchLine->clear();
}
TreeSortFilterProxyModel::TreeSortFilterProxyModel(QObject *p) :
QSortFilterProxyModel(p)
{
Q_ASSERT(p);
}
/**
* @brief TreeSortFilterProxyModel::filterAcceptsRow Taken from
* http://qt-project.org/forums/viewthread/7782. This proxy model
* will accept rows:
* - That match themselves, or
* - That have a parent that matches (on its own), or
* - That have a child that matches.
* @param sourceRow
* @param sourceParent
* @return
*/
bool TreeSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (filterAcceptsRowItself(source_row, source_parent)) {
return true;
}
// accept if any of the parents is accepted on it's own merits
QModelIndex parent = source_parent;
while (parent.isValid()) {
if (filterAcceptsRowItself(parent.row(), parent.parent())) {
return true;
}
parent = parent.parent();
}
// accept if any of the children is accepted on it's own merits
if (hasAcceptedChildren(source_row, source_parent)) {
return true;
}
return false;
}
bool TreeSortFilterProxyModel::filterAcceptsRowItself(int source_row, const QModelIndex &source_parent) const
{
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
bool TreeSortFilterProxyModel::hasAcceptedChildren(int source_row, const QModelIndex &source_parent) const
{
QModelIndex item = sourceModel()->index(source_row, 0, source_parent);
if (!item.isValid()) {
return false;
}
// check if there are children
int childCount = item.model()->rowCount(item);
if (childCount == 0) {
return false;
}
for (int i = 0; i < childCount; ++i) {
if (filterAcceptsRowItself(i, item)) {
return true;
}
if (hasAcceptedChildren(i, item)) {
return true;
}
}
return false;
}

View File

@ -2,7 +2,9 @@
****************************************************************************** ******************************************************************************
* *
* @file uavobjectbrowserwidget.h * @file uavobjectbrowserwidget.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
* Tau Labs, http://taulabs.org, Copyright (C) 2013
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup UAVObjectBrowserPlugin UAVObject Browser Plugin * @addtogroup UAVObjectBrowserPlugin UAVObject Browser Plugin
@ -28,16 +30,30 @@
#ifndef UAVOBJECTBROWSERWIDGET_H_ #ifndef UAVOBJECTBROWSERWIDGET_H_
#define UAVOBJECTBROWSERWIDGET_H_ #define UAVOBJECTBROWSERWIDGET_H_
#include "uavobjecttreemodel.h"
#include "objectpersistence.h"
#include <QWidget> #include <QWidget>
#include <QTreeView> #include <QTreeView>
#include "objectpersistence.h" #include <QKeyEvent>
#include "uavobjecttreemodel.h" #include <QSortFilterProxyModel>
class QPushButton; class QPushButton;
class ObjectTreeItem; class ObjectTreeItem;
class Ui_UAVObjectBrowser; class Ui_UAVObjectBrowser;
class Ui_viewoptions; class Ui_viewoptions;
class TreeSortFilterProxyModel : public QSortFilterProxyModel {
public:
TreeSortFilterProxyModel(QObject *parent);
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
bool filterAcceptsRowItself(int source_row, const QModelIndex &source_parent) const;
bool hasAcceptedChildren(int source_row, const QModelIndex &source_parent) const;
};
class UAVObjectBrowserWidget : public QWidget { class UAVObjectBrowserWidget : public QWidget {
Q_OBJECT Q_OBJECT
@ -72,6 +88,7 @@ public:
} }
void setViewOptions(bool categorized, bool scientific, bool metadata, bool description); void setViewOptions(bool categorized, bool scientific, bool metadata, bool description);
void setSplitterState(QByteArray state); void setSplitterState(QByteArray state);
public slots: public slots:
void showMetaData(bool show); void showMetaData(bool show);
void showDescription(bool show); void showDescription(bool show);
@ -87,18 +104,21 @@ private slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous); void currentChanged(const QModelIndex &current, const QModelIndex &previous);
void viewSlot(); void viewSlot();
void viewOptionsChangedSlot(); void viewOptionsChangedSlot();
void searchLineChanged(QString searchText);
void searchTextCleared();
void splitterMoved(); void splitterMoved();
QString createObjectDescription(UAVObject *object); QString createObjectDescription(UAVObject *object);
signals: signals:
void viewOptionsChanged(bool categorized, bool scientific, bool metadata, bool description); void viewOptionsChanged(bool categorized, bool scientific, bool metadata, bool description);
void splitterChanged(QByteArray state); void splitterChanged(QByteArray state);
private: private:
QPushButton *m_requestUpdate;
QPushButton *m_sendUpdate;
Ui_UAVObjectBrowser *m_browser; Ui_UAVObjectBrowser *m_browser;
Ui_viewoptions *m_viewoptions; Ui_viewoptions *m_viewoptions;
QDialog *m_viewoptionsDialog; QDialog *m_viewoptionsDialog;
UAVObjectTreeModel *m_model; UAVObjectTreeModel *m_model;
TreeSortFilterProxyModel *m_modelProxy;
int m_recentlyUpdatedTimeout; int m_recentlyUpdatedTimeout;
QColor m_unknownObjectColor; QColor m_unknownObjectColor;

View File

@ -68,20 +68,23 @@ UAVObjectTreeModel::~UAVObjectTreeModel()
void UAVObjectTreeModel::setupModelData(UAVObjectManager *objManager) void UAVObjectTreeModel::setupModelData(UAVObjectManager *objManager)
{ {
m_settingsTree = new TopTreeItem(tr("Settings"));
m_settingsTree->setHighlightManager(m_highlightManager);
connect(m_settingsTree, SIGNAL(updateHighlight(TreeItem *)), this, SLOT(updateHighlight(TreeItem *)));
m_nonSettingsTree = new TopTreeItem(tr("Data Objects"));
m_nonSettingsTree->setHighlightManager(m_highlightManager);
connect(m_nonSettingsTree, SIGNAL(updateHighlight(TreeItem *)), this, SLOT(updateHighlight(TreeItem *)));
// root // root
QList<QVariant> rootData; QList<QVariant> rootData;
rootData << tr("Property") << tr("Value") << tr("Unit"); rootData << tr("Property") << tr("Value") << tr("Unit");
m_rootItem = new TreeItem(rootData); m_rootItem = new TreeItem(rootData);
m_settingsTree = new TopTreeItem(tr("Settings"), m_rootItem);
m_settingsTree->setHighlightManager(m_highlightManager);
m_rootItem->appendChild(m_settingsTree);
m_nonSettingsTree = new TopTreeItem(tr("Data Objects"), m_rootItem);
m_nonSettingsTree->setHighlightManager(m_highlightManager);
m_rootItem->appendChild(m_nonSettingsTree);
m_rootItem->setHighlightManager(m_highlightManager); m_rootItem->setHighlightManager(m_highlightManager);
connect(m_settingsTree, SIGNAL(updateHighlight(TreeItem *)), this, SLOT(updateHighlight(TreeItem *)));
connect(m_nonSettingsTree, SIGNAL(updateHighlight(TreeItem *)), this, SLOT(updateHighlight(TreeItem *))); // tree item takes ownership of its children
m_rootItem->appendChild(m_settingsTree);
m_rootItem->appendChild(m_nonSettingsTree);
QList< QList<UAVDataObject *> > objList = objManager->getDataObjects(); QList< QList<UAVDataObject *> > objList = objManager->getDataObjects();
foreach(QList<UAVDataObject *> list, objList) { foreach(QList<UAVDataObject *> list, objList) {
@ -258,8 +261,7 @@ void UAVObjectTreeModel::addSingleField(int index, UAVObjectField *field, TreeIt
parent->appendChild(item); parent->appendChild(item);
} }
QModelIndex UAVObjectTreeModel::index(int row, int column, const QModelIndex &parent) QModelIndex UAVObjectTreeModel::index(int row, int column, const QModelIndex &parent) const
const
{ {
if (!hasIndex(row, column, parent)) { if (!hasIndex(row, column, parent)) {
return QModelIndex(); return QModelIndex();
@ -306,10 +308,11 @@ QModelIndex UAVObjectTreeModel::parent(const QModelIndex &index) const
return QModelIndex(); return QModelIndex();
} }
TreeItem *childItem = static_cast<TreeItem *>(index.internalPointer()); TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
TreeItem *parentItem = childItem->parent();
if (parentItem == m_rootItem) { TreeItem *parentItem = item->parent();
if (!parentItem) {
// item is root has no parent...
return QModelIndex(); return QModelIndex();
} }
@ -363,50 +366,56 @@ QVariant UAVObjectTreeModel::data(const QModelIndex &index, int role) const
TreeItem *item = static_cast<TreeItem *>(index.internalPointer()); TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
if (index.column() == TreeItem::DATA_COLUMN && role == Qt::EditRole) { switch (role) {
case Qt::DisplayRole:
if (index.column() == TreeItem::DATA_COLUMN) {
EnumFieldTreeItem *fieldItem = dynamic_cast<EnumFieldTreeItem *>(item);
if (fieldItem) {
int enumIndex = fieldItem->data(index.column()).toInt();
return fieldItem->enumOptions(enumIndex);
}
}
return item->data(index.column()); return item->data(index.column());
}
if (role == Qt::ToolTipRole) { case Qt::EditRole:
if (index.column() == TreeItem::DATA_COLUMN) {
return item->data(index.column());
}
return QVariant();
case Qt::ToolTipRole:
return item->description(); return item->description();
}
if (role == Qt::ForegroundRole) { case Qt::ForegroundRole:
if (!dynamic_cast<TopTreeItem *>(item) && !item->isKnown()) { if (!dynamic_cast<TopTreeItem *>(item) && !item->isKnown()) {
return QVariant(m_unknownObjectColor); return m_unknownObjectColor;
} }
} return QVariant();
if (index.column() == 0 && role == Qt::BackgroundRole) { case Qt::BackgroundRole:
if (!dynamic_cast<TopTreeItem *>(item) && item->highlighted()) { if (index.column() == TreeItem::TITLE_COLUMN) {
return QVariant(m_recentlyUpdatedColor); if (!dynamic_cast<TopTreeItem *>(item) && item->highlighted()) {
return m_recentlyUpdatedColor;
}
} else if (index.column() == TreeItem::DATA_COLUMN) {
FieldTreeItem *fieldItem = dynamic_cast<FieldTreeItem *>(item);
if (fieldItem && fieldItem->highlighted()) {
return m_recentlyUpdatedColor;
}
if (fieldItem && fieldItem->changed()) {
return m_manuallyChangedColor;
}
} }
} return QVariant();
if (index.column() == TreeItem::DATA_COLUMN && role == Qt::BackgroundRole) { case Qt::UserRole:
FieldTreeItem *fieldItem = dynamic_cast<FieldTreeItem *>(item); // UserRole gives access to TreeItem
if (fieldItem && fieldItem->highlighted()) { // cast to void* is necessary
return QVariant(m_recentlyUpdatedColor); return qVariantFromValue((void *)item);
}
if (fieldItem && fieldItem->changed()) { default:
return QVariant(m_manuallyChangedColor);
}
}
if (role != Qt::DisplayRole) {
return QVariant(); return QVariant();
} }
if (index.column() == TreeItem::DATA_COLUMN) {
EnumFieldTreeItem *fieldItem = dynamic_cast<EnumFieldTreeItem *>(item);
if (fieldItem) {
int enumIndex = fieldItem->data(index.column()).toInt();
return fieldItem->enumOptions(enumIndex);
}
}
return item->data(index.column());
} }
bool UAVObjectTreeModel::setData(const QModelIndex &index, const QVariant & value, int role) bool UAVObjectTreeModel::setData(const QModelIndex &index, const QVariant & value, int role)