Commit 7797d824 authored by Don Gagne's avatar Don Gagne

Merge pull request #1947 from DonLakeFlyer/EditorLines

Editor lines
parents 782af62d 674bf254
...@@ -26,6 +26,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -26,6 +26,7 @@ This file is part of the QGROUNDCONTROL project
#include "MultiVehicleManager.h" #include "MultiVehicleManager.h"
#include "MissionManager.h" #include "MissionManager.h"
#include "QGCFileDialog.h" #include "QGCFileDialog.h"
#include "CoordinateVector.h"
#include <QQmlContext> #include <QQmlContext>
#include <QQmlEngine> #include <QQmlEngine>
...@@ -51,6 +52,7 @@ MissionEditor::MissionEditor(QWidget *parent) ...@@ -51,6 +52,7 @@ MissionEditor::MissionEditor(QWidget *parent)
_newMissionItemsAvailable(); _newMissionItemsAvailable();
} else { } else {
_missionItems = new QmlObjectListModel(this); _missionItems = new QmlObjectListModel(this);
connect(_missionItems, &QmlObjectListModel::dirtyChanged, this, &MissionEditor::_missionListDirtyChanged);
} }
setContextPropertyObject("controller", this); setContextPropertyObject("controller", this);
...@@ -75,6 +77,9 @@ void MissionEditor::_newMissionItemsAvailable(void) ...@@ -75,6 +77,9 @@ void MissionEditor::_newMissionItemsAvailable(void)
_reSequence(); _reSequence();
_missionItems->setDirty(false); _missionItems->setDirty(false);
connect(_missionItems, &QmlObjectListModel::dirtyChanged, this, &MissionEditor::_missionListDirtyChanged);
_rebuildWaypointLines();
emit missionItemsChanged(); emit missionItemsChanged();
emit canEditChanged(_canEdit); emit canEditChanged(_canEdit);
} }
...@@ -190,7 +195,11 @@ void MissionEditor::loadMissionFromFile(void) ...@@ -190,7 +195,11 @@ void MissionEditor::loadMissionFromFile(void)
return; return;
} }
_missionItems->clear(); if (_missionItems) {
_missionItems->deleteLater();
}
_missionItems = new QmlObjectListModel(this);
_canEdit = true; _canEdit = true;
QFile file(filename); QFile file(filename);
...@@ -229,6 +238,9 @@ void MissionEditor::loadMissionFromFile(void) ...@@ -229,6 +238,9 @@ void MissionEditor::loadMissionFromFile(void)
_missionItems->setDirty(false); _missionItems->setDirty(false);
emit canEditChanged(_canEdit); emit canEditChanged(_canEdit);
connect(_missionItems, &QmlObjectListModel::dirtyChanged, this, &MissionEditor::_missionListDirtyChanged);
_rebuildWaypointLines();
} }
void MissionEditor::saveMissionToFile(void) void MissionEditor::saveMissionToFile(void)
...@@ -256,3 +268,21 @@ void MissionEditor::saveMissionToFile(void) ...@@ -256,3 +268,21 @@ void MissionEditor::saveMissionToFile(void)
_missionItems->setDirty(false); _missionItems->setDirty(false);
} }
void MissionEditor::_rebuildWaypointLines(void)
{
_waypointLines.clear();
for (int i=1; i<_missionItems->count(); i++) {
MissionItem* item1 = qobject_cast<MissionItem*>(_missionItems->get(i-1));
MissionItem* item2 = qobject_cast<MissionItem*>(_missionItems->get(i));
_waypointLines.append(new CoordinateVector(item1->coordinate(), item2->coordinate()));
}
emit waypointLinesChanged();
}
void MissionEditor::_missionListDirtyChanged(bool dirty)
{
Q_UNUSED(dirty);
_rebuildWaypointLines();
}
...@@ -35,7 +35,8 @@ public: ...@@ -35,7 +35,8 @@ public:
MissionEditor(QWidget* parent = NULL); MissionEditor(QWidget* parent = NULL);
~MissionEditor(); ~MissionEditor();
Q_PROPERTY(QmlObjectListModel* missionItems READ missionItemsModel NOTIFY missionItemsChanged) Q_PROPERTY(QmlObjectListModel* missionItems READ missionItems NOTIFY missionItemsChanged)
Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged)
Q_PROPERTY(bool canEdit READ canEdit NOTIFY canEditChanged) Q_PROPERTY(bool canEdit READ canEdit NOTIFY canEditChanged)
Q_INVOKABLE int addMissionItem(QGeoCoordinate coordinate); Q_INVOKABLE int addMissionItem(QGeoCoordinate coordinate);
...@@ -49,21 +50,26 @@ public: ...@@ -49,21 +50,26 @@ public:
// Property accessors // Property accessors
QmlObjectListModel* missionItemsModel(void) { return _missionItems; } QmlObjectListModel* missionItems(void) { return _missionItems; }
QmlObjectListModel* waypointLines(void) { return &_waypointLines; }
bool canEdit(void) { return _canEdit; } bool canEdit(void) { return _canEdit; }
signals: signals:
void missionItemsChanged(void); void missionItemsChanged(void);
void canEditChanged(bool canEdit); void canEditChanged(bool canEdit);
void waypointLinesChanged(void);
private slots: private slots:
void _newMissionItemsAvailable(); void _newMissionItemsAvailable();
void _missionListDirtyChanged(bool dirty);
private: private:
void _reSequence(void); void _reSequence(void);
void _rebuildWaypointLines(void);
private: private:
QmlObjectListModel* _missionItems; QmlObjectListModel* _missionItems;
QmlObjectListModel _waypointLines;
bool _canEdit; ///< true: UI can edit these items, false: can't edit, can only send to vehicle or save bool _canEdit; ///< true: UI can edit these items, false: can't edit, can only send to vehicle or save
static const char* _settingsGroup; static const char* _settingsGroup;
......
...@@ -383,6 +383,7 @@ This code will need to wait for Qml 5.5 support since Map.visibleRegion is only ...@@ -383,6 +383,7 @@ This code will need to wait for Qml 5.5 support since Map.visibleRegion is only
label: "H" label: "H"
isCurrentItem: _showHomePositionManager isCurrentItem: _showHomePositionManager
coordinate: _homePositionCoordinate coordinate: _homePositionCoordinate
z: 2
onClicked: _showHomePositionManager = true onClicked: _showHomePositionManager = true
} }
...@@ -396,13 +397,59 @@ This code will need to wait for Qml 5.5 support since Map.visibleRegion is only ...@@ -396,13 +397,59 @@ This code will need to wait for Qml 5.5 support since Map.visibleRegion is only
label: object.sequenceNumber label: object.sequenceNumber
isCurrentItem: !_showHomePositionManager && object.isCurrentItem isCurrentItem: !_showHomePositionManager && object.isCurrentItem
coordinate: object.coordinate coordinate: object.coordinate
z: 2
onClicked: { onClicked: {
_showHomePositionManager = false _showHomePositionManager = false
setCurrentItem(object.sequenceNumber) setCurrentItem(object.sequenceNumber)
} }
}
}
MapPolyline {
id: homePositionLine
line.width: 3
line.color: "orange"
z: 1
property var homePositionCoordinate: _homePositionCoordinate
function update() {
while (homePositionLine.path.length != 0) {
homePositionLine.removeCoordinate(homePositionLine.path[0])
}
if (_missionItems && _missionItems.count != 0) {
homePositionLine.addCoordinate(homePositionCoordinate)
homePositionLine.addCoordinate(_missionItems.get(0).coordinate)
}
}
onHomePositionCoordinateChanged: update()
Component.onCompleted: console.log("Indicator", object.coordinate) Connections {
target: controller
onWaypointLinesChanged: homePositionLine.update()
}
Component.onCompleted: homePositionLine.update()
}
// Add lines between waypoints
MapItemView {
model: controller.waypointLines
delegate:
MapPolyline {
line.width: 3
line.color: "orange"
z: 1
path: [
{ latitude: object.coordinate1.latitude, longitude: object.coordinate1.longitude },
{ latitude: object.coordinate2.latitude, longitude: object.coordinate2.longitude },
]
} }
} }
...@@ -630,7 +677,8 @@ This code will need to wait for Qml 5.5 support since Map.visibleRegion is only ...@@ -630,7 +677,8 @@ This code will need to wait for Qml 5.5 support since Map.visibleRegion is only
text: "Add/Update" text: "Add/Update"
onClicked: { onClicked: {
_homePositionManager.updateHomePosition(nameField.text, QtPositioning.coordinate(latitudeField.text, longitudeField.text, altitudeField.text)) _homePositionCoordinate = QtPositioning.coordinate(latitudeField.text, longitudeField.text, altitudeField.text)
_homePositionManager.updateHomePosition(nameField.text, _homePositionCoordinate)
homePosCombo.currentIndex = homePosCombo.find(nameField.text) homePosCombo.currentIndex = homePosCombo.find(nameField.text)
} }
} }
......
...@@ -158,6 +158,11 @@ MissionItem::MissionItem(QObject* parent, ...@@ -158,6 +158,11 @@ MissionItem::MissionItem(QObject* parent,
connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged); connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged); connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged); connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
// Connect valueChanged signals so we can output coordinateChanged signal
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
} }
MissionItem::MissionItem(const MissionItem& other, QObject* parent) MissionItem::MissionItem(const MissionItem& other, QObject* parent)
...@@ -182,6 +187,21 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent) ...@@ -182,6 +187,21 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent)
_jumpSequenceMetaData = new FactMetaData(this); _jumpSequenceMetaData = new FactMetaData(this);
_jumpRepeatMetaData = new FactMetaData(this); _jumpRepeatMetaData = new FactMetaData(this);
// Connect to valueChanged to track dirty state
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_yawRadiansFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_loiterOrbitRadiusFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
// Connect valueChanged signals so we can output coordinateChanged signal
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
*this = other; *this = other;
} }
...@@ -752,7 +772,6 @@ void MissionItem::setYawRadians(double yaw) ...@@ -752,7 +772,6 @@ void MissionItem::setYawRadians(double yaw)
if (yawRadians() != yaw) if (yawRadians() != yaw)
{ {
_yawRadiansFact->setValue(yaw); _yawRadiansFact->setValue(yaw);
emit yawChanged(yaw);
emit changed(this); emit changed(this);
emit valueStringsChanged(valueStrings()); emit valueStringsChanged(valueStrings());
} }
...@@ -813,6 +832,8 @@ bool MissionItem::canEdit(void) ...@@ -813,6 +832,8 @@ bool MissionItem::canEdit(void)
void MissionItem::setDirty(bool dirty) void MissionItem::setDirty(bool dirty)
{ {
_dirty = dirty; _dirty = dirty;
// We want to emit dirtyChanged even if _dirty didn't change. This can be handy signal for
// any value within the item changing.
emit dirtyChanged(_dirty); emit dirtyChanged(_dirty);
} }
...@@ -821,3 +842,9 @@ void MissionItem::_factValueChanged(QVariant value) ...@@ -821,3 +842,9 @@ void MissionItem::_factValueChanged(QVariant value)
Q_UNUSED(value); Q_UNUSED(value);
setDirty(true); setDirty(true);
} }
void MissionItem::_coordinateFactChanged(QVariant value)
{
Q_UNUSED(value);
emit coordinateChanged(coordinate());
}
...@@ -68,7 +68,6 @@ public: ...@@ -68,7 +68,6 @@ public:
Q_PROPERTY(bool isCurrentItem READ isCurrentItem WRITE setIsCurrentItem NOTIFY isCurrentItemChanged) Q_PROPERTY(bool isCurrentItem READ isCurrentItem WRITE setIsCurrentItem NOTIFY isCurrentItemChanged)
Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY commandChanged) Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY commandChanged)
Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged)
Q_PROPERTY(double yaw READ yawDegrees WRITE setYawDegrees NOTIFY yawChanged)
Q_PROPERTY(QStringList commandNames READ commandNames CONSTANT) Q_PROPERTY(QStringList commandNames READ commandNames CONSTANT)
Q_PROPERTY(QString commandName READ commandName NOTIFY commandChanged) Q_PROPERTY(QString commandName READ commandName NOTIFY commandChanged)
Q_PROPERTY(QStringList valueLabels READ valueLabels NOTIFY commandChanged) Q_PROPERTY(QStringList valueLabels READ valueLabels NOTIFY commandChanged)
...@@ -189,7 +188,6 @@ signals: ...@@ -189,7 +188,6 @@ signals:
void sequenceNumberChanged(int sequenceNumber); void sequenceNumberChanged(int sequenceNumber);
void isCurrentItemChanged(bool isCurrentItem); void isCurrentItemChanged(bool isCurrentItem);
void coordinateChanged(const QGeoCoordinate& coordinate); void coordinateChanged(const QGeoCoordinate& coordinate);
void yawChanged(double yaw);
void dirtyChanged(bool dirty); void dirtyChanged(bool dirty);
/** @brief Announces a change to the waypoint data */ /** @brief Announces a change to the waypoint data */
...@@ -229,6 +227,7 @@ public: ...@@ -229,6 +227,7 @@ public:
private slots: private slots:
void _factValueChanged(QVariant value); void _factValueChanged(QVariant value);
void _coordinateFactChanged(QVariant value);
private: private:
QString _oneDecimalString(double value); QString _oneDecimalString(double value);
......
...@@ -9,9 +9,11 @@ import QGroundControl.ScreenTools 1.0 ...@@ -9,9 +9,11 @@ import QGroundControl.ScreenTools 1.0
/// are switched. In order to fix this we ahve a signal hacked into ScreenTools to force /// are switched. In order to fix this we ahve a signal hacked into ScreenTools to force
/// a repaint. /// a repaint.
Canvas { Canvas {
id: _root
Connections { Connections {
target: ScreenTools target: ScreenTools
onRepaintRequested: arrowCanvas.requestPaint() onRepaintRequested: _root.requestPaint()
} }
} }
...@@ -149,20 +149,18 @@ void QmlObjectListModel::clear(void) ...@@ -149,20 +149,18 @@ void QmlObjectListModel::clear(void)
void QmlObjectListModel::removeAt(int i) void QmlObjectListModel::removeAt(int i)
{ {
setDirty(true);
// Look for a dirtyChanged signal on the object // Look for a dirtyChanged signal on the object
if (_objectList[i]->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) { if (_objectList[i]->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) {
QObject::disconnect(_objectList[i], SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool))); QObject::disconnect(_objectList[i], SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
} }
removeRows(i, 1); removeRows(i, 1);
setDirty(true);
} }
void QmlObjectListModel::insert(int i, QObject* object) void QmlObjectListModel::insert(int i, QObject* object)
{ {
setDirty(true);
if (i < 0 || i > _objectList.count()) { if (i < 0 || i > _objectList.count()) {
qWarning() << "Invalid index index:count" << i << _objectList.count(); qWarning() << "Invalid index index:count" << i << _objectList.count();
} }
...@@ -176,6 +174,8 @@ void QmlObjectListModel::insert(int i, QObject* object) ...@@ -176,6 +174,8 @@ void QmlObjectListModel::insert(int i, QObject* object)
_objectList.insert(i, object); _objectList.insert(i, object);
insertRows(i, 1); insertRows(i, 1);
setDirty(true);
} }
void QmlObjectListModel::append(QObject* object) void QmlObjectListModel::append(QObject* object)
...@@ -212,5 +212,7 @@ void QmlObjectListModel::setDirty(bool dirty) ...@@ -212,5 +212,7 @@ void QmlObjectListModel::setDirty(bool dirty)
void QmlObjectListModel::_childDirtyChanged(bool dirty) void QmlObjectListModel::_childDirtyChanged(bool dirty)
{ {
_dirty |= 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); emit dirtyChanged(_dirty);
} }
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