Commit ff537957 authored by Valentin Platzgummer's avatar Valentin Platzgummer

QmlObjectVectorModel added and used inside WimaController, no speed improvement though

parent bdc59c26
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -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