diff --git a/src/Airmap/AirMapFlightPlanManager.cc b/src/Airmap/AirMapFlightPlanManager.cc index 205687953b984effd103ec5b17559af3ed130167..9c552a9b052d9e21a9e0187fd4534bafa60ef5bf 100644 --- a/src/Airmap/AirMapFlightPlanManager.cc +++ b/src/Airmap/AirMapFlightPlanManager.cc @@ -658,7 +658,7 @@ AirMapFlightPlanManager::loadFlightList() void AirMapFlightPlanManager::_loadFlightList() { - _flightList.clearAndDeleteContents(); + _flightList.clear(); emit flightListChanged(); _state = State::LoadFlightList; std::weak_ptr isAlive(_instance); @@ -667,7 +667,7 @@ AirMapFlightPlanManager::_loadFlightList() if (_state != State::LoadFlightList) return; Flights::Search::Parameters params; params.authorization = login_token.toStdString(); - params.limit = 200; + params.limit = 60; params.pilot_id = _pilotID.toStdString(); _shared.client()->flights().search(params, [this, isAlive](const Flights::Search::Result& result) { if (!isAlive.lock()) return; diff --git a/src/Airmap/AirMapFlightPlanManager.h b/src/Airmap/AirMapFlightPlanManager.h index e0b1df63277d51e79bd5eb501e53602b29200560..cb686dca717a33244ba63716019b3ad0e692cc34 100644 --- a/src/Airmap/AirMapFlightPlanManager.h +++ b/src/Airmap/AirMapFlightPlanManager.h @@ -29,9 +29,9 @@ class AirMapFlightInfo : public AirspaceFlightInfo public: AirMapFlightInfo (const airmap::Flight& flight, QObject *parent = nullptr); virtual QString flightID () override { return QString::fromStdString(_flight.id); } - virtual QDateTime createdTime () override { return QDateTime(); } //-- TODO: Need to get rid of boost first - virtual QDateTime startTime () override { return QDateTime(); } //-- TODO: Need to get rid of boost first - virtual QDateTime endTime () override { return QDateTime(); } //-- TODO: Need to get rid of boost first + virtual QString createdTime () override { return QDateTime::currentDateTime().toString(Qt::SystemLocaleShortDate); } //-- TODO: Need to get rid of boost first + virtual QString startTime () override { return QDateTime::currentDateTime().toString(Qt::SystemLocaleShortDate); } //-- TODO: Need to get rid of boost first + virtual QString endTime () override { return QDateTime::currentDateTime().toString(Qt::SystemLocaleShortDate); } //-- TODO: Need to get rid of boost first virtual QGeoCoordinate takeOff () override { return QGeoCoordinate(_flight.latitude, _flight.longitude);} virtual QmlObjectListModel* boundingBox () override { return &_boundingBox; } private: @@ -64,7 +64,7 @@ public: QmlObjectListModel* rulesReview () override { return &_rulesReview; } QmlObjectListModel* rulesFollowing () override { return &_rulesFollowing; } QmlObjectListModel* briefFeatures () override { return &_briefFeatures; } - QmlObjectListModel* flightList () override { return &_flightList; } + AirspaceFlightModel*flightList () override { return &_flightList; } void updateFlightPlan () override; void submitFlightPlan () override; @@ -131,7 +131,7 @@ private: QmlObjectListModel _rulesReview; QmlObjectListModel _rulesFollowing; QmlObjectListModel _briefFeatures; - QmlObjectListModel _flightList; + AirspaceFlightModel _flightList; AirspaceAdvisoryProvider::AdvisoryColor _airspaceColor; AirspaceFlightPlanProvider::PermitStatus _flightPermitStatus = AirspaceFlightPlanProvider::PermitNone; diff --git a/src/Airmap/AirmapSettings.qml b/src/Airmap/AirmapSettings.qml index 8ac4c2f4dbc6a77788ff59a824703ea91f31f0c6..9c4249ae837377be8cc95b12fbb6a72a7ee9d41e 100644 --- a/src/Airmap/AirmapSettings.qml +++ b/src/Airmap/AirmapSettings.qml @@ -8,21 +8,25 @@ ****************************************************************************/ +import QtGraphicalEffects 1.0 +import QtMultimedia 5.5 import QtQuick 2.3 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.2 -import QtMultimedia 5.5 import QtQuick.Layouts 1.2 +import QtLocation 5.3 +import QtPositioning 5.3 import QGroundControl 1.0 -import QGroundControl.FactSystem 1.0 -import QGroundControl.FactControls 1.0 +import QGroundControl.Controllers 1.0 import QGroundControl.Controls 1.0 -import QGroundControl.ScreenTools 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.FactSystem 1.0 +import QGroundControl.FlightMap 1.0 import QGroundControl.MultiVehicleManager 1.0 import QGroundControl.Palette 1.0 -import QGroundControl.Controllers 1.0 +import QGroundControl.ScreenTools 1.0 import QGroundControl.SettingsManager 1.0 QGCView { @@ -34,6 +38,7 @@ QGCView { property real _labelWidth: ScreenTools.defaultFontPixelWidth * 20 property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30 + property real _buttonWidth: ScreenTools.defaultFontPixelWidth * 18 property real _panelWidth: _qgcView.width * _internalWidthRatio property Fact _enableAirMapFact: QGroundControl.settingsManager.airMapSettings.enableAirMap property bool _airMapEnabled: _enableAirMapFact.rawValue @@ -238,35 +243,231 @@ QGCView { anchors.horizontalCenter: parent.horizontalCenter visible: QGroundControl.settingsManager.appSettings.visible QGCLabel { - id: flightListLabel - text: qsTr("Flight List") - font.family: ScreenTools.demiboldFontFamily - } - Component.onCompleted: { - QGroundControl.airspaceManager.flightPlan.loadFlightList() + id: flightListLabel + text: qsTr("Flight List Management") + font.family: ScreenTools.demiboldFontFamily } } Rectangle { - height: flightCol.height + (ScreenTools.defaultFontPixelHeight * 2) + height: flightListButton.height + (ScreenTools.defaultFontPixelHeight * 2) width: _panelWidth color: qgcPal.windowShade anchors.margins: ScreenTools.defaultFontPixelWidth anchors.horizontalCenter: parent.horizontalCenter + QGCButton { + id: flightListButton + text: qsTr("Show Flight List") + backRadius: 4 + heightFactor: 0.3333 + showBorder: true + width: ScreenTools.defaultFontPixelWidth * 16 + anchors.centerIn: parent + onClicked: { + panelLoader.sourceComponent = flightList + } + } + } + } + } + Loader { + id: panelLoader + anchors.centerIn: parent + } + } + //--------------------------------------------------------------- + //-- Flight List + Component { + id: flightList + Rectangle { + id: flightListRoot + width: _qgcView.width + height: _qgcView.height + color: qgcPal.window + property var _flightList: QGroundControl.airspaceManager.flightPlan.flightList + Component.onCompleted: { + QGroundControl.airspaceManager.flightPlan.loadFlightList() + } + Connections { + target: _flightList + onCountChanged: { + tableView.resizeColumnsToContents() + } + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + onWheel: { wheel.accepted = true; } + onPressed: { mouse.accepted = true; } + onReleased: { mouse.accepted = true; } + } + //--------------------------------------------------------- + //-- Flight List + RowLayout { + anchors.fill: parent + TableView { + id: tableView + anchors.top: parent.top + anchors.bottom: parent.bottom + model: _flightList + selectionMode: SelectionMode.MultiSelection + Layout.fillWidth: true + TableViewColumn { + title: qsTr("Created") + width: ScreenTools.defaultFontPixelWidth * 20 + horizontalAlignment: Text.AlignHCenter + delegate : Text { + horizontalAlignment: Text.AlignHCenter + text: { + var o = _flightList.get(styleData.row) + return o ? o.createdTime : "" + } + } + } + TableViewColumn { + title: qsTr("Flight Start") + width: ScreenTools.defaultFontPixelWidth * 20 + horizontalAlignment: Text.AlignHCenter + delegate : Text { + horizontalAlignment: Text.AlignHCenter + text: { + var o = _flightList.get(styleData.row) + return o ? o.startTime : "" + } + } + } + TableViewColumn { + title: qsTr("Take Off") + width: ScreenTools.defaultFontPixelWidth * 22 + horizontalAlignment: Text.AlignHCenter + delegate : Text { + horizontalAlignment: Text.AlignHCenter + text: { + var o = _flightList.get(styleData.row) + return o ? o.takeOff.latitude.toFixed(6) + ', ' + o.takeOff.longitude.toFixed(6) : "" + } + } + } + } + Item { + width: map.width + height: parent.height + Layout.alignment: Qt.AlignTop | Qt.AlignLeft Column { - id: flightCol spacing: ScreenTools.defaultFontPixelHeight - anchors.centerIn: parent - Repeater { - model: QGroundControl.airspaceManager.flightPlan.flightList - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCCheckBox { - text: object.flightID - checked: object.selected - onClicked: object.selected = checked + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + text: qsTr("Flight List") + anchors.horizontalCenter: parent.horizontalCenter + } + QGCButton { + text: qsTr("Refresh") + backRadius: 4 + heightFactor: 0.3333 + showBorder: true + width: _buttonWidth + enabled: true + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + QGroundControl.airspaceManager.flightPlan.loadFlightList() + } + } + QGCButton { + text: qsTr("Select All") + backRadius: 4 + heightFactor: 0.3333 + showBorder: true + width: _buttonWidth + enabled: _flightList.count > 0 + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + tableView.selection.selectAll() + } + } + QGCButton { + text: qsTr("Select None") + backRadius: 4 + heightFactor: 0.3333 + showBorder: true + width: _buttonWidth + enabled: _flightList.count > 0 + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + tableView.selection.clear() + } + } + QGCButton { + text: qsTr("Delete Selected") + backRadius: 4 + heightFactor: 0.3333 + showBorder: true + width: _buttonWidth + enabled: false + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + //-- Clear selection + for(var i = 0; i < _flightList.count; i++) { + var o = _flightList.get(i) + if (o) o.selected = false + } + //-- Flag selected flights + tableView.selection.forEach(function(rowIndex){ + var o = _flightList.get(rowIndex) + if (o) o.selected = true + }) + //TODO: + } + } + QGCButton { + text: qsTr("Close") + backRadius: 4 + heightFactor: 0.3333 + showBorder: true + width: _buttonWidth + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + panelLoader.sourceComponent = null + } + } + } + QGCLabel { + text: qsTr("Flight Area") + anchors.bottom: map.top + anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 0.25 + } + Map { + id: map + width: ScreenTools.defaultFontPixelWidth * 40 + height: width * 0.6666 + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + zoomLevel: QGroundControl.flightMapZoom + center: QGroundControl.flightMapPosition + gesture.acceptedGestures: MapGestureArea.PinchGesture + plugin: Plugin { name: "QGroundControl" } + function updateActiveMapType() { + var settings = QGroundControl.settingsManager.flightMapSettings + var fullMapName = settings.mapProvider.enumStringValue + " " + settings.mapType.enumStringValue + for (var i = 0; i < _map.supportedMapTypes.length; i++) { + if (fullMapName === _map.supportedMapTypes[i].name) { + _map.activeMapType = _map.supportedMapTypes[i] + return } } } + Component.onCompleted: { + updateActiveMapType() + } + Connections { + target: QGroundControl.settingsManager.flightMapSettings.mapType + onRawValueChanged: updateActiveMapType() + } + + Connections { + target: QGroundControl.settingsManager.flightMapSettings.mapProvider + onRawValueChanged: updateActiveMapType() + } + } } } diff --git a/src/AirspaceManagement/AirspaceFlightPlanProvider.cc b/src/AirspaceManagement/AirspaceFlightPlanProvider.cc index 463949c114e7401b780c5f62bf149280419e1dbd..fde0a6ffe3247e078431112cb9ea7910ed5dc18f 100644 --- a/src/AirspaceManagement/AirspaceFlightPlanProvider.cc +++ b/src/AirspaceManagement/AirspaceFlightPlanProvider.cc @@ -8,14 +8,100 @@ ****************************************************************************/ #include "AirspaceFlightPlanProvider.h" +#include +//----------------------------------------------------------------------------- AirspaceFlightInfo::AirspaceFlightInfo(QObject *parent) : QObject(parent) , _selected(false) { } +//----------------------------------------------------------------------------- AirspaceFlightPlanProvider::AirspaceFlightPlanProvider(QObject *parent) : QObject(parent) { } + +//----------------------------------------------------------------------------- +AirspaceFlightModel::AirspaceFlightModel(QObject *parent) + : QAbstractListModel(parent) +{ + +} + +//----------------------------------------------------------------------------- +AirspaceFlightInfo* +AirspaceFlightModel::get(int index) +{ + if (index < 0 || index >= _flightEntries.count()) { + return NULL; + } + return _flightEntries[index]; +} + +//----------------------------------------------------------------------------- +int +AirspaceFlightModel::count() const +{ + return _flightEntries.count(); +} + +//----------------------------------------------------------------------------- +void +AirspaceFlightModel::append(AirspaceFlightInfo* object) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership); + _flightEntries.append(object); + endInsertRows(); + emit countChanged(); +} + +//----------------------------------------------------------------------------- +void +AirspaceFlightModel::clear(void) +{ + if(!_flightEntries.isEmpty()) { + beginRemoveRows(QModelIndex(), 0, _flightEntries.count()); + while (_flightEntries.count()) { + AirspaceFlightInfo* entry = _flightEntries.last(); + if(entry) entry->deleteLater(); + _flightEntries.removeLast(); + } + endRemoveRows(); + emit countChanged(); + } +} + +//----------------------------------------------------------------------------- +AirspaceFlightInfo* +AirspaceFlightModel::operator[](int index) +{ + return get(index); +} + +//----------------------------------------------------------------------------- +int +AirspaceFlightModel::rowCount(const QModelIndex& /*parent*/) const +{ + return _flightEntries.count(); +} + +//----------------------------------------------------------------------------- +QVariant +AirspaceFlightModel::data(const QModelIndex & index, int role) const { + if (index.row() < 0 || index.row() >= _flightEntries.count()) + return QVariant(); + if (role == ObjectRole) + return QVariant::fromValue(_flightEntries[index.row()]); + return QVariant(); +} + +//----------------------------------------------------------------------------- +QHash +AirspaceFlightModel::roleNames() const { + QHash roles; + roles[ObjectRole] = "flightEntry"; + return roles; +} diff --git a/src/AirspaceManagement/AirspaceFlightPlanProvider.h b/src/AirspaceManagement/AirspaceFlightPlanProvider.h index 6fa119c29425c7136325b6522db6788d508ed8c5..9d4e3da8fce93fc3c180bb982af77e73a6946e1a 100644 --- a/src/AirspaceManagement/AirspaceFlightPlanProvider.h +++ b/src/AirspaceManagement/AirspaceFlightPlanProvider.h @@ -19,8 +19,10 @@ #include #include +#include class PlanMasterController; +class AirspaceFlightInfo; //----------------------------------------------------------------------------- class AirspaceFlightInfo : public QObject @@ -30,17 +32,17 @@ public: AirspaceFlightInfo (QObject *parent = nullptr); Q_PROPERTY(QString flightID READ flightID CONSTANT) - Q_PROPERTY(QDateTime createdTime READ createdTime CONSTANT) - Q_PROPERTY(QDateTime startTime READ startTime CONSTANT) - Q_PROPERTY(QDateTime endTime READ endTime CONSTANT) + Q_PROPERTY(QString createdTime READ createdTime CONSTANT) + Q_PROPERTY(QString startTime READ startTime CONSTANT) + Q_PROPERTY(QString endTime READ endTime CONSTANT) Q_PROPERTY(QGeoCoordinate takeOff READ takeOff CONSTANT) Q_PROPERTY(QmlObjectListModel* boundingBox READ boundingBox CONSTANT) Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged) virtual QString flightID () = 0; - virtual QDateTime createdTime () = 0; - virtual QDateTime startTime () = 0; - virtual QDateTime endTime () = 0; + virtual QString createdTime () = 0; + virtual QString startTime () = 0; + virtual QString endTime () = 0; virtual QGeoCoordinate takeOff () = 0; virtual QmlObjectListModel* boundingBox () = 0; @@ -54,6 +56,40 @@ protected: bool _selected; }; +//----------------------------------------------------------------------------- +class AirspaceFlightModel : public QAbstractListModel +{ + Q_OBJECT +public: + + enum QGCLogModelRoles { + ObjectRole = Qt::UserRole + 1 + }; + + AirspaceFlightModel(QObject *parent = 0); + + Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_INVOKABLE AirspaceFlightInfo* get(int index); + + int count (void) const; + void append (AirspaceFlightInfo *entry); + void clear (void); + + AirspaceFlightInfo* + operator[] (int i); + + int rowCount (const QModelIndex & parent = QModelIndex()) const; + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + +signals: + void countChanged (); + +protected: + QHash roleNames() const; +private: + QList _flightEntries; +}; + //----------------------------------------------------------------------------- class AirspaceFlightPlanProvider : public QObject { @@ -85,7 +121,7 @@ public: Q_PROPERTY(QmlObjectListModel* rulesReview READ rulesReview NOTIFY rulesChanged) Q_PROPERTY(QmlObjectListModel* rulesFollowing READ rulesFollowing NOTIFY rulesChanged) Q_PROPERTY(QmlObjectListModel* briefFeatures READ briefFeatures NOTIFY rulesChanged) - Q_PROPERTY(QmlObjectListModel* flightList READ flightList NOTIFY flightListChanged) + Q_PROPERTY(AirspaceFlightModel* flightList READ flightList NOTIFY flightListChanged) //-- TODO: This will submit the current flight plan in memory. Q_INVOKABLE virtual void submitFlightPlan () = 0; @@ -106,7 +142,7 @@ public: virtual QmlObjectListModel* rulesReview () = 0; ///< List of AirspaceRule should review virtual QmlObjectListModel* rulesFollowing () = 0; ///< List of AirspaceRule following virtual QmlObjectListModel* briefFeatures () = 0; ///< List of AirspaceRule in violation - virtual QmlObjectListModel* flightList () = 0; ///< List of AirspaceFlightInfo + virtual AirspaceFlightModel*flightList () = 0; ///< List of AirspaceFlightInfo virtual void setFlightStartTime (QDateTime start) = 0; virtual void setFlightEndTime (QDateTime end) = 0;