Browse Source

Merge pull request #1944 from DonLakeFlyer/MissionDirty

Add dirty bit support to mission editing
QGC4.4
Don Gagne 10 years ago
parent
commit
93928a62a1
  1. BIN
      resources/Sync.png
  2. 5
      src/MissionEditor/MissionEditor.cc
  3. 30
      src/MissionEditor/MissionEditor.qml
  4. 24
      src/MissionItem.cc
  5. 12
      src/MissionItem.h
  6. 39
      src/QmlControls/QmlObjectListModel.cc
  7. 16
      src/QmlControls/QmlObjectListModel.h

BIN
resources/Sync.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

5
src/MissionEditor/MissionEditor.cc

@ -73,6 +73,7 @@ void MissionEditor::_newMissionItemsAvailable(void) @@ -73,6 +73,7 @@ void MissionEditor::_newMissionItemsAvailable(void)
_canEdit = missionManager->canEdit();
_missionItems = missionManager->copyMissionItems();
_reSequence();
_missionItems->setDirty(false);
emit missionItemsChanged();
emit canEditChanged(_canEdit);
@ -95,6 +96,7 @@ void MissionEditor::setMissionItems(void) @@ -95,6 +96,7 @@ void MissionEditor::setMissionItems(void)
if (activeVehicle) {
activeVehicle->missionManager()->writeMissionItems(*_missionItems);
_missionItems->setDirty(false);
}
}
@ -225,6 +227,7 @@ void MissionEditor::loadMissionFromFile(void) @@ -225,6 +227,7 @@ void MissionEditor::loadMissionFromFile(void)
_missionItems->clear();
}
_missionItems->setDirty(false);
emit canEditChanged(_canEdit);
}
@ -250,4 +253,6 @@ void MissionEditor::saveMissionToFile(void) @@ -250,4 +253,6 @@ void MissionEditor::saveMissionToFile(void)
qobject_cast<MissionItem*>(_missionItems->get(i))->save(out);
}
}
_missionItems->setDirty(false);
}

30
src/MissionEditor/MissionEditor.qml

