From f5389ba62d08fa84c691c79e54062a5bedb4c3d1 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Thu, 10 Sep 2015 22:33:03 -0700 Subject: [PATCH] Add Delete, Move Up, Move Down Plus more overall ui work --- src/FlightMap/MapItems/MissionItemIndicator.qml | 6 +++ src/MissionEditor/MissionEditor.cc | 70 ++++++++++++++++++------- src/MissionEditor/MissionEditor.h | 11 ++-- src/MissionEditor/MissionEditor.qml | 27 +++++++++- src/QmlControls/MissionItemEditor.qml | 65 ++++++++++++++++++++--- src/QmlControls/MissionItemIndexLabel.qml | 8 +++ src/QmlControls/QmlObjectListModel.cc | 25 ++++++++- src/QmlControls/QmlObjectListModel.h | 1 + 8 files changed, 179 insertions(+), 34 deletions(-) diff --git a/src/FlightMap/MapItems/MissionItemIndicator.qml b/src/FlightMap/MapItems/MissionItemIndicator.qml index 8036cb1..d67bdbe 100644 --- a/src/FlightMap/MapItems/MissionItemIndicator.qml +++ b/src/FlightMap/MapItems/MissionItemIndicator.qml @@ -30,14 +30,20 @@ import QGroundControl.Vehicle 1.0 /// Marker for displaying a mission item on the map MapQuickItem { + id: _item + property alias label: _label.label property alias isCurrentItem: _label.isCurrentItem + signal clicked + anchorPoint.x: sourceItem.width / 2 anchorPoint.y: sourceItem.height / 2 sourceItem: MissionItemIndexLabel { id: _label + + onClicked: _item.clicked() } } diff --git a/src/MissionEditor/MissionEditor.cc b/src/MissionEditor/MissionEditor.cc index c998c59..c385d84 100644 --- a/src/MissionEditor/MissionEditor.cc +++ b/src/MissionEditor/MissionEditor.cc @@ -36,16 +36,11 @@ MissionEditor::MissionEditor(QWidget *parent) : QGCQmlWidgetHolder(parent) , _missionItems(NULL) { - setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); // Get rid of layout default margins QLayout* pl = layout(); if(pl) { pl->setContentsMargins(0,0,0,0); } -#ifndef __android__ - setMinimumWidth( 31 * ScreenToolsController::defaultFontPixelSize_s()); - setMinimumHeight(33 * ScreenToolsController::defaultFontPixelSize_s()); -#endif Vehicle* activeVehicle = MultiVehicleManager::instance()->activeVehicle(); if (activeVehicle) { @@ -72,6 +67,8 @@ void MissionEditor::_newMissionItemsAvailable(void) } _missionItems = MultiVehicleManager::instance()->activeVehicle()->missionManager()->copyMissionItems(); + _reSequence(); + emit missionItemsChanged(); } @@ -93,30 +90,63 @@ void MissionEditor::setMissionItems(void) } } -void MissionEditor::saveSetting(const QString &name, const QString& value) +int MissionEditor::addMissionItem(QGeoCoordinate coordinate) { - QSettings settings; - - settings.beginGroup(_settingsGroup); + MissionItem * newItem = new MissionItem(this, _missionItems->count(), coordinate); + if (_missionItems->count() == 0) { + newItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF); + } + qDebug() << "MissionItem" << newItem->coordinate(); + _missionItems->append(newItem); - settings.setValue(name, value); + return _missionItems->count() - 1; } -QString MissionEditor::loadSetting(const QString &name, const QString& defaultValue) +void MissionEditor::_reSequence(void) { - QSettings settings; + for (int i=0; i<_missionItems->count(); i++) { + qobject_cast(_missionItems->get(i))->setSequenceNumber(i); + } +} + +void MissionEditor::removeMissionItem(int index) +{ + _missionItems->removeAt(index); + _reSequence(); +} + +void MissionEditor::moveUp(int index) +{ + if (_missionItems->count() < 2 || index <= 0 || index >= _missionItems->count()) { + return; + } + + MissionItem item1 = *qobject_cast(_missionItems->get(index - 1)); + MissionItem item2 = *qobject_cast(_missionItems->get(index)); + + _missionItems->removeAt(index - 1); + _missionItems->removeAt(index - 1); - settings.beginGroup(_settingsGroup); + _missionItems->insert(index - 1, new MissionItem(item2, _missionItems)); + _missionItems->insert(index, new MissionItem(item1, _missionItems)); - return settings.value(name, defaultValue).toString(); + _reSequence(); } -void MissionEditor::addMissionItem(QGeoCoordinate coordinate) +void MissionEditor::moveDown(int index) { - MissionItem * newItem = new MissionItem(this, _missionItems->count(), coordinate); - if (_missionItems->count() == 0) { - newItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF); + if (_missionItems->count() < 2 || index >= _missionItems->count() - 1) { + return; } - qDebug() << "MissionItem" << newItem->coordinate(); - _missionItems->append(newItem); + + MissionItem item1 = *qobject_cast(_missionItems->get(index)); + MissionItem item2 = *qobject_cast(_missionItems->get(index + 1)); + + _missionItems->removeAt(index); + _missionItems->removeAt(index); + + _missionItems->insert(index, new MissionItem(item2, _missionItems)); + _missionItems->insert(index + 1, new MissionItem(item1, _missionItems)); + + _reSequence(); } diff --git a/src/MissionEditor/MissionEditor.h b/src/MissionEditor/MissionEditor.h index ceea6e8..57786c0 100644 --- a/src/MissionEditor/MissionEditor.h +++ b/src/MissionEditor/MissionEditor.h @@ -37,12 +37,12 @@ public: Q_PROPERTY(QmlObjectListModel* missionItems READ missionItemsModel NOTIFY missionItemsChanged) - Q_INVOKABLE void addMissionItem(QGeoCoordinate coordinate); + Q_INVOKABLE int addMissionItem(QGeoCoordinate coordinate); Q_INVOKABLE void getMissionItems(void); Q_INVOKABLE void setMissionItems(void); - - Q_INVOKABLE void saveSetting (const QString &key, const QString& value); - Q_INVOKABLE QString loadSetting (const QString &key, const QString& defaultValue); + Q_INVOKABLE void removeMissionItem(int index); + Q_INVOKABLE void moveUp(int index); + Q_INVOKABLE void moveDown(int index); // Property accessors @@ -55,6 +55,9 @@ private slots: void _newMissionItemsAvailable(); private: + void _reSequence(void); + +private: QmlObjectListModel* _missionItems; static const char* _settingsGroup; diff --git a/src/MissionEditor/MissionEditor.qml b/src/MissionEditor/MissionEditor.qml index e27ebe7..d5a2996 100644 --- a/src/MissionEditor/MissionEditor.qml +++ b/src/MissionEditor/MissionEditor.qml @@ -44,8 +44,16 @@ QGCView { readonly property real _verticalMargin: ScreenTools.defaultFontPixelHeight / 2 readonly property var _activeVehicle: multiVehicleManager.activeVehicle + property var _missionItems: controller.missionItems + QGCPalette { id: _qgcPal; colorGroupEnabled: enabled } + function setCurrentItem(index) { + for (var i=0; i<_missionItems.count; i++) { + _missionItems.get(i).isCurrentItem = (i == index) + } + } + QGCViewPanel { id: panel anchors.fill: parent @@ -76,7 +84,8 @@ QGCView { coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) coordinate.altitude = 0 - controller.addMissionItem(coordinate) + var index = controller.addMissionItem(coordinate) + setCurrentItem(index) } } @@ -90,6 +99,8 @@ QGCView { isCurrentItem: object.isCurrentItem coordinate: object.coordinate + onClicked: setCurrentItem(object.sequenceNumber) + Component.onCompleted: console.log("Indicator", object.coordinate) } } @@ -171,6 +182,20 @@ QGCView { MissionItemEditor { missionItem: object width: parent.width + + onClicked: setCurrentItem(object.sequenceNumber) + + onRemove: { + var newCurrentItem = object.sequenceNumber - 1 + controller.removeMissionItem(object.sequenceNumber) + if (_missionItems.count) { + newCurrentItem = Math.min(_missionItems.count - 1, newCurrentItem) + setCurrentItem(newCurrentItem) + } + } + + onMoveUp: controller.moveUp(object.sequenceNumber) + onMoveDown: controller.moveDown(object.sequenceNumber) } } // ListView } // Item diff --git a/src/QmlControls/MissionItemEditor.qml b/src/QmlControls/MissionItemEditor.qml index e9aa869..44e6af5 100644 --- a/src/QmlControls/MissionItemEditor.qml +++ b/src/QmlControls/MissionItemEditor.qml @@ -11,11 +11,20 @@ import QGroundControl.Palette 1.0 /// Mission item edit control Rectangle { + id: _root + property var missionItem - height: ((missionItem.factCount + 3) * (latitudeField.height + _margin)) + commandPicker.height + (_margin * 5) - color: missionItem.isCurrentItem ? qgcPal.buttonHighlight : qgcPal.windowShade + signal clicked + signal remove + signal moveUp + signal moveDown +// FIXME: THis doesn't work right for RTL + height: missionItem.isCurrentItem ? + ((missionItem.factCount + (missionItem.specifiesCoordinate ? 3 : 0)) * (latitudeField.height + _margin)) + commandPicker.height + deleteButton.height + (_margin * 6) : + commandPicker.height + (_margin * 2) + color: missionItem.isCurrentItem ? qgcPal.buttonHighlight : qgcPal.windowShade readonly property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 13 readonly property real _margin: ScreenTools.defaultFontPixelWidth / 3 @@ -30,14 +39,23 @@ Rectangle { anchors.fill: parent MissionItemIndexLabel { - id: label - isCurrentItem: missionItem.isCurrentItem - label: missionItem.sequenceNumber + id: label + anchors.verticalCenter: commandPicker.verticalCenter + isCurrentItem: missionItem.isCurrentItem + label: missionItem.sequenceNumber + } + + MouseArea { + anchors.fill: parent + visible: !missionItem.isCurrentItem + + onClicked: _root.clicked() } + QGCComboBox { id: commandPicker - anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 4 + anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 10 anchors.left: label.right anchors.right: parent.right currentIndex: missionItem.commandByIndex @@ -53,6 +71,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right color: qgcPal.windowShadeDark + visible: missionItem.isCurrentItem Item { anchors.margins: _margin @@ -120,7 +139,7 @@ Rectangle { anchors.topMargin: _margin anchors.left: parent.left anchors.right: parent.right - anchors.top: missionItem.specifiesCoordinate ? altitudeField.bottom : commandPicker.bottom + anchors.top: missionItem.specifiesCoordinate ? altitudeField.bottom : parent.top spacing: _margin Repeater { @@ -145,6 +164,38 @@ Rectangle { } } } // Column - Values column + + Row { + anchors.topMargin: _margin + anchors.top: valueColumn.bottom + + width: parent.width + spacing: _margin + + readonly property real buttonWidth: (width - (_margin * 2)) / 3 + + QGCButton { + id: deleteButton + width: parent.buttonWidth + text: "Delete" + + onClicked: _root.remove() + } + + QGCButton { + width: parent.buttonWidth + text: "Up" + + onClicked: _root.moveUp() + } + + QGCButton { + width: parent.buttonWidth + text: "Down" + + onClicked: _root.moveDown() + } + } } // Item } // Rectangle } // Item diff --git a/src/QmlControls/MissionItemIndexLabel.qml b/src/QmlControls/MissionItemIndexLabel.qml index a5f9b87..630b764 100644 --- a/src/QmlControls/MissionItemIndexLabel.qml +++ b/src/QmlControls/MissionItemIndexLabel.qml @@ -8,6 +8,8 @@ Rectangle { property alias label: _label.text property bool isCurrentItem: false + signal clicked + width: ScreenTools.defaultFontPixelHeight * 1.5 height: width radius: width / 2 @@ -15,6 +17,12 @@ Rectangle { border.color: "white" color: isCurrentItem ? "green" : "orange" + MouseArea { + anchors.fill: parent + + onClicked: parent.clicked() + } + QGCLabel { id: _label anchors.fill: parent diff --git a/src/QmlControls/QmlObjectListModel.cc b/src/QmlControls/QmlObjectListModel.cc index 6d89c0a..a3647ff 100644 --- a/src/QmlControls/QmlObjectListModel.cc +++ b/src/QmlControls/QmlObjectListModel.cc @@ -89,6 +89,10 @@ bool QmlObjectListModel::insertRows(int position, int rows, const QModelIndex& p { 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(); @@ -101,10 +105,18 @@ bool QmlObjectListModel::removeRows(int position, int rows, const QModelIndex& p { 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; rowdeleteLater(); _objectList.removeAt(position); } + qDebug() << _objectList; endRemoveRows(); emit countChanged(count()); @@ -134,10 +146,19 @@ void QmlObjectListModel::removeAt(int i) removeRows(i, 1); } +void QmlObjectListModel::insert(int i, QObject* object) +{ + if (i < 0 || i > _objectList.count()) { + qWarning() << "Invalid index index:count" << i << _objectList.count(); + } + + _objectList.insert(i, object); + insertRows(i, 1); +} + void QmlObjectListModel::append(QObject* object) { - _objectList += object; - insertRows(_objectList.count() - 1, 1); + insert(_objectList.count(), object); } int QmlObjectListModel::count(void) const diff --git a/src/QmlControls/QmlObjectListModel.h b/src/QmlControls/QmlObjectListModel.h index 8f6cd94..effedea 100644 --- a/src/QmlControls/QmlObjectListModel.h +++ b/src/QmlControls/QmlObjectListModel.h @@ -42,6 +42,7 @@ public: void append(QObject* object); void clear(void); void removeAt(int i); + void insert(int i, QObject* object); QObject* operator[](int i); const QObject* operator[](int i) const;