Commit f91c3ae6 authored by Gus Grubba's avatar Gus Grubba

Rules and advisories

parent 7f35db33
......@@ -16,6 +16,8 @@ using namespace airmap;
AirMapRule::AirMapRule(QObject* parent)
: AirspaceRule(parent)
, _isDefault(false)
, _selected(false)
, _selectionType(AirspaceRule::Optional)
{
}
......@@ -55,7 +57,8 @@ void AirMapRulesetsManager::setROI(const QGeoCoordinate& center)
for (const auto& ruleset : rules) {
AirMapRule* pRule = new AirMapRule(this);
pRule->_id = QString::fromStdString(ruleset.id);
pRule->_name = QString::fromStdString(ruleset.short_name);
pRule->_name = QString::fromStdString(ruleset.name);
pRule->_shortName = QString::fromStdString(ruleset.short_name);
pRule->_description = QString::fromStdString(ruleset.description);
pRule->_isDefault = ruleset.is_default;
if(pRule->_isDefault) {
......@@ -66,14 +69,14 @@ void AirMapRulesetsManager::setROI(const QGeoCoordinate& center)
}
switch(ruleset.selection_type) {
case RuleSet::SelectionType::pickone:
pRule->_selectionType = AirspaceRule::pickone;
pRule->_selectionType = AirspaceRule::Pickone;
break;
case RuleSet::SelectionType::required:
pRule->_selectionType = AirspaceRule::required;
pRule->_selectionType = AirspaceRule::Required;
break;
default:
case RuleSet::SelectionType::optional:
pRule->_selectionType = AirspaceRule::optional;
pRule->_selectionType = AirspaceRule::Optional;
break;
}
_rules.append(pRule);
......
......@@ -33,12 +33,17 @@ public:
QString description () override { return _description; }
bool isDefault () override { return _isDefault; }
QString name () override { return _name; }
QString shortName () override { return _shortName; }
SelectionType selectionType () override { return _selectionType; }
bool selected () override { return _selected; }
void setSelected (bool sel) override { _selected = sel; emit selectedChanged(); }
private:
QString _id;
QString _description;
bool _isDefault;
bool _selected;
QString _name;
QString _shortName;
SelectionType _selectionType;
};
......
......@@ -14,6 +14,14 @@
using namespace airmap;
//-----------------------------------------------------------------------------
AirMapAdvisory::AirMapAdvisory(QObject* parent)
: AirspaceAdvisory(parent)
, _radius(0.0)
{
}
//-----------------------------------------------------------------------------
AirMapAdvisories::AirMapAdvisories(AirMapSharedState& shared, QObject *parent)
: AirspaceAdvisoryProvider(parent)
, _valid(false)
......@@ -21,6 +29,7 @@ AirMapAdvisories::AirMapAdvisories(AirMapSharedState& shared, QObject *parent)
{
}
//-----------------------------------------------------------------------------
void
AirMapAdvisories::setROI(const QGeoCoordinate& center, double radiusMeters)
{
......@@ -31,6 +40,17 @@ AirMapAdvisories::setROI(const QGeoCoordinate& center, double radiusMeters)
}
}
//-----------------------------------------------------------------------------
static bool
adv_sort(QObject* a, QObject* b)
{
AirMapAdvisory* aa = qobject_cast<AirMapAdvisory*>(a);
AirMapAdvisory* bb = qobject_cast<AirMapAdvisory*>(b);
if(!aa || !bb) return false;
return aa->color() > bb->color();
}
//-----------------------------------------------------------------------------
void
AirMapAdvisories::_requestAdvisories(const QGeoCoordinate& coordinate, double radiusMeters)
{
......@@ -41,8 +61,8 @@ AirMapAdvisories::_requestAdvisories(const QGeoCoordinate& coordinate, double ra
emit advisoryChanged();
return;
}
_advisories.clear();
_valid = false;
_airspaces.clearAndDeleteContents();
Status::GetStatus::Parameters params;
params.longitude = coordinate.longitude();
params.latitude = coordinate.latitude();
......@@ -50,16 +70,27 @@ AirMapAdvisories::_requestAdvisories(const QGeoCoordinate& coordinate, double ra
params.buffer = radiusMeters;
_shared.client()->status().get_status_by_point(params, [this, coordinate](const Status::GetStatus::Result& result) {
if (result) {
qCDebug(AirMapManagerLog) << _advisories.size() << "Advisories Received";
_advisories = result.value().advisories;
_advisory_color = result.value().advisory_color;
if(_advisories.size()) {
_valid = true;
qCDebug(AirMapManagerLog) << "Advisory Info: " << _advisories.size() << _advisories[0].airspace.name().data();
qCDebug(AirMapManagerLog) << "Successful advisory search. Items:" << result.value().advisories.size();
_airspaceColor = (AirspaceAdvisoryProvider::AdvisoryColor)(int)result.value().advisory_color;
const std::vector<Status::Advisory> advisories = result.value().advisories;
for (const auto& advisory : advisories) {
AirMapAdvisory* pAdvisory = new AirMapAdvisory(this);
pAdvisory->_id = QString::fromStdString(advisory.airspace.id());
pAdvisory->_name = QString::fromStdString(advisory.airspace.name());
pAdvisory->_type = (AirspaceAdvisory::AdvisoryType)(int)advisory.airspace.type();
pAdvisory->_color = (AirspaceAdvisoryProvider::AdvisoryColor)(int)advisory.color;
//-- TODO: Add airspace center coordinates and radius (easy to get from Json but
// I have no idea how to get it from airmap::Airspace.)
// pAdvisory->_coordinates = QGeoCoordinate( something );
// pAdvisory->_radius = something ;
_airspaces.append(pAdvisory);
qCDebug(AirMapManagerLog) << "Adding advisory" << pAdvisory->name();
}
//-- Sort in order of color (priority)
std::sort(_airspaces.objectList()->begin(), _airspaces.objectList()->end(), adv_sort);
_valid = true;
} else {
qCDebug(AirMapManagerLog) << "Advisories Request Failed";
_valid = false;
}
emit advisoryChanged();
});
......
......@@ -9,6 +9,8 @@
#pragma once
#include "QmlObjectListModel.h"
#include "LifetimeChecker.h"
#include "AirspaceAdvisoryProvider.h"
......@@ -23,26 +25,46 @@
* Advisory information provided by AirMap.
*/
//-----------------------------------------------------------------------------
class AirMapAdvisory : public AirspaceAdvisory
{
Q_OBJECT
friend class AirMapAdvisories;
public:
AirMapAdvisory (QObject* parent = NULL);
QString id () override { return _id; }
QString name () override { return _name; }
AdvisoryType type () override { return _type; }
QGeoCoordinate coordinates () override { return _coordinates; }
qreal radius () override { return _radius; }
AirspaceAdvisoryProvider::AdvisoryColor color () override { return _color; }
private:
QString _id;
QString _name;
AdvisoryType _type;
QGeoCoordinate _coordinates;
qreal _radius;
AirspaceAdvisoryProvider::AdvisoryColor _color;
};
//-----------------------------------------------------------------------------
class AirMapAdvisories : public AirspaceAdvisoryProvider, public LifetimeChecker
{
Q_OBJECT
public:
AirMapAdvisories (AirMapSharedState &shared, QObject *parent = nullptr);
bool valid () override { return _valid; }
AdvisoryColor airspaceColor () override { return _airspaceColor; }
QmlObjectListModel* airspaces () override { return &_airspaces; }
void setROI (const QGeoCoordinate& center, double radiusMeters) override;
signals:
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
private:
void _requestAdvisories (const QGeoCoordinate& coordinate, double radiusMeters);
private:
bool _valid;
AirMapSharedState& _shared;
QGeoCoordinate _lastRoiCenter;
airmap::Status::Color _advisory_color;
std::vector<airmap::Status::Advisory> _advisories;
QmlObjectListModel _airspaces;
AdvisoryColor _airspaceColor;
};
......@@ -24,6 +24,7 @@ Item {
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool validRules: _activeVehicle ? _activeVehicle.airspaceController.rulesets.valid : false
property bool validAdvisories: _activeVehicle ? _activeVehicle.airspaceController.advisories.valid : false
readonly property real _radius: ScreenTools.defaultFontPixelWidth * 0.5
readonly property color _colorOrange: "#d75e0d"
......@@ -33,19 +34,29 @@ Item {
readonly property color _colorMidBrown: "#3a322f"
readonly property color _colorYellow: "#d7c61d"
readonly property color _colorWhite: "#ffffff"
readonly property color _colorRed: "#aa1200"
readonly property color _colorGreen: "#125f00"
QGCPalette {
id: qgcPal
colorGroupEnabled: enabled
}
function getAispaceColor(color) {
if(color === AirspaceAdvisoryProvider.Green) return _colorGreen;
if(color === AirspaceAdvisoryProvider.Yellow) return _colorYellow;
if(color === AirspaceAdvisoryProvider.Orange) return _colorOrange;
if(color === AirspaceAdvisoryProvider.Red) return _colorRed;
return _colorGray;
}
//---------------------------------------------------------------
//-- Colapsed State
Rectangle {
id: colapsedRect
width: parent.width
height: colapsed ? colapsedRow.height + ScreenTools.defaultFontPixelHeight : 0
color: _colorOrange
color: validAdvisories ? getAispaceColor(_activeVehicle.airspaceController.advisories.airspaceColor) : _colorGray
radius: _radius
visible: colapsed
Row {
......@@ -98,9 +109,15 @@ Item {
id: expandedRect
width: parent.width
height: !colapsed ? expandedCol.height + ScreenTools.defaultFontPixelHeight : 0
color: _colorOrange
color: validAdvisories ? getAispaceColor(_activeVehicle.airspaceController.advisories.airspaceColor) : _colorGray
radius: _radius
visible: !colapsed
MouseArea {
anchors.fill: parent
onWheel: { wheel.accepted = true; }
onPressed: { mouse.accepted = true; }
onReleased: { mouse.accepted = true; }
}
Column {
id: expandedCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
......@@ -133,8 +150,9 @@ Item {
color: _colorWhite
}
QGCLabel {
text: qsTr("3 Advisories")
text: validAdvisories ? _activeVehicle.airspaceController.advisories.airspaces.count + qsTr(" Advisories") : ""
color: _colorWhite
visible: validAdvisories
font.pointSize: ScreenTools.smallFontPointSize
}
}
......@@ -261,25 +279,33 @@ Item {
}
}
}
AirspaceRegulation {
regTitle: qsTr("Controlled Aispace (1)")
regText: qsTr("Santa Monica Class D requires FAA Authorization, permissible below 100ft.")
regColor: _colorOrange
textColor: _colorWhite
Flickable {
clip: true
height: ScreenTools.defaultFontPixelHeight * 8
contentHeight: advisoryCol.height
flickableDirection: Flickable.VerticalFlick
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.5
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 0.5
}
AirspaceRegulation {
regTitle: qsTr("Schools (2)")
regText: qsTr("Santa Monica School of Something.")
regColor: _colorYellow
textColor: _colorWhite
anchors.rightMargin:ScreenTools.defaultFontPixelWidth * 0.5
Column {
id: advisoryCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.right: parent.right
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.5
Repeater {
model: validAdvisories ? _activeVehicle.airspaceController.advisories.airspaces : []
delegate: AirspaceRegulation {
regTitle: object.typeStr
regText: object.name
regColor: getAispaceColor(object.color)
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 0.5
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
}
}
}
}
}
}
......@@ -358,33 +384,69 @@ Item {
flickableDirection: Flickable.VerticalFlick
Column {
id: rulesetCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
spacing: ScreenTools.defaultFontPixelHeight * 0.25
anchors.right: parent.right
anchors.left: parent.left
anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 2
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
Item {
width: 1
height: 1
}
QGCLabel {
text: qsTr("PICK ONE REGULATION")
font.pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
}
Repeater {
model: validRules ? _activeVehicle.airspaceController.rulesets.rules : []
delegate: Row {
spacing: ScreenTools.defaultFontPixelWidth
delegate: RuleSelector {
visible: object.selectionType === AirspaceRule.Pickone
rule: object
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
Rectangle {
width: ScreenTools.defaultFontPixelWidth * 0.75
height: ScreenTools.defaultFontPixelHeight
color: qgcPal.colorGreen
anchors.verticalCenter: parent.verticalCenter
}
}
Item {
width: 1
height: 1
}
QGCLabel {
text: object.name
text: qsTr("OPTIONAL")
font.pointSize: ScreenTools.smallFontPointSize
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
}
Repeater {
model: validRules ? _activeVehicle.airspaceController.rulesets.rules : []
delegate: RuleSelector {
visible: object.selectionType === AirspaceRule.Optional
rule: object
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
}
}
Item {
width: 1
height: 1
}
QGCLabel {
text: qsTr("REQUIRED")
font.pointSize: ScreenTools.smallFontPointSize
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
}
Repeater {
model: validRules ? _activeVehicle.airspaceController.rulesets.rules : []
delegate: RuleSelector {
visible: object.selectionType === AirspaceRule.Required
rule: object
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
}
}
}
......
......@@ -3,3 +3,4 @@ Module QGroundControl.Airmap
AirspaceControl 1.0 AirspaceControl.qml
AirspaceRegulation 1.0 AirspaceRegulation.qml
AirspaceWeather 1.0 AirspaceWeather.qml
RuleSelector 1.0 RuleSelector.qml
\ No newline at end of file
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQml 2.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Airmap 1.0
import QGroundControl.SettingsManager 1.0
Rectangle {
height: ScreenTools.defaultFontPixelHeight * 1.25
color: rule && rule.selected ? qgcPal.windowShadeDark : qgcPal.window
property var rule: null
QGCPalette {
id: qgcPal
colorGroupEnabled: enabled
}
Row {
id: ruleRow
spacing: ScreenTools.defaultFontPixelWidth
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
Rectangle {
width: ScreenTools.defaultFontPixelWidth * 0.75
height: ScreenTools.defaultFontPixelHeight
color: rule.selected ? qgcPal.colorGreen : qgcPal.window
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: rule.name === "" ? rule.shortName : rule.name
font.pointSize: ScreenTools.smallFontPointSize
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
onClicked: {
rule.selected = !rule.selected
}
}
}
......@@ -4,6 +4,7 @@
<file alias="QGroundControl/Airmap/AirspaceControl.qml">AirspaceControl.qml</file>
<file alias="QGroundControl/Airmap/AirspaceRegulation.qml">AirspaceRegulation.qml</file>
<file alias="QGroundControl/Airmap/AirspaceWeather.qml">AirspaceWeather.qml</file>
<file alias="QGroundControl/Airmap/RuleSelector.qml">RuleSelector.qml</file>
<file alias="AirmapSettings.qml">AirmapSettings.qml</file>
</qresource>
<qresource prefix="/json">
......
......@@ -9,7 +9,38 @@
#include "AirspaceAdvisoryProvider.h"
AirspaceAdvisory::AirspaceAdvisory(QObject* parent)
: QObject(parent)
{
}
AirspaceAdvisoryProvider::AirspaceAdvisoryProvider(QObject *parent)
: QObject(parent)
{
}
//-- TODO: This enum is a bitmask, which implies an airspace can be any
// combination of these types. However, I have not seen any that this
// was the case.
QString
AirspaceAdvisory::typeStr()
{
switch(type()) {
case Airport: return QString(tr("Airport")); break;
case Controlled_airspace: return QString(tr("Controlled Airspace")); break;
case Special_use_airspace: return QString(tr("Special Use Airspace")); break;
case Tfr: return QString(tr("TFR")); break;
case Wildfire: return QString(tr("Wild Fire")); break;
case Park: return QString(tr("Park")); break;
case Power_plant: return QString(tr("Power Plant")); break;
case Heliport: return QString(tr("Heliport")); break;
case Prison: return QString(tr("Prison")); break;
case School: return QString(tr("School")); break;
case Hospital: return QString(tr("Hospital")); break;
case Fire: return QString(tr("Fire")); break;
case Emergency: return QString(tr("Emergency")); break;
case Invalid: return QString(tr("Invalid")); break;
default: return QString(tr("Unknown")); break;
}
}
......@@ -14,19 +14,36 @@
* Weather information provided by the Airspace Managemement
*/
#include "QmlObjectListModel.h"
#include <QObject>
#include <QGeoCoordinate>
//-----------------------------------------------------------------------------
class AirspaceAdvisoryProvider : public QObject
{
Q_OBJECT
public:
enum AdvisoryColor {
Green,
Yellow,
Orange,
Red
};
Q_ENUM(AdvisoryColor)
AirspaceAdvisoryProvider (QObject *parent = nullptr);
virtual ~AirspaceAdvisoryProvider () {}
Q_PROPERTY(bool valid READ valid NOTIFY advisoryChanged)
Q_PROPERTY(AdvisoryColor airspaceColor READ airspaceColor NOTIFY advisoryChanged)
Q_PROPERTY(QmlObjectListModel* airspaces READ airspaces NOTIFY advisoryChanged)
virtual bool valid () = 0; ///< Current data is valid
virtual AdvisoryColor airspaceColor () = 0; ///< Aispace overall color
virtual QmlObjectListModel* airspaces () = 0; ///< List of AirspaceAdvisory
/**
* Set region of interest that should be queried. When finished, the advisoryChanged() signal will be emmited.
......@@ -37,3 +54,50 @@ public:
signals:
void advisoryChanged ();
};
//-----------------------------------------------------------------------------
class AirspaceAdvisory : public QObject
{
Q_OBJECT
public:
enum AdvisoryType {
Invalid = 0,
Airport = 1 << 0,
Controlled_airspace = 1 << 1,
Special_use_airspace = 1 << 2,
Tfr = 1 << 3,
Wildfire = 1 << 4,
Park = 1 << 5,
Power_plant = 1 << 6,
Heliport = 1 << 7,
Prison = 1 << 8,
School = 1 << 9,
Hospital = 1 << 10,
Fire = 1 << 11,
Emergency = 1 << 12,
};
Q_ENUM(AdvisoryType)
AirspaceAdvisory (QObject* parent = NULL);
Q_PROPERTY(QString id READ id CONSTANT)
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(AdvisoryType type READ type CONSTANT)
Q_PROPERTY(QString typeStr READ typeStr CONSTANT)
Q_PROPERTY(QGeoCoordinate coordinates READ coordinates CONSTANT)
Q_PROPERTY(qreal radius READ radius CONSTANT)
Q_PROPERTY(AirspaceAdvisoryProvider::AdvisoryColor color READ color CONSTANT)
virtual QString id () = 0;
virtual QString name () = 0;
virtual AdvisoryType type () = 0;
virtual QString typeStr ();
virtual QGeoCoordinate coordinates () = 0;
virtual qreal radius () = 0;
virtual AirspaceAdvisoryProvider::AdvisoryColor color () = 0;
};
......@@ -27,9 +27,9 @@ class AirspaceRule : public QObject
public:
enum SelectionType {
pickone, ///< One rule from the overall set needs to be picked.
required, ///< Satisfying the RuleSet is required.
optional ///< Satisfying the RuleSet is not required.
Pickone, ///< One rule from the overall set needs to be picked.
Required, ///< Satisfying the RuleSet is required.
Optional ///< Satisfying the RuleSet is not required.
};
Q_ENUM(SelectionType)
......@@ -38,15 +38,24 @@ public:
Q_PROPERTY(QString id READ id CONSTANT)
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString shortName READ shortName CONSTANT)
Q_PROPERTY(QString description READ description CONSTANT)
Q_PROPERTY(bool isDefault READ isDefault CONSTANT)
Q_PROPERTY(SelectionType selectionType READ selectionType CONSTANT)
Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged)
virtual QString id () = 0;
virtual QString description () = 0;
virtual bool isDefault () = 0;
virtual QString name () = 0;
virtual QString shortName () = 0;
virtual SelectionType selectionType () = 0;
virtual bool selected () = 0;
virtual void setSelected (bool sel) = 0;
signals:
void selectedChanged ();
};
//-----------------------------------------------------------------------------
......
......@@ -31,21 +31,22 @@ public:
// Property accessors
int count(void) const;
bool dirty(void) const { return _dirty; }
void setDirty(bool dirty);
void append(QObject* object);
QObjectList swapObjectList(const QObjectList& newlist);
void clear(void);
QObject* removeAt(int i);
QObject* removeOne(QObject* object) { return removeAt(indexOf(object)); }
void insert(int i, QObject* object);
QObject* operator[](int i);
const QObject* operator[](int i) const;
bool contains(QObject* object) { return _objectList.indexOf(object) != -1; }
int indexOf(QObject* object) { return _objectList.indexOf(object); }
int count (void) const;
bool dirty (void) const { return _dirty; }
void setDirty (bool dirty);
void append (QObject* object);
QObjectList swapObjectList (const QObjectList& newlist);
void clear (void);
QObject* removeAt (int i);
QObject* removeOne (QObject* object) { return removeAt(indexOf(object)); }
void insert (int i, QObject* object);
QObject* operator[] (int i);
const QObject* operator[] (int i) const;
bool contains (QObject* object) { return _objectList.indexOf(object) != -1; }
int indexOf (QObject* object) { return _objectList.indexOf(object); }
QList<QObject*>* objectList () { return &_objectList; }
template<class T> T value(int index) { return qobject_cast<T>(_objectList[index]); }
/// Calls deleteLater on all items and this itself.
......@@ -55,11 +56,11 @@ public:
void clearAndDeleteContents(void);
signals:
void countChanged(int count);
void dirtyChanged(bool dirtyChanged);
void countChanged (int count);
void dirtyChanged (bool dirtyChanged);
private slots:
void _childDirtyChanged(bool dirty);
void _childDirtyChanged (bool dirty);
private:
// Overrides from QAbstractListModel
......
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