Commit ff537957 authored by Valentin Platzgummer's avatar Valentin Platzgummer

QmlObjectVectorModel added and used inside WimaController, no speed improvement though

parent bdc59c26
This diff is collapsed.
......@@ -434,7 +434,8 @@ HEADERS += \
src/Wima/GeoUtilities.h \
src/Wima/TestPolygonCalculus.h \
src/Wima/testplanimetrycalculus.h \
src/Settings/WimaSettings.h
src/Settings/WimaSettings.h \
src/QmlControls/QmlObjectVectorModel.h
SOURCES += \
src/api/QGCCorePlugin.cc \
src/api/QGCOptions.cc \
......@@ -466,7 +467,8 @@ SOURCES += \
src/Wima/PolygonCalculus.cc \
src/Wima/TestPolygonCalculus.cpp \
src/Wima/testplanimetrycalculus.cpp \
src/Settings/WimaSettings.cc
src/Settings/WimaSettings.cc \
src/QmlControls/QmlObjectVectorModel.cc
#
# Unit Test specific configuration goes here (requires full debug build with all plugins)
......
#include "QmlObjectVectorModel.h"
#include <QDebug>
#include <QQmlEngine>
const int QmlObjectVectorModel::ObjectRole = Qt::UserRole;
const int QmlObjectVectorModel::TextRole = Qt::UserRole + 1;
QmlObjectVectorModel::QmlObjectVectorModel(QObject* parent)
: QAbstractListModel(parent)
, _dirty(false)
, _skipDirtyFirstItem(false)
{
}
int QmlObjectVectorModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return _objectList.count();
}
QVariant QmlObjectVectorModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
if (index.row() < 0 || index.row() >= _objectList.count()) {
return QVariant();
}
if (role == ObjectRole) {
return QVariant::fromValue(_objectList[index.row()]);
} else if (role == TextRole) {
return QVariant::fromValue(_objectList[index.row()]->objectName());
} else {
return QVariant();
}
}
QHash<int, QByteArray> QmlObjectVectorModel::roleNames(void) const
{
QHash<int, QByteArray> hash;
hash[ObjectRole] = "object";
hash[TextRole] = "text";
return hash;
}
bool QmlObjectVectorModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (index.isValid() && role == ObjectRole) {
_objectList.replace(index.row(), value.value<QObject*>());
emit dataChanged(index, index);
return true;
}
return false;
}
bool QmlObjectVectorModel::insertRows(int position, int rows, const QModelIndex& parent)
{
Q_UNUSED(parent);
if (position < 0 || position > _objectList.count() + 1) {
qWarning() << "Invalid position position:count" << position << _objectList.count();
}
beginInsertRows(QModelIndex(), position, position + rows - 1);
endInsertRows();
emit countChanged(count());
return true;
}
bool QmlObjectVectorModel::removeRows(int position, int rows, const QModelIndex& parent)
{
Q_UNUSED(parent);
if (position < 0 || position >= _objectList.count()) {
qWarning() << "Invalid position position:count" << position << _objectList.count();
} else if (position + rows > _objectList.count()) {
qWarning() << "Invalid rows position:rows:count" << position << rows << _objectList.count();
}
beginRemoveRows(QModelIndex(), position, position + rows - 1);
for (int row=0; row<rows; row++) {
_objectList.removeAt(position);
}
endRemoveRows();
emit countChanged(count());
return true;
}
QObject* QmlObjectVectorModel::operator[](int index)
{
if (index < 0 || index >= _objectList.count()) {
return NULL;
}
return _objectList[index];
}
const QObject* QmlObjectVectorModel::operator[](int index) const
{
if (index < 0 || index >= _objectList.count()) {
return NULL;
}
return _objectList[index];
}
void QmlObjectVectorModel::clear()
{
while (rowCount()) {
removeAt(0);
}
}
QObject* QmlObjectVectorModel::removeAt(int i)
{
QObject* removedObject = _objectList[i];
if(removedObject) {
// Look for a dirtyChanged signal on the object
if (_objectList[i]->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) {
if (!_skipDirtyFirstItem || i != 0) {
QObject::disconnect(_objectList[i], SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
}
}
}
removeRows(i, 1);
setDirty(true);
return removedObject;
}
void QmlObjectVectorModel::insert(int i, QObject* object)
{
if (i < 0 || i > _objectList.count()) {
qWarning() << "Invalid index index:count" << i << _objectList.count();
}
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
// Look for a dirtyChanged signal on the object
if (object->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) {
if (!_skipDirtyFirstItem || i != 0) {
QObject::connect(object, SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
}
}
_objectList.insert(i, object);
insertRows(i, 1);
setDirty(true);
}
void QmlObjectVectorModel::insert(int i, QVector<QObject*> objects)
{
if (i < 0 || i > _objectList.count()) {
qWarning() << "Invalid index index:count" << i << _objectList.count();
}
int j = i;
for (QObject* object: objects) {
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
// Look for a dirtyChanged signal on the object
if (object->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) {
if (!_skipDirtyFirstItem || j != 0) {
QObject::connect(object, SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
}
}
j++;
_objectList.insert(j, object);
}
insertRows(i, objects.count());
setDirty(true);
}
void QmlObjectVectorModel::append(QObject* object)
{
insert(_objectList.count(), object);
}
void QmlObjectVectorModel::append(QVector<QObject*> objects)
{
insert(_objectList.count(), objects);
}
QVector<QObject*> QmlObjectVectorModel::swapObjectList(const QVector<QObject*>& newlist)
{
QVector<QObject*> oldlist(_objectList);
beginResetModel();
_objectList = newlist;
endResetModel();
emit countChanged(count());
return oldlist;
}
int QmlObjectVectorModel::count() const
{
return rowCount();
}
void QmlObjectVectorModel::setDirty(bool dirty)
{
if (_dirty != dirty) {
_dirty = dirty;
if (!dirty) {
// Need to clear dirty from all children
for(QObject* object: _objectList) {
if (object->property("dirty").isValid()) {
object->setProperty("dirty", false);
}
}
}
emit dirtyChanged(_dirty);
}
}
void QmlObjectVectorModel::_childDirtyChanged(bool dirty)
{
_dirty |= dirty;
// We want to emit dirtyChanged even if the actual value of _dirty didn't change. It can be a useful
// signal to know when a child has changed dirty state
emit dirtyChanged(_dirty);
}
void QmlObjectVectorModel::deleteListAndContents()
{
for (int i=0; i<_objectList.count(); i++) {
_objectList[i]->deleteLater();
}
deleteLater();
}
void QmlObjectVectorModel::clearAndDeleteContents()
{
beginResetModel();
for (int i=0; i<_objectList.count(); i++) {
_objectList[i]->deleteLater();
}
clear();
endResetModel();
}
void swap(QmlObjectVectorModel &list1, QmlObjectVectorModel &list2)
{
using std::swap;
swap(list1._objectList, list2._objectList);
swap(list1._dirty, list2._dirty);
swap(list1._skipDirtyFirstItem, list2._skipDirtyFirstItem);
}
#pragma once
#include <QAbstractListModel>
class QmlObjectVectorModel : public QAbstractListModel
{
Q_OBJECT
public:
QmlObjectVectorModel(QObject* parent = nullptr);
Q_PROPERTY(int count READ count NOTIFY countChanged)
/// Returns true if any of the items in the list are dirty. Requires each object to have
/// a dirty property and dirtyChanged signal.
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
Q_INVOKABLE QObject* get(int index) { return _objectList[index]; }
// Property accessors
int count () const;
bool dirty () const { return _dirty; }
void setDirty (bool dirty);
void append (QObject* object);
void append (QVector<QObject*> objects);
QVector<QObject*> swapObjectList (const QVector<QObject*>& newlist);
void clear ();
QObject* removeAt (int i);
QObject* removeOne (QObject* object) { return removeAt(indexOf(object)); }
void insert (int i, QObject* object);
void insert (int i, QVector<QObject*> objects);
bool contains (QObject* object) { return _objectList.indexOf(object) != -1; }
int indexOf (QObject* object) { return _objectList.indexOf(object); }
QObject* operator[] (int i);
const QObject* operator[] (int i) const;
template<class T> T value (int index) { return qobject_cast<T>(_objectList[index]); }
QVector<QObject*>* objectList () { return &_objectList; }
/// Calls deleteLater on all items and this itself.
void deleteListAndContents ();
/// Clears the list and calls deleteLater on each entry
void clearAndDeleteContents ();
void beginReset () { beginResetModel(); }
void endReset () { endResetModel(); }
// Friends
friend void swap(QmlObjectVectorModel& list1, QmlObjectVectorModel& list2);
signals:
void countChanged (int count);
void dirtyChanged (bool dirtyChanged);
private slots:
void _childDirtyChanged (bool dirty);
private:
// Overrides from QAbstractListModel
int rowCount (const QModelIndex & parent = QModelIndex()) const override;
QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override;
bool insertRows (int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool removeRows (int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
QHash<int, QByteArray> roleNames(void) const override;
private:
QVector<QObject*> _objectList;
bool _dirty;
bool _skipDirtyFirstItem;
static const int ObjectRole;
static const int TextRole;
};
......@@ -35,7 +35,6 @@ CircularSurveyComplexItem::CircularSurveyComplexItem(Vehicle *vehicle, bool flyV
, _maxWaypoints (settingsGroup, _metaDataMap[maxWaypointsName])
, _isInitialized (false)
, _reverseOnly (false)
, _updateCounter (0)
{
Q_UNUSED(kmlOrShpFile)
_editorQml = "qrc:/qml/CircularSurveyItemEditor.qml";
......@@ -299,7 +298,6 @@ void CircularSurveyComplexItem::_rebuildTransectsFast()
using namespace PlanimetryCalculus;
_transects.clear();
_updateCounter++;
QPolygonF surveyPolygon = toQPolygonF(toCartesian2D(_surveyAreaPolygon.coordinateList(), _referencePoint));
if (!_rebuildTransectsInputCheck(surveyPolygon))
......@@ -360,8 +358,6 @@ void CircularSurveyComplexItem::_rebuildTransectsFast()
_rebuildTransectsToGeo(optiPath, _referencePoint);
_transectsDirty = true;
//_triggerSlowRecalcTimer.start(triggerTime);
qDebug() << "CircularSurveyComplexItem::_rebuildTransectsPhase1(): calls: " << _updateCounter;
}
......
......@@ -129,8 +129,6 @@ private:
bool _isInitialized; // indicates if the polygon and refpoint etc. are initialized, prevents reinitialisation from gui and execution of _rebuildTransectsPhase1 during init from gui
bool _reverseOnly; // if this is true _rebuildTransectsPhase1() will reverse the path only, _rebuildTransectsPhase1() resets _reverseOnly
bool _doFastRecalc; // fast recalc of transects if set, see _rebuildTransectsPhase1 for furhter explanation
int _updateCounter;
};
......
......@@ -65,7 +65,7 @@ WimaController::WimaController(QObject *parent)
enableDisableLowBatteryHandling(enableLowBatteryHandling->rawValue());
}
QmlObjectListModel* WimaController::visualItems()
QmlObjectVectorModel* WimaController::visualItems()
{
return &_visualItems;
}
......@@ -92,12 +92,12 @@ WimaDataContainer *WimaController::dataContainer()
return _container;
}
QmlObjectListModel *WimaController::missionItems()
QmlObjectVectorModel *WimaController::missionItems()
{
return &_missionItems;
}
QmlObjectListModel *WimaController::currentMissionItems()
QmlObjectVectorModel *WimaController::currentMissionItems()
{
return &_currentMissionItems;
}
......@@ -394,12 +394,12 @@ bool WimaController::calcShortestPath(const QGeoCoordinate &start, const QGeoCoo
return retVal;
}
bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVector<QGeoCoordinate> &coordinateList)
bool WimaController::extractCoordinateList(QmlObjectVectorModel &missionItems, QVector<QGeoCoordinate> &coordinateList)
{
return extractCoordinateList(missionItems, coordinateList, 0, missionItems.count()-1);
}
bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVector<QGeoCoordinate> &coordinateList, int startIndex, int endIndex)
bool WimaController::extractCoordinateList(QmlObjectVectorModel &missionItems, QVector<QGeoCoordinate> &coordinateList, int startIndex, int endIndex)
{
if ( startIndex >= 0
&& startIndex < missionItems.count()
......@@ -427,12 +427,12 @@ bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVe
return true;
}
bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVariantList &coordinateList)
bool WimaController::extractCoordinateList(QmlObjectVectorModel &missionItems, QVariantList &coordinateList)
{
return extractCoordinateList(missionItems, coordinateList, 0 , missionItems.count()-1);
}
bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVariantList &coordinateList, int startIndex, int endIndex)
bool WimaController::extractCoordinateList(QmlObjectVectorModel &missionItems, QVariantList &coordinateList, int startIndex, int endIndex)
{
QVector<QGeoCoordinate> geoCoordintateList;
......@@ -567,9 +567,10 @@ bool WimaController::fetchContainerData()
_nextPhaseStartWaypointIndex.setRawValue(reverse? _missionItems.count() : int(1));
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
/*
if(!calcNextPhase())
return false;
*/
emit visualItemsChanged();
......@@ -803,9 +804,10 @@ bool WimaController::calcNextPhase()
updateCurrentPath();
emit currentMissionItemsChanged();
qWarning() << "WimaController::calcNextPhase() exec time: "
<< std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now() - start).count() << " us";
qWarning() << "WimaController::calcNextPhase()"
<< std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now()-start).count()
<< " ms";
return true;
}
......
......@@ -2,7 +2,7 @@
#include <QObject>
#include "QGCMapPolygon.h"
#include "QmlObjectListModel.h"
#include "QmlObjectVectorModel.h"
#include "WimaArea.h"
#include "WimaMeasurementArea.h"
......@@ -37,14 +37,14 @@ public:
Q_PROPERTY(PlanMasterController* masterController READ masterController WRITE setMasterController NOTIFY masterControllerChanged)
Q_PROPERTY(MissionController* missionController READ missionController WRITE setMissionController NOTIFY missionControllerChanged)
Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged)
Q_PROPERTY(QmlObjectVectorModel* visualItems READ visualItems NOTIFY visualItemsChanged)
Q_PROPERTY(QString currentFile READ currentFile NOTIFY currentFileChanged)
Q_PROPERTY(QStringList loadNameFilters READ loadNameFilters CONSTANT)
Q_PROPERTY(QStringList saveNameFilters READ saveNameFilters CONSTANT)
Q_PROPERTY(QString fileExtension READ fileExtension CONSTANT)
Q_PROPERTY(WimaDataContainer* dataContainer READ dataContainer WRITE setDataContainer NOTIFY dataContainerChanged)
Q_PROPERTY(QmlObjectListModel* missionItems READ missionItems NOTIFY missionItemsChanged)
Q_PROPERTY(QmlObjectListModel* currentMissionItems READ currentMissionItems NOTIFY currentMissionItemsChanged)
Q_PROPERTY(QmlObjectVectorModel* missionItems READ missionItems NOTIFY missionItemsChanged)
Q_PROPERTY(QmlObjectVectorModel* currentMissionItems READ currentMissionItems NOTIFY currentMissionItemsChanged)
Q_PROPERTY(QVariantList waypointPath READ waypointPath NOTIFY waypointPathChanged)
Q_PROPERTY(QVariantList currentWaypointPath READ currentWaypointPath NOTIFY currentWaypointPathChanged)
Q_PROPERTY(Fact* enableWimaController READ enableWimaController CONSTANT)
......@@ -67,15 +67,15 @@ public:
// Property accessors
PlanMasterController* masterController (void) { return _masterController; }
MissionController* missionController (void) { return _missionController; }
QmlObjectListModel* visualItems (void);
QmlObjectVectorModel* visualItems (void);
QString currentFile (void) const { return _currentFile; }
QStringList loadNameFilters (void) const;
QStringList saveNameFilters (void) const;
QString fileExtension (void) const { return wimaFileExtension; }
QGCMapPolygon joinedArea (void) const;
WimaDataContainer* dataContainer (void);
QmlObjectListModel* missionItems (void);
QmlObjectListModel* currentMissionItems (void);
QmlObjectVectorModel* missionItems (void);
QmlObjectVectorModel* currentMissionItems (void);
QVariantList waypointPath (void);
QVariantList currentWaypointPath (void);
Fact* enableWimaController (void);
......@@ -141,13 +141,13 @@ public:
bool calcShortestPath(const QGeoCoordinate &start, const QGeoCoordinate &destination, QVector<QGeoCoordinate> &path);
/// extracts the coordinates stored in missionItems (list of MissionItems) and stores them in coordinateList
bool extractCoordinateList(QmlObjectListModel &missionItems, QVector<QGeoCoordinate> &coordinateList);
bool extractCoordinateList(QmlObjectVectorModel &missionItems, QVector<QGeoCoordinate> &coordinateList);
/// extracts the coordinates (between startIndex and endIndex) stored in missionItems (list of MissionItems) and stores them in coordinateList.
bool extractCoordinateList(QmlObjectListModel &missionItems, QVector<QGeoCoordinate> &coordinateList, int startIndex, int endIndex);
bool extractCoordinateList(QmlObjectVectorModel &missionItems, QVector<QGeoCoordinate> &coordinateList, int startIndex, int endIndex);
/// extracts the coordinates stored in missionItems (list of MissionItems) and stores them in coordinateList
bool extractCoordinateList(QmlObjectListModel &missionItems, QVariantList &coordinateList);
bool extractCoordinateList(QmlObjectVectorModel &missionItems, QVariantList &coordinateList);
/// extracts the coordinates (between startIndex and endIndex) stored in missionItems (list of MissionItems) and stores them in coordinateList.
bool extractCoordinateList(QmlObjectListModel &missionItems, QVariantList &coordinateList, int startIndex, int endIndex);
bool extractCoordinateList(QmlObjectVectorModel &missionItems, QVariantList &coordinateList, int startIndex, int endIndex);
signals:
void masterControllerChanged (void);
......@@ -198,16 +198,16 @@ private:
MissionController *_missionController;
QString _currentFile; // file for saveing
WimaDataContainer *_container; // container for data exchange with WimaController
QmlObjectListModel _visualItems; // contains all visible areas
QmlObjectVectorModel _visualItems; // contains all visible areas
WimaJoinedAreaData _joinedArea; // joined area fromed by opArea, serArea, _corridor
WimaMeasurementAreaData _measurementArea; // measurement area
WimaServiceAreaData _serviceArea; // area for supplying
WimaCorridorData _corridor; // corridor connecting opArea and serArea
bool _localPlanDataValid;
QmlObjectListModel _missionItems; // all mission itmes (Mission Items) generaded by wimaPlaner, displayed in flightView
QmlObjectListModel _currentMissionItems; // contains the current mission items, which are a sub set of _missionItems,
QmlObjectVectorModel _missionItems; // all mission itmes (Mission Items) generaded by wimaPlaner, displayed in flightView
QmlObjectVectorModel _currentMissionItems; // contains the current mission items, which are a sub set of _missionItems,
// _currentMissionItems contains a number of mission items which can be worked off with a single battery chrage
QmlObjectListModel _missionItemsBuffer; // Buffer to store mission items, e.g. for storing _currentMissionItems when smartRTL() is invoked
QmlObjectVectorModel _missionItemsBuffer; // Buffer to store mission items, e.g. for storing _currentMissionItems when smartRTL() is invoked
QVariantList _waypointPath; // path connecting the items in _missionItems
QVariantList _currentWaypointPath; // path connecting the items in _currentMissionItems
QGeoCoordinate _takeoffLandPostion;
......
#include "WimaPlaner.h"
 #include "WimaPlaner.h"