@ -88,11 +88,6 @@ QGCView { @@ -88,11 +88,6 @@ QGCView {
longitude = _homePositionCoordinate.longitude
}
QGCLabel {
anchors.bottom: parent.bottom
text: "WIP: Danger, do not fly with this!"; font.pixelSize: ScreenTools.largeFontPixelSize }
MouseArea {
anchors.fill: parent
@ -111,6 +106,31 @@ QGCView { @@ -111,6 +106,31 @@ QGCView {
}
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
width: parent.width / 3
height: syncNeededText.height + (ScreenTools.defaultFontPixelWidth * 2)
border.width: 1
border.color: "white"
color: "black"
opacity: 0.75
visible: controller.missionItems.dirty
QGCLabel {
id: syncNeededText
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: ScreenTools.mediumFontPixelSize
text: "You have unsaved changes. Be sure to use the Sync tool to save when ready."
}
}
Rectangle {
id: addMissionItemsButton
anchors.rightMargin: ScreenTools.defaultFontPixelHeight
anchors.right: homePositionManagerButton.left

24
src/MissionItem.cc

@ -83,6 +83,7 @@ MissionItem::MissionItem(QObject* parent, @@ -83,6 +83,7 @@ MissionItem::MissionItem(QObject* parent,
, _isCurrentItem(isCurrentItem)
, _reachedTime(0)
, _yawRadiansFact(NULL)
,_dirty(false)
{
_latitudeFact = new Fact(0, "Latitude:", FactMetaData::valueTypeDouble, this);
_longitudeFact = new Fact(0, "Longitude:", FactMetaData::valueTypeDouble, this);
@ -147,6 +148,16 @@ MissionItem::MissionItem(QObject* parent, @@ -147,6 +148,16 @@ MissionItem::MissionItem(QObject* parent,
_altitudeFact->setMetaData(altitudeMetaData);
_yawRadiansFact->setMetaData(yawMetaData);
_loiterOrbitRadiusFact->setMetaData(loiterOrbitRadiusMetaData);
// 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);
}
MissionItem::MissionItem(const MissionItem& other, QObject* parent)
@ -187,6 +198,7 @@ const MissionItem& MissionItem::operator=(const MissionItem& other) @@ -187,6 +198,7 @@ const MissionItem& MissionItem::operator=(const MissionItem& other)
_autocontinue = other._autocontinue;
_reachedTime = other._reachedTime;
_altitudeRelativeToHomeFact = other._altitudeRelativeToHomeFact;
_dirty = other._dirty;
*_latitudeFact = *other._latitudeFact;
*_longitudeFact = *other._longitudeFact;
@ -797,3 +809,15 @@ bool MissionItem::canEdit(void) @@ -797,3 +809,15 @@ bool MissionItem::canEdit(void)
return false;
}
}
void MissionItem::setDirty(bool dirty)
{
_dirty = dirty;
emit dirtyChanged(_dirty);
}
void MissionItem::_factValueChanged(QVariant value)
{
Q_UNUSED(value);
setDirty(true);
}

12
src/MissionItem.h

@ -61,6 +61,9 @@ public: @@ -61,6 +61,9 @@ public:
const MissionItem& operator=(const MissionItem& other);
/// Returns true if the item has been modified since the last time dirty was false
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
Q_PROPERTY(int sequenceNumber READ sequenceNumber WRITE setSequenceNumber NOTIFY sequenceNumberChanged)
Q_PROPERTY(bool isCurrentItem READ isCurrentItem WRITE setIsCurrentItem NOTIFY isCurrentItemChanged)
Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY commandChanged)
@ -106,6 +109,9 @@ public: @@ -106,6 +109,9 @@ public:
double yawDegrees(void) const;
void setYawDegrees(double yaw);
bool dirty(void) { return _dirty; }
void setDirty(bool dirty);
// C++ only methods
/// Returns true if this item can be edited in the ui
@ -184,6 +190,7 @@ signals: @@ -184,6 +190,7 @@ signals:
void isCurrentItemChanged(bool isCurrentItem);
void coordinateChanged(const QGeoCoordinate& coordinate);
void yawChanged(double yaw);
void dirtyChanged(bool dirty);
/** @brief Announces a change to the waypoint data */
void changed(MissionItem* wp);
@ -219,6 +226,9 @@ public: @@ -219,6 +226,9 @@ public:
void setChanged() {
emit changed(this);
}
private slots:
void _factValueChanged(QVariant value);
private:
QString _oneDecimalString(double value);
@ -254,6 +264,8 @@ private: @@ -254,6 +264,8 @@ private:
FactMetaData* _jumpSequenceMetaData;
FactMetaData* _jumpRepeatMetaData;
bool _dirty;
static const int _cMavCmd2Name = 9;
static const MavCmd2Name_t _rgMavCmd2Name[_cMavCmd2Name];
};

39
src/QmlControls/QmlObjectListModel.cc

@ -34,6 +34,7 @@ const int QmlObjectListModel::TextRole = Qt::UserRole + 1; @@ -34,6 +34,7 @@ const int QmlObjectListModel::TextRole = Qt::UserRole + 1;
QmlObjectListModel::QmlObjectListModel(QObject* parent)
: QAbstractListModel(parent)
, _dirty(false)
{
}
@ -142,22 +143,36 @@ const QObject* QmlObjectListModel::operator[](int index) const @@ -142,22 +143,36 @@ const QObject* QmlObjectListModel::operator[](int index) const
void QmlObjectListModel::clear(void)
{
while (rowCount()) {
removeRows(0, 1);
removeAt(0);
}
}
void QmlObjectListModel::removeAt(int i)
{
setDirty(true);
// Look for a dirtyChanged signal on the object
if (_objectList[i]->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) {
QObject::disconnect(_objectList[i], SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
}
removeRows(i, 1);
}
void QmlObjectListModel::insert(int i, QObject* object)
{
setDirty(true);
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) {
QObject::connect(object, SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
}
_objectList.insert(i, object);
insertRows(i, 1);
@ -177,3 +192,25 @@ QObject* QmlObjectListModel::get(int index) @@ -177,3 +192,25 @@ QObject* QmlObjectListModel::get(int index)
{
return _objectList[index];
}
void QmlObjectListModel::setDirty(bool dirty)
{
_dirty = dirty;
if (!dirty) {
// Need to clear dirty from all children
foreach(QObject* object, _objectList) {
if (object->property("dirty").isValid()) {
object->setProperty("dirty", false);
}
}
}
emit dirtyChanged(_dirty);
}
void QmlObjectListModel::_childDirtyChanged(bool dirty)
{
_dirty |= dirty;
emit dirtyChanged(_dirty);
}

16
src/QmlControls/QmlObjectListModel.h

@ -37,8 +37,18 @@ public: @@ -37,8 +37,18 @@ public:
Q_INVOKABLE QObject* get(int index);
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)
// Property accessors
int count(void) const;
bool dirty(void) { return _dirty; }
void setDirty(bool dirty);
void append(QObject* object);
void clear(void);
void removeAt(int i);
@ -51,6 +61,10 @@ public: @@ -51,6 +61,10 @@ public:
signals:
void countChanged(int count);
void dirtyChanged(bool dirtyChanged);
private slots:
void _childDirtyChanged(bool dirty);
private:
// Overrides from QAbstractListModel
@ -63,6 +77,8 @@ private: @@ -63,6 +77,8 @@ private:
private:
QList<QObject*> _objectList;
bool _dirty;
static const int ObjectRole;
static const int TextRole;

Loading…
Cancel
Save