#include "CircularSurveyComplexItem.h"
......@@ -480,7 +480,6 @@ void WimaPlaner::recalcPolygonInteractivity(int index)
bool WimaPlaner::calcArrivalAndReturnPath()
{
static int counter = 0;
setReadyForSync(false);
// extract old survey data
......@@ -595,8 +594,6 @@ bool WimaPlaner::calcArrivalAndReturnPath()
_missionController->setCurrentPlanViewIndex(missionItems->indexOf(_circularSurvey), false);
setSyncronizedWithControllerFalse();
setReadyForSync(true);
counter++;
qWarning() << "WimaPlaner::calcArrivalAndReturnPath(): " << counter;
return true;
}
......@@ -646,6 +643,7 @@ bool WimaPlaner::recalcJoinedArea()
*/
void WimaPlaner::pushToContainer()
{
auto start = std::chrono::high_resolution_clock::now();
if (_container != nullptr) {
if (!_readyForSync)
return;
......@@ -654,6 +652,10 @@ void WimaPlaner::pushToContainer()
} else {
qWarning("WimaPlaner::uploadToContainer(): no container assigned.");
}
qWarning() << "WimaPlaner::pushToContainer()"
<< std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now()-start).count()
<< " ms";
}
bool WimaPlaner::calcShortestPath(const QGeoCoordinate &start, const QGeoCoordinate &destination, QVector<QGeoCoordinate> &path)
......@@ -662,16 +664,12 @@ bool WimaPlaner::calcShortestPath(const QGeoCoordinate &start, const QGeoCoordin
using namespace PolygonCalculus;
QVector<QPointF> path2D;
auto startTime = std::chrono::high_resolution_clock::now();
bool retVal = PolygonCalculus::shortestPath(
toQPolygonF(toCartesian2D(_joinedArea.coordinateList(), /*origin*/ start)),
/*start point*/ QPointF(0,0),
/*destination*/ toCartesian2D(destination, start),
/*shortest path*/ path2D);
path.append(toGeo(path2D, /*origin*/ start));
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()-startTime).count();
qWarning() << "WimaPlaner::calcShortestPath: time " << duration << " us";
return retVal;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment