Commit 3b5740bc authored by Pritam Ghanghas's avatar Pritam Ghanghas

Merge branch 'master' of https://github.com/mavlink/qgroundcontrol into apm_mode_support

parents 3a3a8afc 3ba9c2f8
......@@ -21,23 +21,25 @@ test_script:
- if "%CONFIG%" EQU "debug" ( debug\qgroundcontrol --unittest )
after_build:
- if "%CONFIG%" EQU "installer" ( appveyor PushArtifact C:\projects\qgroundcontrol\release\qgroundcontrol-installer-win32.exe )
- if "%CONFIG%" EQU "installer" ( appveyor PushArtifact C:\projects\qgroundcontrol\release\qgroundcontrol.exe )
deploy:
- provider: S3
name: qgroundcontrol-s3
access_key_id: AKIAIVORNALE7NHD3T6Q
access_key_id:
secure: IGAojLMqokL+76DbdulmWDA3MTsxEBBi3ReVVSqTy9c=
secret_access_key:
secure: RiYqaR+3T2PMNz2j5ur8LCA6H/Zfd4jTX33CZE5iBxm+zaz4QLs25p0B7prpaoNN
bucket: qgrondcontrol
bucket: qgroundcontrol
set_public: true
folder: "%APPVEYOR_REPO_BRANCH%"
artifact: C:\projects\qgroundcontrol\release\qgroundcontrol-installer-win32.exe
folder: $(APPVEYOR_REPO_BRANCH)
artifcat: 'release\qgroundcontrol.exe'
on:
CONFIG: installer
- provider: GitHub
artifact: C:\projects\qgroundcontrol\release\qgroundcontrol-installer-win32.exe
artifact: 'release\qgroundcontrol.exe'
draft: false
prerelease: false
on:
CONFIG: installer
appveyor_repo_tag: true
\ No newline at end of file
......@@ -162,12 +162,10 @@ INCLUDEPATH += \
FORMS += \
src/QGCQmlWidgetHolder.ui \
src/ui/Linechart.ui \
src/ui/LogReplayLinkConfigurationWidget.ui \
src/ui/MainWindow.ui \
src/ui/MAVLinkSettingsWidget.ui \
src/ui/QGCCommConfiguration.ui \
src/ui/QGCDataPlot2D.ui \
src/ui/QGCLinkConfiguration.ui \
src/ui/QGCMapRCToParamDialog.ui \
src/ui/QGCMAVLinkLogPlayer.ui \
......@@ -185,7 +183,9 @@ FORMS += \
!MobileBuild {
FORMS += \
src/ui/Linechart.ui \
src/ui/MultiVehicleDockWidget.ui \
src/ui/QGCDataPlot2D.ui \
src/ui/QGCHilConfiguration.ui \
src/ui/QGCHilFlightGearConfiguration.ui \
src/ui/QGCHilJSBSimConfiguration.ui \
......@@ -230,6 +230,7 @@ HEADERS += \
src/QGCApplication.h \
src/QGCComboBox.h \
src/QGCConfig.h \
src/QGCDockWidget.h \
src/QGCFileDialog.h \
src/QGCGeo.h \
src/QGCLoggingCategory.h \
......@@ -251,19 +252,11 @@ HEADERS += \
src/uas/UAS.h \
src/uas/UASInterface.h \
src/uas/UASMessageHandler.h \
src/ui/linechart/ChartPlot.h \
src/ui/linechart/IncrementalPlot.h \
src/ui/linechart/LinechartPlot.h \
src/ui/linechart/Linecharts.h \
src/ui/linechart/LinechartWidget.h \
src/ui/linechart/Scrollbar.h \
src/ui/linechart/ScrollZoomer.h \
src/ui/LogReplayLinkConfigurationWidget.h \
src/ui/MainWindow.h \
src/ui/MAVLinkDecoder.h \
src/ui/MAVLinkSettingsWidget.h \
src/ui/QGCCommConfiguration.h \
src/ui/QGCDataPlot2D.h \
src/ui/QGCLinkConfiguration.h \
src/ui/QGCMapRCToParamDialog.h \
src/ui/QGCMAVLinkLogPlayer.h \
......@@ -289,10 +282,17 @@ HEADERS += \
src/comm/QGCHilLink.h \
src/comm/QGCJSBSimLink.h \
src/comm/QGCXPlaneLink.h \
src/QGCDockWidget.h \
src/ui/CameraView.h \
src/ui/HILDockWidget.h \
src/ui/linechart/ChartPlot.h \
src/ui/linechart/IncrementalPlot.h \
src/ui/linechart/LinechartPlot.h \
src/ui/linechart/Linecharts.h \
src/ui/linechart/LinechartWidget.h \
src/ui/linechart/Scrollbar.h \
src/ui/linechart/ScrollZoomer.h \
src/ui/MultiVehicleDockWidget.h \
src/ui/QGCDataPlot2D.h \
src/ui/QGCHilConfiguration.h \
src/ui/QGCHilFlightGearConfiguration.h \
src/ui/QGCHilJSBSimConfiguration.h \
......@@ -340,6 +340,7 @@ SOURCES += \
src/QGC.cc \
src/QGCApplication.cc \
src/QGCComboBox.cc \
src/QGCDockWidget.cc \
src/QGCFileDialog.cc \
src/QGCLoggingCategory.cc \
src/QGCPalette.cc \
......@@ -356,19 +357,11 @@ SOURCES += \
src/uas/FileManager.cc \
src/uas/UAS.cc \
src/uas/UASMessageHandler.cc \
src/ui/linechart/ChartPlot.cc \
src/ui/linechart/IncrementalPlot.cc \
src/ui/linechart/LinechartPlot.cc \
src/ui/linechart/Linecharts.cc \
src/ui/linechart/LinechartWidget.cc \
src/ui/linechart/Scrollbar.cc \
src/ui/linechart/ScrollZoomer.cc \
src/ui/LogReplayLinkConfigurationWidget.cc \
src/ui/MainWindow.cc \
src/ui/MAVLinkDecoder.cc \
src/ui/MAVLinkSettingsWidget.cc \
src/ui/QGCCommConfiguration.cc \
src/ui/QGCDataPlot2D.cc \
src/ui/QGCLinkConfiguration.cc \
src/ui/QGCMapRCToParamDialog.cpp \
src/ui/QGCMAVLinkLogPlayer.cc \
......@@ -393,10 +386,17 @@ SOURCES += \
src/comm/QGCFlightGearLink.cc \
src/comm/QGCJSBSimLink.cc \
src/comm/QGCXPlaneLink.cc \
src/QGCDockWidget.cc \
src/ui/CameraView.cc \
src/ui/HILDockWidget.cc \
src/ui/linechart/ChartPlot.cc \
src/ui/linechart/IncrementalPlot.cc \
src/ui/linechart/LinechartPlot.cc \
src/ui/linechart/Linecharts.cc \
src/ui/linechart/LinechartWidget.cc \
src/ui/linechart/Scrollbar.cc \
src/ui/linechart/ScrollZoomer.cc \
src/ui/MultiVehicleDockWidget.cc \
src/ui/QGCDataPlot2D.cc \
src/ui/QGCHilConfiguration.cc \
src/ui/QGCHilFlightGearConfiguration.cc \
src/ui/QGCHilJSBSimConfiguration.cc \
......
......@@ -46,7 +46,7 @@ installer {
# easier to debug user crashes.
#QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY $${DESTDIR_WIN}\\qgroundcontrol.pdb
#QMAKE_POST_LINK += $$escape_expand(\\n) del $${DESTDIR_WIN}\\qgroundcontrol.pdb
QMAKE_POST_LINK += $$escape_expand(\\n) $$quote("\"C:\\Program Files \(x86\)\\NSIS\\makensis.exe\"" /NOCD "\"/XOutFile $${DESTDIR_WIN}\\qgroundcontrol-installer-win32.exe\"" "$$BASEDIR_WIN\\deploy\\qgroundcontrol_installer.nsi")
QMAKE_POST_LINK += $$escape_expand(\\n) $$quote("\"C:\\Program Files \(x86\)\\NSIS\\makensis.exe\"" /NOCD "\"/XOutFile $${DESTDIR_WIN}\\qgroundcontrol.exe\"" "$$BASEDIR_WIN\\deploy\\qgroundcontrol_installer.nsi")
#QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY qgroundcontrol.pdb $${DESTDIR_WIN}
#QMAKE_POST_LINK += $$escape_expand(\\n) del qgroundcontrol.pdb
OTHER_FILES += deploy/qgroundcontrol_installer.nsi
......
......@@ -63,7 +63,7 @@ Supported builds are 64 bit, built using the clang compiler.
Supported builds for Linux are 32 or 64-bit, built using gcc.
#### Install Qt5.4 and SDL1.2 prerequistites
* For Fedora: `sudo yum install qt-creator qt5-qtbase-devel qt5-qtdeclarative-devel qt5-qtserialport-devel qt5-qtsvg-devel qt5-qtwebkit-devel SDL-devel SDL-static systemd-devel qt5-qtgraphicaleffects qt5-qtquickcontrols`
* For Fedora: `sudo yum install qt-creator qt5-qtbase-devel qt5-qtdeclarative-devel qt5-qtserialport-devel qt5-qtsvg-devel qt5-qtwebkit-devel SDL-devel SDL-static systemd-devel qt5-qtgraphicaleffects qt5-qtquickcontrols qt5-qtlocation-devel`
* For Arch Linux: `pacman -Sy qtcreator qt5-base qt5-declarative qt5-serialport qt5-svg qt5-webkit`
* For Ubuntu: Please be aware that the time of writing, Qt5.4 is unavailable in the official repositories Ubuntu 14.04/Mint 17
* Add this PPA for Qt5.4: `sudo add-apt-repository ppa:beineri/opt-qt541-trusty`
......
[Desktop Entry]
Type=Application
Name=qgroundcontrol
GenericName=Ground Control Station
Comment=UAS ground control station
Icon=qgroundcontrol
Exec=qgroundcontrol
Terminal=false
Categories=Utility;
Keywords=computer;
......@@ -117,6 +117,7 @@
<file alias="QGroundControl/Controls/DropButton.qml">src/QmlControls/DropButton.qml</file>
<file alias="QGroundControl/Controls/RoundButton.qml">src/QmlControls/RoundButton.qml</file>
<file alias="QGroundControl/Controls/QGCCanvas.qml">src/QmlControls/QGCCanvas.qml</file>
<file alias="QGroundControl/Controls/ExclusiveGroupItem.qml">src/QmlControls/ExclusiveGroupItem.qml</file>
<!-- Vehicle Setup -->
<file alias="SetupView.qml">src/VehicleSetup/SetupView.qml</file>
......
......@@ -35,7 +35,7 @@ This file is part of the QGROUNDCONTROL project
const char* kMainFlightDisplayViewGroup = "FlightDisplayView";
FlightDisplayView::FlightDisplayView(QWidget *parent)
: QGCQmlWidgetHolder(parent)
: QGCQmlWidgetHolder(QString(), NULL, parent)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setObjectName("FlightDisplayView");
......
......@@ -34,8 +34,8 @@ This file is part of the QGROUNDCONTROL project
const char* kMainFlightDisplayWidgetGroup = "FlightDisplayWidget";
FlightDisplayWidget::FlightDisplayWidget(QWidget *parent)
: QGCQmlWidgetHolder(parent)
FlightDisplayWidget::FlightDisplayWidget(const QString& title, QAction* action, QWidget *parent)
: QGCQmlWidgetHolder(title, action, parent)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setObjectName("FlightDisplayWidget");
......@@ -86,6 +86,8 @@ FlightDisplayWidget::FlightDisplayWidget(QWidget *parent)
setSource(QUrl::fromUserInput("qrc:/qml/FlightDisplayWidget.qml"));
setVisible(true);
loadSettings();
}
FlightDisplayWidget::~FlightDisplayWidget()
......
......@@ -30,7 +30,7 @@ class FlightDisplayWidget : public QGCQmlWidgetHolder
{
Q_OBJECT
public:
FlightDisplayWidget(QWidget* parent = NULL);
FlightDisplayWidget(const QString& title, QAction* action, QWidget* parent = NULL);
~FlightDisplayWidget();
/// @brief Invokes the Flight Display Options menu
......
......@@ -50,7 +50,7 @@ Map {
property string mapName: 'defaultMap'
property string mapType: QGroundControl.flightMapSettings.mapTypeForMapName(mapName)
property alias mapWidgets: controlWidgets
property bool isSatelliteMap: false
property bool isSatelliteMap: mapType == "Satellite Map" || mapType == "Hybrid Map"
property real lon: (longitude >= -180 && longitude <= 180) ? longitude : 0
property real lat: (latitude >= -90 && latitude <= 90) ? latitude : 0
......@@ -289,4 +289,11 @@ Map {
}
}
*/
MouseArea {
//-- TODO: Check if this is still needed when we switch to 5.5.1
//-- Workaround for QTBUG-46388 (Pinch zoom doesn't work without it on mobile)
anchors.fill: parent
}
} // Map
......@@ -35,9 +35,11 @@ This file is part of the QGROUNDCONTROL project
const char* MissionEditor::_settingsGroup = "MissionEditor";
MissionEditor::MissionEditor(QWidget *parent)
: QGCQmlWidgetHolder(parent)
: QGCQmlWidgetHolder(QString(), NULL, parent)
, _missionItems(NULL)
, _canEdit(true)
, _activeVehicle(NULL)
, _liveHomePositionAvailable(false)
{
// Get rid of layout default margins
QLayout* pl = layout();
......@@ -45,11 +47,16 @@ MissionEditor::MissionEditor(QWidget *parent)
pl->setContentsMargins(0,0,0,0);
}
Vehicle* activeVehicle = MultiVehicleManager::instance()->activeVehicle();
MultiVehicleManager* multiVehicleMgr = MultiVehicleManager::instance();
connect(multiVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this, &MissionEditor::_activeVehicleChanged);
Vehicle* activeVehicle = multiVehicleMgr->activeVehicle();
if (activeVehicle) {
MissionManager* missionManager = activeVehicle->missionManager();
connect(missionManager, &MissionManager::newMissionItemsAvailable, this, &MissionEditor::_newMissionItemsAvailable);
_newMissionItemsAvailable();
_activeVehicleChanged(activeVehicle);
} else {
_missionItems = new QmlObjectListModel(this);
_initAllMissionItems();
......@@ -135,52 +142,6 @@ void MissionEditor::removeMissionItem(int index)
_recalcAll();
}
void MissionEditor::moveUp(int index)
{
if (!_canEdit) {
qWarning() << "addMissionItem called with _canEdit == false";
return;
}
if (_missionItems->count() < 2 || index <= 0 || index >= _missionItems->count()) {
return;
}
MissionItem item1 = *qobject_cast<MissionItem*>(_missionItems->get(index - 1));
MissionItem item2 = *qobject_cast<MissionItem*>(_missionItems->get(index));
_missionItems->removeAt(index - 1);
_missionItems->removeAt(index - 1);
_missionItems->insert(index - 1, new MissionItem(item2, _missionItems));
_missionItems->insert(index, new MissionItem(item1, _missionItems));
_recalcAll();
}
void MissionEditor::moveDown(int index)
{
if (!_canEdit) {
qWarning() << "addMissionItem called with _canEdit == false";
return;
}
if (_missionItems->count() < 2 || index >= _missionItems->count() - 1) {
return;
}
MissionItem item1 = *qobject_cast<MissionItem*>(_missionItems->get(index));
MissionItem item2 = *qobject_cast<MissionItem*>(_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));
_recalcAll();
}
void MissionEditor::loadMissionFromFile(void)
{
QString errorString;
......@@ -389,3 +350,34 @@ void MissionEditor::_itemCommandChanged(MavlinkQmlSingleton::Qml_MAV_CMD command
_recalcChildItems();
_recalcWaypointLines();
}
void MissionEditor::_activeVehicleChanged(Vehicle* activeVehicle)
{
if (_activeVehicle) {
disconnect(_activeVehicle, &Vehicle::homePositionAvailableChanged, this, &MissionEditor::_activeVehicleHomePositionAvailableChanged);
disconnect(_activeVehicle, &Vehicle::homePositionChanged, this, &MissionEditor::_activeVehicleHomePositionChanged);
_activeVehicle = NULL;
_activeVehicleHomePositionAvailableChanged(false);
}
_activeVehicle = activeVehicle;
if (_activeVehicle) {
connect(_activeVehicle, &Vehicle::homePositionAvailableChanged, this, &MissionEditor::_activeVehicleHomePositionAvailableChanged);
connect(_activeVehicle, &Vehicle::homePositionChanged, this, &MissionEditor::_activeVehicleHomePositionChanged);
_activeVehicleHomePositionChanged(_activeVehicle->homePosition());
_activeVehicleHomePositionAvailableChanged(_activeVehicle->homePositionAvailable());
}
}
void MissionEditor::_activeVehicleHomePositionAvailableChanged(bool homePositionAvailable)
{
_liveHomePositionAvailable = homePositionAvailable;
emit liveHomePositionAvailableChanged(_liveHomePositionAvailable);
}
void MissionEditor::_activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition)
{
_liveHomePosition = homePosition;
emit liveHomePositionChanged(_liveHomePosition);
}
......@@ -26,6 +26,7 @@ This file is part of the QGROUNDCONTROL project
#include "QGCQmlWidgetHolder.h"
#include "QmlObjectListModel.h"
#include "Vehicle.h"
class MissionEditor : public QGCQmlWidgetHolder
{
......@@ -38,6 +39,8 @@ public:
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 liveHomePositionAvailable READ liveHomePositionAvailable NOTIFY liveHomePositionAvailableChanged)
Q_PROPERTY(QGeoCoordinate liveHomePosition READ liveHomePosition NOTIFY liveHomePositionChanged)
Q_INVOKABLE int addMissionItem(QGeoCoordinate coordinate);
Q_INVOKABLE void getMissionItems(void);
......@@ -45,24 +48,29 @@ public:
Q_INVOKABLE void loadMissionFromFile(void);
Q_INVOKABLE void saveMissionToFile(void);
Q_INVOKABLE void removeMissionItem(int index);
Q_INVOKABLE void moveUp(int index);
Q_INVOKABLE void moveDown(int index);
// Property accessors
QmlObjectListModel* missionItems(void) { return _missionItems; }
QmlObjectListModel* waypointLines(void) { return &_waypointLines; }
bool canEdit(void) { return _canEdit; }
bool liveHomePositionAvailable(void) { return _liveHomePositionAvailable; }
QGeoCoordinate liveHomePosition(void) { return _liveHomePosition; }
signals:
void missionItemsChanged(void);
void canEditChanged(bool canEdit);
void waypointLinesChanged(void);
void liveHomePositionAvailableChanged(bool homePositionAvailable);
void liveHomePositionChanged(const QGeoCoordinate& homePosition);
private slots:
void _newMissionItemsAvailable();
void _itemCoordinateChanged(const QGeoCoordinate& coordinate);
void _itemCommandChanged(MavlinkQmlSingleton::Qml_MAV_CMD command);
void _activeVehicleChanged(Vehicle* activeVehicle);
void _activeVehicleHomePositionAvailableChanged(bool homePositionAvailable);
void _activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
private:
void _recalcSequence(void);
......@@ -78,6 +86,9 @@ private:
QmlObjectListModel* _missionItems;
QmlObjectListModel _waypointLines;
bool _canEdit; ///< true: UI can edit these items, false: can't edit, can only send to vehicle or save
Vehicle* _activeVehicle;
bool _liveHomePositionAvailable;
QGeoCoordinate _liveHomePosition;
static const char* _settingsGroup;
};
......
......@@ -46,13 +46,14 @@ QGCView {
readonly property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 16
property var _missionItems: controller.missionItems
property bool _showHomePositionManager: false
property bool _addMissionItems: false
property bool _showHelpPanel: true
property var _homePositionManager: QGroundControl.homePositionManager
property string _homePositionName: _homePositionManager.homePositions.get(0).name
property var homePositionCoordinate: _homePositionManager.homePositions.get(0).coordinate
property var offlineHomePosition: _homePositionManager.homePositions.get(0).coordinate
property var liveHomePosition: controller.liveHomePosition
property var liveHomePositionAvailable: controller.liveHomePositionAvailable
property var homePosition: offlineHomePosition // live or offline depending on state
QGCPalette { id: _qgcPal; colorGroupEnabled: enabled }
......@@ -62,12 +63,7 @@ QGCView {
ExclusiveGroup {
id: _dropButtonsExclusiveGroup
}
function disableToggles() {
_showHomePositionManager = false
_addMissionItems = false
_showHelpPanel = false
onCurrentChanged: console.log("Current button", current)
}
function setCurrentItem(index) {
......@@ -76,20 +72,24 @@ QGCView {
}
}
// Home position is mission item 0, so keep them in sync
onHomePositionCoordinateChanged: {
function updateHomePosition() {
homePosition = liveHomePositionAvailable ? liveHomePosition : offlineHomePosition
// Changing the coordinate will set the dirty bit, so we save and reset it
var dirtyBit = _missionItems.dirty
_missionItems.get(0).coordinate = homePositionCoordinate
_missionItems.get(0).coordinate = homePosition
_missionItems.dirty = dirtyBit
}
Component.onCompleted: onHomePositionCoordinateChanged
Component.onCompleted: updateHomePosition()
onOfflineHomePositionChanged: updateHomePosition()
onLiveHomePositionAvailableChanged: updateHomePosition()
onLiveHomePositionChanged: updateHomePosition()
Connections {
target: controller
onMissionItemsChanged: _missionItems.get(0).coordinate = homePositionCoordinate
// When the mission items change _missionsItems[0] changes as well so we need to reset it to home
onMissionItemsChanged: updateHomePosition
}
QGCViewPanel {
......@@ -108,8 +108,8 @@ QGCView {
mapName: "MissionEditor"
Component.onCompleted: {
latitude = homePositionCoordinate.latitude
longitude = homePositionCoordinate.longitude
latitude = homePosition.latitude
longitude = homePosition.longitude
}
MouseArea {
......@@ -120,9 +120,9 @@ QGCView {
coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
if (_showHomePositionManager) {
homePositionCoordinate = coordinate
} else if (_addMissionItems) {
if (homePositionManagerButton.checked) {
offlineHomePosition = coordinate
} else if (addMissionItemsButton.checked) {
var index = controller.addMissionItem(coordinate)
setCurrentItem(index)
}
......@@ -164,20 +164,12 @@ QGCView {
id: addMissionItemsButton
buttonImage: "/qmlimages/MapAddMission.svg"
exclusiveGroup: _dropButtonsExclusiveGroup
onClicked: {
disableToggles()
_addMissionItems = addMissionItemsButton.checked
}
}
RoundButton {
id: homePositionManagerButton
buttonImage: "/qmlimages/MapHome.svg"
exclusiveGroup: _dropButtonsExclusiveGroup
onClicked: {
disableToggles()
_showHomePositionManager = homePositionManagerButton.checked
}
}
DropButton {
......@@ -187,10 +179,6 @@ QGCView {
viewportMargins: ScreenTools.defaultFontPixelWidth / 2
exclusiveGroup: _dropButtonsExclusiveGroup
onClicked: {
disableToggles()
}
dropDownComponent: Component {
Row {
spacing: ScreenTools.defaultFontPixelWidth
......@@ -200,8 +188,7 @@ QGCView {
onClicked: {
centerMapButton.hideDropDown()
editorMap.center = QtPositioning.coordinate(homePositionCoordinate.latitude, homePositionCoordinate.longitude)
_showHomePositionManager = true
editorMap.center = QtPositioning.coordinate(homePosition.latitude, homePosition.longitude)
}
}
......@@ -229,8 +216,8 @@ QGCView {
centerMapButton.hideDropDown()
// Begin with only the home position in the region
var region = QtPositioning.rectangle(QtPositioning.coordinate(homePositionCoordinate.latitude, _homePositionCoordinate.longitude),
QtPositioning.coordinate(homePositionCoordinate.latitude, _homePositionCoordinate.longitude))
var region = QtPositioning.rectangle(QtPositioning.coordinate(homePosition.latitude, homePosition.longitude),
QtPositioning.coordinate(homePosition.latitude, homePosition.longitude))
// Now expand the region to include all mission items
for (var i=0; i<_missionItems.count; i++) {
......@@ -264,10 +251,6 @@ QGCView {
viewportMargins: ScreenTools.defaultFontPixelWidth / 2
exclusiveGroup: _dropButtonsExclusiveGroup
onClicked: {
disableToggles()
}
dropDownComponent: Component {
Row {
spacing: ScreenTools.defaultFontPixelWidth
......@@ -320,10 +303,6 @@ QGCView {
viewportMargins: ScreenTools.defaultFontPixelWidth / 2
exclusiveGroup: _dropButtonsExclusiveGroup
onClicked: {
disableToggles()
}
dropDownComponent: Component {
Row {
spacing: ScreenTools.defaultFontPixelWidth
......@@ -349,14 +328,9 @@ QGCView {
}
RoundButton {
id: showHelpButton
id: helpButton
buttonImage: "/qmlimages/Help.svg"
exclusiveGroup: _dropButtonsExclusiveGroup
checked: true
onClicked: {
disableToggles()
_showHelpPanel = showHelpButton.checked
}
}
}
......@@ -368,27 +342,15 @@ QGCView {
delegate:
MissionItemIndicator {
id: itemIndicator
label: object.sequenceNumber == 0 ? "H" : object.sequenceNumber
isCurrentItem: !_showHomePositionManager && object.isCurrentItem
label: object.sequenceNumber == 0 ? (liveHomePositionAvailable ? "H" : "F") : object.sequenceNumber
isCurrentItem: !homePositionManagerButton.checked && object.isCurrentItem
coordinate: object.coordinate
z: 2
visible: object.specifiesCoordinate
onClicked: {
disableToggles()
if (_dropButtonsExclusiveGroup.current) {
_dropButtonsExclusiveGroup.current.checked = false
}
//-- Home?
if (object.sequenceNumber === 0) {
homePositionManagerButton.checked = true
_showHomePositionManager = true
//-- Otherwise it's a mission item
} else {
addMissionItemsButton.checked = true
_addMissionItems = true
}
setCurrentItem(object.sequenceNumber)
missionItemEditorButton.checked
}
Row {
......@@ -401,12 +363,12 @@ QGCView {
delegate:
MissionItemIndexLabel {
label: object.sequenceNumber
isCurrentItem: !_showHomePositionManager && object.isCurrentItem
isCurrentItem: !homePositionManagerButton.checked && object.isCurrentItem
z: 2
onClicked: {
_showHomePositionManager = false
setCurrentItem(object.sequenceNumber)
missionItemEditorButton.checked
}
}
......@@ -461,8 +423,9 @@ QGCView {
// Mission Item Editor
Item {
id: missionItemEditor
anchors.fill: parent
visible: !_showHomePositionManager && controller.missionItems.count != 1 && ! _showHelpPanel
visible: !helpButton.checked && !homePositionManagerButton.checked && _missionItems.count > 1
ListView {
id: missionItemSummaryList
......@@ -477,6 +440,7 @@ QGCView {
MissionItemEditor {
missionItem: object
width: parent.width
readOnly: object.sequenceNumber == 0 && liveHomePositionAvailable
onClicked: setCurrentItem(object.sequenceNumber)
......@@ -488,9 +452,6 @@ QGCView {
setCurrentItem(newCurrentItem)
}
}
onMoveUp: controller.moveUp(object.sequenceNumber)
onMoveDown: controller.moveDown(object.sequenceNumber)
}
} // ListView
......@@ -505,15 +466,28 @@ QGCView {
// Home Position Manager
Item {
id: homePositionManager
anchors.fill: parent
visible: _showHomePositionManager && !_showHelpPanel
visible: homePositionManagerButton.checked
Column {
anchors.fill: parent
visible: !liveHomePositionAvailable
QGCLabel {
font.pixelSize: ScreenTools.mediumFontPixelSize
text: "Home Position Manager"
text: "Flying Field Manager"
}
Item {
width: 10
height: ScreenTools.defaultFontPixelHeight
}
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: "This is used to save locations associated with your flying field for use while creating missions with no vehicle connection."
}
Item {
......@@ -522,7 +496,7 @@ QGCView {
}
QGCLabel {
text: "Select home position to use:"
text: "Select field to use:"
}
QGCComboBox {
......@@ -535,9 +509,9 @@ QGCView {
if (currentIndex != -1) {
var homePos = _homePositionManager.homePositions.get(currentIndex)
_homePositionName = homePos.name
homePositionCoordinate = homePos.coordinate
editorMap.latitude = homePositionCoordinate.latitude
editorMap.longitude = homePositionCoordinate.longitude
offlineHomePosition = homePos.coordinate
editorMap.latitude = offlineHomePosition.latitude
editorMap.longitude = offlineHomePosition.longitude
}
}
}
......@@ -550,9 +524,9 @@ QGCView {
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: "To add a new home position, click on the Map to set the position. " +
text: "To add a new flying field, click on the Map to set the position. " +
"Then give it a new name and click Add/Update. " +
"To change the current home position, click on the Map to set the new position. " +
"To change the current field position, click on the Map to set the new position. " +
"Then click Add/Update without changing the name."
}
......@@ -585,18 +559,18 @@ QGCView {
Item {
width: parent.width
height: latitudeField.height
height: offlineLatitudeField.height
QGCLabel {
anchors.baseline: latitudeField.baseline
anchors.baseline: offlineLatitudeField.baseline
text: "Lat:"
}
QGCTextField {
id: latitudeField
id: offlineLatitudeField
anchors.right: parent.right
width: _editFieldWidth
text: homePositionCoordinate.latitude
text: offlineHomePosition.latitude
}
}
......@@ -607,18 +581,18 @@ QGCView {
Item {
width: parent.width
height: longitudeField.height
height: offlineLongitudeField.height
QGCLabel {
anchors.baseline: longitudeField.baseline
anchors.baseline: offlineLongitudeField.baseline
text: "Lon:"
}
QGCTextField {
id: longitudeField
id: offlineLongitudeField
anchors.right: parent.right
width: _editFieldWidth
text: homePositionCoordinate.longitude
text: offlineHomePosition.longitude
}
}
......@@ -629,18 +603,18 @@ QGCView {
Item {
width: parent.width
height: altitudeField.height
height: offlineAltitudeField.height
QGCLabel {
anchors.baseline: altitudeField.baseline
anchors.baseline: offlineAltitudeField.baseline
text: "Alt:"
}
QGCTextField {
id: altitudeField
id: offlineAltitudeField
anchors.right: parent.right
width: _editFieldWidth
text: homePositionCoordinate.altitude
text: offlineHomePosition.altitude
}
}
......@@ -656,8 +630,8 @@ QGCView {
text: "Add/Update"
onClicked: {
homePositionCoordinate = QtPositioning.coordinate(latitudeField.text, longitudeField.text, altitudeField.text)
_homePositionManager.updateHomePosition(nameField.text, homePositionCoordinate)
offlineHomePosition = QtPositioning.coordinate(latitudeField.text, longitudeField.text, altitudeField.text)
_homePositionManager.updateHomePosition(nameField.text, offlineHomePosition)
homePosCombo.currentIndex = homePosCombo.find(nameField.text)
}
}
......@@ -671,17 +645,95 @@ QGCView {
homePosCombo.currentIndex = 0
var homePos = _homePositionManager.homePositions.get(0)
_homePositionName = homePos.name
homePositionCoordinate = homePos.coordinate
offlineHomePosition = homePos.coordinate
}
}
}
} // Column - Offline view
Column {
anchors.fill: parent
visible: liveHomePositionAvailable
QGCLabel {
font.pixelSize: ScreenTools.mediumFontPixelSize
text: "Vehicle Home Position"
}
Item {
width: 10
height: ScreenTools.defaultFontPixelHeight
}
Item {
width: parent.width
height: liveLatitudeField.height
QGCLabel {
anchors.baseline: liveLatitudeField.baseline
text: "Lat:"
}
QGCLabel {
id: liveLatitudeField
anchors.right: parent.right
width: _editFieldWidth
text: liveHomePosition.latitude
}
}
Item {
width: 10
height: ScreenTools.defaultFontPixelHeight / 3
}
Item {
width: parent.width
height: liveLongitudeField.height
QGCLabel {
anchors.baseline: liveLongitudeField.baseline
text: "Lon:"
}
QGCLabel {
id: liveLongitudeField
anchors.right: parent.right
width: _editFieldWidth
text: liveHomePosition.longitude
}
}
Item {
width: 10
height: ScreenTools.defaultFontPixelHeight / 3
}
} // Column
Item {
width: parent.width
height: liveAltitudeField.height
QGCLabel {
anchors.baseline: liveAltitudeField.baseline
text: "Alt:"
}
QGCLabel {
id: liveAltitudeField
anchors.right: parent.right
width: _editFieldWidth
text: liveHomePosition.altitude
}
}
} // Column - Online view
} // Item - Home Position Manager
// Help Panel
Item {
id: helpPanel
anchors.fill: parent
visible: !_showHomePositionManager && (controller.missionItems.count == 1 || _showHelpPanel)
visible: !homePositionManagerButton.checked && (_missionItems.count == 1 || helpButton.checked)
QGCLabel {
id: helpTitle
......@@ -738,9 +790,9 @@ QGCView {
anchors.right: parent.right
anchors.top: homePositionManagerHelpIcon.top
wrapMode: Text.WordWrap
text: "<b>Home Position Manager</b><br>" +
"When enabled, allows you to select/add/update home positions. " +
"You can save multiple home position to represent multiple flying areas."
text: "<b>Flying Field Manager</b><br>" +
"When enabled, allows you to select/add/update flying field locations. " +
"You can save multiple flying field locations for use while creating missions while you are not connected to your vehicle."
}
Image {
......
......@@ -450,9 +450,11 @@ bool QGCApplication::_initForNormalAppBoot(void)
splashScreen->finish(mainWindow);
mainWindow->splashScreenFinished();
#ifndef __mobile__
// Now that main window is up check for lost log files
connect(this, &QGCApplication::checkForLostLogFiles, MAVLinkProtocol::instance(), &MAVLinkProtocol::checkForLostLogFiles);
emit checkForLostLogFiles();
#endif
// Load known link configurations
LinkManager::instance()->loadLinkConfigurationList();
......
......@@ -24,24 +24,51 @@
#include "QGCDockWidget.h"
#include <QCloseEvent>
#include <QSettings>
QGCDockWidget::QGCDockWidget(const QString& title, QAction* action, QWidget *parent, Qt::WindowFlags flags) :
QDockWidget(title, parent, flags),
_action(action)
{
QDockWidget::DockWidgetFeatures features = QDockWidget::DockWidgetMovable;
const char* QGCDockWidget::_settingsGroup = "DockWidgets";
QGCDockWidget::QGCDockWidget(const QString& title, QAction* action, QWidget* parent)
: QWidget(parent)
, _title(title)
, _action(action)
{
if (action) {
features |= QDockWidget::DockWidgetClosable;
setWindowTitle(title);
setWindowFlags(Qt::Tool);
loadSettings();
}
setFeatures(features);
}
// Instead of destroying the widget just hide it
void QGCDockWidget::closeEvent(QCloseEvent* event)
{
Q_ASSERT(_action);
if (_action) {
saveSettings();
event->ignore();
_action->trigger();
}
}
void QGCDockWidget::loadSettings(void)
{
if (_action) {
QSettings settings;
settings.beginGroup(_settingsGroup);
if (settings.contains(_title)) {
restoreGeometry(settings.value(_title).toByteArray());
}
}
}
void QGCDockWidget::saveSettings(void)
{
if (_action) {
QSettings settings;
settings.beginGroup(_settingsGroup);
settings.setValue(_title, saveGeometry());
}
}
......@@ -27,21 +27,22 @@
#include <QDockWidget>
#include <QAction>
/// @file
/// @brief Subclass of QDockWidget so we can intercept the closeEvent.
///
/// @author Don Gagne <don@thegagnes.com>
class QGCDockWidget : public QDockWidget {
class QGCDockWidget : public QWidget {
Q_OBJECT
public:
QGCDockWidget(const QString& title, QAction* action, QWidget *parent = 0, Qt::WindowFlags flags = 0);
/// Pass in title = QString() and action = NULL when just using as a regular widget
QGCDockWidget(const QString& title, QAction* action, QWidget *parent = 0);
void loadSettings(void);
void saveSettings(void);
void closeEvent(QCloseEvent* event);
private:
protected:
QString _title;
QAction* _action;
static const char* _settingsGroup;
};
......
......@@ -26,10 +26,14 @@
#include "QGCQmlWidgetHolder.h"
QGCQmlWidgetHolder::QGCQmlWidgetHolder(QWidget *parent) :
QWidget(parent)
QGCQmlWidgetHolder::QGCQmlWidgetHolder(const QString& title, QAction* action, QWidget *parent) :
QGCDockWidget(title, action, parent)
{
_ui.setupUi(this);
if (action) {
setWindowTitle(title);
}
setResizeMode(QQuickWidget::SizeRootObjectToView);
}
......
......@@ -27,10 +27,10 @@
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include <QWidget>
#include "QGCDockWidget.h"
#include "AutoPilotPlugin.h"
#include "ui_QGCQmlWidgetHolder.h"
#include "AutoPilotPlugin.h"
namespace Ui {
class QGCQmlWidgetHolder;
......@@ -38,12 +38,16 @@ class QGCQmlWidgetHolder;
/// This is used to create widgets which are implemented in QML.
class QGCQmlWidgetHolder : public QWidget
class QGCQmlWidgetHolder : public QGCDockWidget
{
Q_OBJECT
public:
explicit QGCQmlWidgetHolder(QWidget *parent = 0);
// This has a title and action since the base class is QGCDockWidget. In order to use this
// control as a normal QWidget, not a doc widget just pass in:
// title = QString()
// action = NULL
explicit QGCQmlWidgetHolder(const QString& title, QAction* action, QWidget *parent = 0);
~QGCQmlWidgetHolder();
/// Sets the UAS into the widget which in turn will load facts into the context
......
import QtQuick 2.4
import QtQuick.Controls 1.2
/// The ExclusiveGroupItem control can be used as a base class for a control which
/// needs support for ExclusiveGroup
Item {
id: _root
property bool checked: false
property ExclusiveGroup exclusiveGroup: null
onExclusiveGroupChanged: {
if (exclusiveGroup) {
exclusiveGroup.bindCheckable(_root)
}
}
}
......@@ -13,17 +13,16 @@ import QGroundControl.Palette 1.0
Rectangle {
id: _root
property var missionItem
property var missionItem ///< MissionItem associated with this editor
property bool readOnly ///< true: read only view, false: full editing view
signal clicked
signal remove
signal moveUp
signal moveDown
height: missionItem.isCurrentItem ?
(missionItem.textFieldFacts.count * (measureTextField.height + _margin)) +
(missionItem.checkboxFacts.count * (measureCheckbox.height + _margin)) +
commandPicker.height + deleteButton.height + (_margin * 9) :
commandPicker.height + (deleteButton.visible ? deleteButton.height : 0) + (_margin * 9) :
commandPicker.height + (_margin * 2)
color: missionItem.isCurrentItem ? qgcPal.buttonHighlight : qgcPal.windowShade
......@@ -63,7 +62,6 @@ Rectangle {
onClicked: _root.clicked()
}
QGCComboBox {
id: commandPicker
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 10
......@@ -71,7 +69,7 @@ Rectangle {
anchors.right: parent.right
currentIndex: missionItem.commandByIndex
model: missionItem.commandNames
visible: missionItem.sequenceNumber != 0
visible: missionItem.sequenceNumber != 0 // Item 0 is home position, can't change item type
onActivated: missionItem.commandByIndex = index
}
......@@ -79,7 +77,7 @@ Rectangle {
Rectangle {
anchors.fill: commandPicker
color: qgcPal.button
visible: missionItem.sequenceNumber == 0
visible: missionItem.sequenceNumber == 0 // Item 0 is home position, can't change item type
QGCLabel {
id: homeLabel
......@@ -119,6 +117,7 @@ Rectangle {
height: textField.height
QGCLabel {
id: textFieldLabel
anchors.baseline: textField.baseline
text: object.name
}
......@@ -129,6 +128,14 @@ Rectangle {
width: _editFieldWidth
showUnits: true
fact: object
visible: !_root.readOnly
}
FactLabel {
anchors.baseline: textFieldLabel.baseline
anchors.right: parent.right
fact: object
visible: _root.readOnly
}
}
}
......@@ -163,23 +170,10 @@ Rectangle {
id: deleteButton
width: parent.buttonWidth
text: "Delete"
visible: !readOnly
onClicked: _root.remove()
}
QGCButton {
width: parent.buttonWidth
text: "Up"
onClicked: _root.moveUp()
}
QGCButton {
width: parent.buttonWidth
text: "Down"
onClicked: _root.moveDown()
}
}
} // Column
......
......@@ -18,6 +18,7 @@ RoundButton 1.0 RoundButton.qml
VehicleRotationCal 1.0 VehicleRotationCal.qml
VehicleSummaryRow 1.0 VehicleSummaryRow.qml
ViewWidget 1.0 ViewWidget.qml
ExclusiveGroupItem 1.0 ExclusiveGroupItem.qml
ParameterEditor 1.0 ParameterEditor.qml
ParameterEditorDialog 1.0 ParameterEditorDialog.qml
......
......@@ -27,6 +27,7 @@
#include "QmlTestWidget.h"
QmlTestWidget::QmlTestWidget(void)
: QGCQmlWidgetHolder(QString(), NULL, NULL)
{
setAttribute(Qt::WA_DeleteOnClose);
resize(900, 500);
......
......@@ -55,7 +55,7 @@ void ScreenToolsController::_updateCanvas()
double ScreenToolsController::getQmlDefaultFontPixelSize(void)
{
if (_qmlDefaultFontPixelSize == -1) {
QGCQmlWidgetHolder qmlWidgetHolder;
QGCQmlWidgetHolder qmlWidgetHolder(QString(), NULL);
qmlWidgetHolder.setSource(QUrl::fromUserInput("qrc:/qml/ScreenToolsFontQuery.qml"));
}
......
......@@ -227,8 +227,8 @@ void Vehicle::_handleHomePosition(mavlink_message_t& message)
_homePosition.setAltitude(homePos.altitude / 1000.0);
_homePositionAvailable = true;
emit homePositionAvailableChanged(true);
emit homePositionChanged(_homePosition);
emit homePositionAvailableChanged(true);
}
void Vehicle::_handleHeartbeat(mavlink_message_t& message)
......@@ -963,10 +963,6 @@ bool Vehicle::homePositionAvailable(void)
QGeoCoordinate Vehicle::homePosition(void)
{
if (!_homePositionAvailable) {
qWarning() << "Call to homePosition while _homePositionAvailable == false";
}
return _homePosition;
}
......
......@@ -41,7 +41,7 @@
#include <QDebug>
SetupView::SetupView(QWidget* parent) :
QGCQmlWidgetHolder(parent)
QGCQmlWidgetHolder(QString(), NULL, parent)
{
setSource(QUrl::fromUserInput("qrc:/qml/SetupView.qml"));
}
......
......@@ -23,8 +23,12 @@ This file is part of the QGROUNDCONTROL project
#include "CustomCommandWidget.h"
CustomCommandWidget::CustomCommandWidget(QWidget *parent) :
QGCQmlWidgetHolder(parent)
CustomCommandWidget::CustomCommandWidget(const QString& title, QAction* action, QWidget *parent) :
QGCQmlWidgetHolder(title, action, parent)
{
Q_UNUSED(title);
Q_UNUSED(action);
setSource(QUrl::fromUserInput("qrc:/qml/CustomCommandWidget.qml"));
loadSettings();
}
......@@ -34,7 +34,7 @@ class CustomCommandWidget : public QGCQmlWidgetHolder
Q_OBJECT
public:
CustomCommandWidget(QWidget *parent = 0);
CustomCommandWidget(const QString& title, QAction* action, QWidget *parent = 0);
};
#endif
......@@ -367,7 +367,9 @@ void LogReplayLink::_play(void)
{
// FIXME: With move to link I don't think this is needed any more? Except for the replay widget handling multi-uas?
LinkManager::instance()->setConnectionsSuspended(tr("Connect not allowed during Flight Data replay."));
#ifndef __mobile__
MAVLinkProtocol::instance()->suspendLogForReplay(true);
#endif
// Make sure we aren't at the end of the file, if we are, reset to the beginning and play from there.
if (_logFile.atEnd()) {
......@@ -397,7 +399,9 @@ void LogReplayLink::_play(void)
void LogReplayLink::_pause(void)
{
LinkManager::instance()->setConnectionsAllowed();
#ifndef __mobile__
MAVLinkProtocol::instance()->suspendLogForReplay(false);
#endif
_readTickTimer.stop();
......
......@@ -33,8 +33,10 @@ Q_DECLARE_METATYPE(mavlink_message_t)
IMPLEMENT_QGC_SINGLETON(MAVLinkProtocol, MAVLinkProtocol)
QGC_LOGGING_CATEGORY(MAVLinkProtocolLog, "MAVLinkProtocolLog")
#ifndef __mobile__
const char* MAVLinkProtocol::_tempLogFileTemplate = "FlightDataXXXXXX"; ///< Template for temporary log file
const char* MAVLinkProtocol::_logFileExtension = "mavlink"; ///< Extension for log files
#endif
/**
* The default constructor will create a new MAVLink object sending heartbeats at
......@@ -52,10 +54,12 @@ MAVLinkProtocol::MAVLinkProtocol(QObject* parent) :
m_actionRetransmissionTimeout(100),
versionMismatchIgnore(false),
systemId(QGC::defaultSystemId),
#ifndef __mobile__
_logSuspendError(false),
_logSuspendReplay(false),
_logWasArmed(false),
_tempLogFile(QString("%2.%3").arg(_tempLogFileTemplate).arg(_logFileExtension)),
#endif
_linkMgr(LinkManager::instance()),
_heartbeatRate(MAVLINK_HEARTBEAT_DEFAULT_RATE),
_heartbeatsEnabled(true)
......@@ -91,7 +95,9 @@ MAVLinkProtocol::~MAVLinkProtocol()
{
storeSettings();
#ifndef __mobile__
_closeLogFile();
#endif
}
void MAVLinkProtocol::loadSettings()
......@@ -181,10 +187,12 @@ void MAVLinkProtocol::_linkStatusChanged(LinkInterface* link, bool connected)
// Use the same shared pointer as LinkManager
_connectedLinks.append(LinkManager::instance()->sharedPointerForLink(link));
#ifndef __mobile__
if (_connectedLinks.count() == 1) {
// This is the first link, we need to start logging
_startLogging();
}
#endif
// Send command to start MAVLink
// XXX hacky but safe
......@@ -206,10 +214,12 @@ void MAVLinkProtocol::_linkStatusChanged(LinkInterface* link, bool connected)
Q_UNUSED(found);
Q_ASSERT(found);
#ifndef __mobile__
if (_connectedLinks.count() == 0) {
// Last link is gone, close out logging
_stopLogging();
}
#endif
}
}
......@@ -303,6 +313,7 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
rstatus.txbuf, rstatus.noise, rstatus.remnoise);
}
#ifndef __mobile__
// Log data
if (!_logSuspendError && !_logSuspendReplay && _tempLogFile.isOpen()) {
......@@ -339,6 +350,7 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
}
}
}
#endif
if (message.msgid == MAVLINK_MSG_ID_HEARTBEAT) {
// Notify the vehicle manager of the heartbeat. This will create/update vehicles as needed.
......@@ -613,6 +625,7 @@ int MAVLinkProtocol::getHeartbeatRate()
return _heartbeatRate;
}
#ifndef __mobile__
/// @brief Closes the log file if it is open
bool MAVLinkProtocol::_closeLogFile(void)
{
......@@ -707,3 +720,4 @@ void MAVLinkProtocol::deleteTempLogFiles(void)
QFile::remove(fileInfo.filePath());
}
}
#endif
......@@ -203,11 +203,13 @@ public slots:
/** @brief Store protocol settings */
void storeSettings();
#ifndef __mobile__
/// @brief Deletes any log files which are in the temp directory
static void deleteTempLogFiles(void);
/// Checks for lost log files
void checkForLostLogFiles(void);
#endif
protected:
bool m_multiplexingEnabled; ///< Enable/disable packet multiplexing
......@@ -281,15 +283,12 @@ private:
~MAVLinkProtocol();
void _linkStatusChanged(LinkInterface* link, bool connected);
#ifndef __mobile__
bool _closeLogFile(void);
void _startLogging(void);
void _stopLogging(void);
/// List of all links connected to protocol. We keep SharedLinkInterface objects
/// which are QSharedPointer's in order to maintain reference counts across threads.
/// This way Link deletion works correctly.
QList<SharedLinkInterface> _connectedLinks;
bool _logSuspendError; ///< true: Logging suspended due to error
bool _logSuspendReplay; ///< true: Logging suspended due to replay
bool _logWasArmed; ///< true: vehicle was armed during logging
......@@ -297,6 +296,12 @@ private:
QGCTemporaryFile _tempLogFile; ///< File to log to
static const char* _tempLogFileTemplate; ///< Template for temporary log file
static const char* _logFileExtension; ///< Extension for log files
#endif
/// List of all links connected to protocol. We keep SharedLinkInterface objects
/// which are QSharedPointer's in order to maintain reference counts across threads.
/// This way Link deletion works correctly.
QList<SharedLinkInterface> _connectedLinks;
LinkManager* _linkMgr;
......
......@@ -157,6 +157,7 @@ void MockLink::_run1HzTasks(void)
{
if (_mavlinkStarted && _connected) {
_sendHeartBeat();
_sendHomePosition();
}
}
......@@ -692,3 +693,25 @@ void MockLink::setMissionItemFailureMode(MockLinkMissionItemHandler::FailureMode
{
_missionItemHandler.setMissionItemFailureMode(failureMode, firstTimeOnly);
}
void MockLink::_sendHomePosition(void)
{
mavlink_message_t msg;
float bogus[4];
bogus[0] = 0.0f;
bogus[1] = 0.0f;
bogus[2] = 0.0f;
bogus[3] = 0.0f;
mavlink_msg_home_position_pack(_vehicleSystemId,
_vehicleComponentId,
&msg,
(int32_t)(47.633033f * 1E7),
(int32_t)(-122.08794f * 1E7),
(int32_t)(2.0f * 1000),
0.0f, 0.0f, 0.0f,
&bogus[0],
0.0f, 0.0f, 0.0f);
respondWithMavlinkMessage(msg);
}
......@@ -143,6 +143,7 @@ private:
void _handleCommandLong(const mavlink_message_t& msg);
float _floatUnionForParam(int componentId, const QString& paramName);
void _setParamFloatUnionIntoMap(int componentId, const QString& paramName, float paramFloat);
void _sendHomePosition(void);
MockLinkMissionItemHandler _missionItemHandler;
......
......@@ -84,8 +84,6 @@ void MainWindowTest::_connectWindowClose_test(MAV_AUTOPILOT autopilot)
QTest::qWait(200);
_mainToolBar->onFlyView();
QTest::qWait(200);
_mainToolBar->onAnalyzeView();
QTest::qWait(200);
// On MainWindow close we should get a message box telling the user to disconnect first. Cancel should do nothing.
setExpectedMessageBox(QGCMessageBox::Cancel);
......
......@@ -164,7 +164,7 @@ void RadioConfigTest::init(void)
Q_ASSERT(_autopilot);
// This will instatiate the widget with an active uas with ready parameters
_calWidget = new QGCQmlWidgetHolder();
_calWidget = new QGCQmlWidgetHolder(QString(), NULL);
_calWidget->resize(600, 600);
Q_CHECK_PTR(_calWidget);
_calWidget->setAutoPilot(_autopilot);
......
......@@ -206,6 +206,7 @@ UAS::~UAS()
if (simulation) {
// wait for the simulator to exit
simulation->wait();
simulation->disconnectSimulation();
simulation->deleteLater();
}
#endif
......@@ -1950,7 +1951,7 @@ void UAS::enableHilFlightGear(bool enable, QString options, bool sensorHil, QObj
Q_UNUSED(configuration);
QGCFlightGearLink* link = dynamic_cast<QGCFlightGearLink*>(simulation);
if (!link || !simulation) {
if (!link) {
// Delete wrong sim
if (simulation) {
stopHil();
......@@ -1959,18 +1960,18 @@ void UAS::enableHilFlightGear(bool enable, QString options, bool sensorHil, QObj
simulation = new QGCFlightGearLink(this, options);
}
float noise_scaler = 0.05f;
float noise_scaler = 0.002f;
xacc_var = noise_scaler * 0.2914f;
yacc_var = noise_scaler * 0.2914f;
zacc_var = noise_scaler * 0.9577f;
rollspeed_var = noise_scaler * 0.1f * 0.8126f;
pitchspeed_var = noise_scaler * 0.1f * 0.6145f;
yawspeed_var = noise_scaler * 0.1f * 0.5852f;
rollspeed_var = noise_scaler * 0.8126f;
pitchspeed_var = noise_scaler * 0.6145f;
yawspeed_var = noise_scaler * 0.5852f;
xmag_var = noise_scaler * 0.0786f;
ymag_var = noise_scaler * 0.0566f;
zmag_var = noise_scaler * 0.0333f;
abs_pressure_var = noise_scaler * 1.1604f;
diff_pressure_var = noise_scaler * 0.6604f;
diff_pressure_var = noise_scaler * 0.3604f;
pressure_alt_var = noise_scaler * 1.1604f;
temperature_var = noise_scaler * 2.4290f;
......@@ -1998,7 +1999,7 @@ void UAS::enableHilFlightGear(bool enable, QString options, bool sensorHil, QObj
void UAS::enableHilJSBSim(bool enable, QString options)
{
QGCJSBSimLink* link = dynamic_cast<QGCJSBSimLink*>(simulation);
if (!link || !simulation) {
if (!link) {
// Delete wrong sim
if (simulation) {
stopHil();
......@@ -2027,25 +2028,25 @@ void UAS::enableHilJSBSim(bool enable, QString options)
void UAS::enableHilXPlane(bool enable)
{
QGCXPlaneLink* link = dynamic_cast<QGCXPlaneLink*>(simulation);
if (!link || !simulation) {
if (!link) {
if (simulation) {
stopHil();
delete simulation;
}
simulation = new QGCXPlaneLink(this);
float noise_scaler = 0.02f;
float noise_scaler = 0.0002f;
xacc_var = noise_scaler * 0.2914f;
yacc_var = noise_scaler * 0.2914f;
zacc_var = noise_scaler * 0.9577f;
rollspeed_var = noise_scaler * 0.15f * 0.8126f;
pitchspeed_var = noise_scaler * 0.15f * 0.6145f;
yawspeed_var = noise_scaler * 0.15f * 0.5852f;
rollspeed_var = noise_scaler * 0.8126f;
pitchspeed_var = noise_scaler * 0.6145f;
yawspeed_var = noise_scaler * 0.5852f;
xmag_var = noise_scaler * 0.0786f;
ymag_var = noise_scaler * 0.0566f;
zmag_var = noise_scaler * 0.0333f;
abs_pressure_var = noise_scaler * 1.1604f;
diff_pressure_var = noise_scaler * 0.6604f;
diff_pressure_var = noise_scaler * 0.3604f;
pressure_alt_var = noise_scaler * 1.1604f;
temperature_var = noise_scaler * 2.4290f;
}
......@@ -2348,7 +2349,7 @@ void UAS::startHil()
void UAS::stopHil()
{
if (simulation && simulation->isConnected()) {
simulation->disconnectSim();
simulation->disconnectSimulation();
_vehicle->setHilMode(false);
qDebug() << __FILE__ << __LINE__ << "HIL is onboard not enabled, trying to disable.";
}
......
......@@ -31,6 +31,7 @@ This file is part of the QGROUNDCONTROL project
#include "CameraView.h"
#include <QDebug>
#include <QtOpenGL>
#include <QOpenGLFunctions_2_0>
CameraView::CameraView(int width, int height, int depth, int channels, QWidget* parent) : QGLWidget(parent)
{
......@@ -237,14 +238,26 @@ void CameraView::setPixels(int imgid, const unsigned char* imageData, int length
void CameraView::paintGL()
{
glDrawPixels(glImage.width(), glImage.height(), GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits());
Q_ASSERT(QOpenGLContext::currentContext());
QOpenGLFunctions_2_0 *funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_0>();
if (!funcs) {
qWarning() << "OpenGL 2.0 not available on this platform. CameraView will not function";
return;
}
funcs->glDrawPixels(glImage.width(), glImage.height(), GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits());
}
void CameraView::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -1, 1);
glMatrixMode(GL_MODELVIEW);
Q_ASSERT(QOpenGLContext::currentContext());
QOpenGLFunctions_2_0 *funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_0>();
if (!funcs) {
// paintGL warning should suffice
return;
}
funcs->glViewport(0, 0, w, h);
funcs->glMatrixMode(GL_PROJECTION);
funcs->glLoadIdentity();
funcs->glOrtho(0, w, 0, h, -1, 1);
funcs->glMatrixMode(GL_MODELVIEW);
}
......@@ -24,10 +24,12 @@
#include "HILDockWidget.h"
#include "QGCHilConfiguration.h"
HILDockWidget::HILDockWidget(QWidget *parent)
: MultiVehicleDockWidget(parent)
HILDockWidget::HILDockWidget(const QString& title, QAction* action, QWidget *parent)
: MultiVehicleDockWidget(title, action, parent)
{
init();
loadSettings();
}
HILDockWidget::~HILDockWidget()
......
......@@ -31,7 +31,7 @@ class HILDockWidget : public MultiVehicleDockWidget
Q_OBJECT
public:
explicit HILDockWidget(QWidget *parent = 0);
explicit HILDockWidget(const QString& title, QAction* action, QWidget *parent = 0);
~HILDockWidget();
protected:
......
......@@ -46,8 +46,6 @@ This file is part of the QGROUNDCONTROL project
#include "QGCMAVLinkLogPlayer.h"
#include "SettingsDialog.h"
#include "MAVLinkDecoder.h"
#include "QGCDataPlot2D.h"
#include "Linecharts.h"
#include "FlightDisplayView.h"
#include "SetupView.h"
#include "QGCApplication.h"
......@@ -60,6 +58,8 @@ This file is part of the QGROUNDCONTROL project
#include "UAS.h"
#ifndef __mobile__
#include "QGCDataPlot2D.h"
#include "Linecharts.h"
#include "QGCUASFileViewMulti.h"
#include "UASQuickView.h"
#include "QGCTabbedInfoView.h"
......@@ -88,14 +88,16 @@ This file is part of the QGROUNDCONTROL project
const char* MAIN_SETTINGS_GROUP = "QGC_MAINWINDOW";
#ifndef __mobile__
const char* MainWindow::_mavlinkDockWidgetName = "MAVLINK_INSPECTOR_DOCKWIDGET";
const char* MainWindow::_customCommandWidgetName = "CUSTOM_COMMAND_DOCKWIDGET";
const char* MainWindow::_filesDockWidgetName = "FILE_VIEW_DOCKWIDGET";
const char* MainWindow::_uasStatusDetailsDockWidgetName = "UAS_STATUS_DETAILS_DOCKWIDGET";
const char* MainWindow::_mapViewDockWidgetName = "MAP_VIEW_DOCKWIDGET";
const char* MainWindow::_pfdDockWidgetName = "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET";
const char* MainWindow::_uasInfoViewDockWidgetName = "UAS_INFO_INFOVIEW_DOCKWIDGET";
const char* MainWindow::_hilDockWidgetName = "HIL_DOCKWIDGET";
const char* MainWindow::_mavlinkDockWidgetName = "MAVLink Inspector";
const char* MainWindow::_customCommandWidgetName = "Custom Command";
const char* MainWindow::_filesDockWidgetName = "Onboard Files";
const char* MainWindow::_uasStatusDetailsDockWidgetName = "Status Details";
const char* MainWindow::_pfdDockWidgetName = "Primary Flight Display";
const char* MainWindow::_uasInfoViewDockWidgetName = "Info View";
const char* MainWindow::_hilDockWidgetName = "HIL Config";
const char* MainWindow::_analyzeDockWidgetName = "Analyze";
const char* MainWindow::_visibleWidgetsKey = "VisibleWidgets";
#endif
static MainWindow* _instance = NULL; ///< @brief MainWindow singleton
......@@ -276,13 +278,11 @@ MainWindow::MainWindow(QSplashScreen* splashScreen)
_ui.actionSetup->setShortcut(QApplication::translate("MainWindow", "Meta+1", 0));
_ui.actionPlan->setShortcut(QApplication::translate("MainWindow", "Meta+2", 0));
_ui.actionFlight->setShortcut(QApplication::translate("MainWindow", "Meta+3", 0));
_ui.actionAnalyze->setShortcut(QApplication::translate("MainWindow", "Meta+4", 0));
_ui.actionFullscreen->setShortcut(QApplication::translate("MainWindow", "Meta+Return", 0));
#else
_ui.actionSetup->setShortcut(QApplication::translate("MainWindow", "Ctrl+1", 0));
_ui.actionPlan->setShortcut(QApplication::translate("MainWindow", "Ctrl+2", 0));
_ui.actionFlight->setShortcut(QApplication::translate("MainWindow", "Ctrl+3", 0));
_ui.actionAnalyze->setShortcut(QApplication::translate("MainWindow", "Ctrl+4", 0));
_ui.actionFullscreen->setShortcut(QApplication::translate("MainWindow", "Ctrl+Return", 0));
#endif
......@@ -313,6 +313,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen)
qd.close();
#endif
}
#ifndef __mobile__
_loadVisibleWidgetsSettings();
#endif
}
MainWindow::~MainWindow()
......@@ -341,34 +345,6 @@ QString MainWindow::_getWindowGeometryKey()
}
#ifndef __mobile__
void MainWindow::_createDockWidget(const QString& title, const QString& name, Qt::DockWidgetArea area, QWidget* innerWidget)
{
Q_ASSERT(!_mapName2DockWidget.contains(name));
// Add to menu
QAction* action = new QAction(title, NULL);
action->setCheckable(true);
action->setData(name);
connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction);
_ui.menuWidgets->addAction(action);
// Create widget
QGCDockWidget* dockWidget = new QGCDockWidget(title, action, this);
Q_CHECK_PTR(dockWidget);
dockWidget->setObjectName(name);
dockWidget->setVisible (false);
if (innerWidget) {
// Put inner widget inside QDockWidget
innerWidget->setParent(dockWidget);
dockWidget->setWidget(innerWidget);
innerWidget->setVisible(true);
}
_mapName2DockWidget[name] = dockWidget;
_mapDockWidget2Action[dockWidget] = action;
addDockWidget(area, dockWidget);
}
void MainWindow::_buildCommonWidgets(void)
{
// Add generic MAVLink decoder
......@@ -382,99 +358,83 @@ void MainWindow::_buildCommonWidgets(void)
logPlayer = new QGCMAVLinkLogPlayer(statusBar());
statusBar()->addPermanentWidget(logPlayer);
// In order for Qt to save and restore state of widgets all widgets must be created ahead of time. We only create the QDockWidget
// holders. We do not create the actual inner widget until it is needed. This saves memory and cpu from running widgets that are
// never shown.
struct DockWidgetInfo {
const char* name;
const char* title;
Qt::DockWidgetArea area;
static const char* rgDockWidgetNames[] = {
_mavlinkDockWidgetName,
_customCommandWidgetName,
_filesDockWidgetName,
_uasStatusDetailsDockWidgetName,
_pfdDockWidgetName,
_uasInfoViewDockWidgetName,
_hilDockWidgetName,
_analyzeDockWidgetName,
};
static const size_t cDockWidgetNames = sizeof(rgDockWidgetNames) / sizeof(rgDockWidgetNames[0]);
static const struct DockWidgetInfo rgDockWidgetInfo[] = {
{ _mavlinkDockWidgetName, "MAVLink Inspector", Qt::RightDockWidgetArea },
{ _customCommandWidgetName, "Custom Command", Qt::RightDockWidgetArea },
{ _filesDockWidgetName, "Onboard Files", Qt::RightDockWidgetArea },
{ _uasStatusDetailsDockWidgetName, "Status Details", Qt::RightDockWidgetArea },
{ _mapViewDockWidgetName, "Map view", Qt::RightDockWidgetArea },
{ _pfdDockWidgetName, "Primary Flight Display", Qt::RightDockWidgetArea },
{ _uasInfoViewDockWidgetName, "Info View", Qt::LeftDockWidgetArea },
{ _hilDockWidgetName, "HIL Config", Qt::LeftDockWidgetArea },
};
static const size_t cDockWidgetInfo = sizeof(rgDockWidgetInfo) / sizeof(rgDockWidgetInfo[0]);
for (size_t i=0; i<cDockWidgetNames; i++) {
const char* pDockWidgetName = rgDockWidgetNames[i];
// Add to menu
QAction* action = new QAction(pDockWidgetName, NULL);
action->setCheckable(true);
action->setData(pDockWidgetName);
connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction);
_ui.menuWidgets->addAction(action);
for (size_t i=0; i<cDockWidgetInfo; i++) {
const struct DockWidgetInfo* pDockInfo = &rgDockWidgetInfo[i];
_createDockWidget(pDockInfo->title, pDockInfo->name, pDockInfo->area, NULL /* no inner widget yet */);
_mapName2Action[pDockWidgetName] = action;
}
}
/// Shows or hides the specified dock widget, creating if necessary
void MainWindow::_showDockWidget(const QString& name, bool show)
{
if (!_mapName2DockWidget.contains(name)) {
// Don't show any sort of warning here. Dock Widgets which have been remove could still be in settings.
// Which would cause us to end up here.
return;
}
// Create the inner widget if we need to
if (!_mapName2DockWidget[name]->widget()) {
if (!_mapName2DockWidget.contains(name)) {
_createInnerDockWidget(name);
}
Q_ASSERT(_mapName2DockWidget.contains(name));
QDockWidget* dockWidget = _mapName2DockWidget[name];
QGCDockWidget* dockWidget = _mapName2DockWidget[name];
Q_ASSERT(dockWidget);
dockWidget->setVisible(show);
Q_ASSERT(_mapDockWidget2Action.contains(dockWidget));
_mapDockWidget2Action[dockWidget]->setChecked(show);
Q_ASSERT(_mapName2Action.contains(name));
_mapName2Action[name]->setChecked(show);
}
/// Creates the specified inner dock widget and adds to the QDockWidget
void MainWindow::_createInnerDockWidget(const QString& widgetName)
{
Q_ASSERT(_mapName2DockWidget.contains(widgetName)); // QDockWidget should already exist
Q_ASSERT(!_mapName2DockWidget[widgetName]->widget()); // Inner widget should not
QWidget* widget = NULL;
QGCDockWidget* widget = NULL;
if (widgetName == _mavlinkDockWidgetName) {
widget = new QGCMAVLinkInspector(MAVLinkProtocol::instance(),this);
widget = new QGCMAVLinkInspector(widgetName, _mapName2Action[widgetName], MAVLinkProtocol::instance(),this);
} else if (widgetName == _customCommandWidgetName) {
widget = new CustomCommandWidget(this);
widget = new CustomCommandWidget(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _filesDockWidgetName) {
widget = new QGCUASFileViewMulti(this);
widget = new QGCUASFileViewMulti(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _uasStatusDetailsDockWidgetName) {
widget = new UASInfoWidget(this);
widget = new UASInfoWidget(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _pfdDockWidgetName) {
widget = new FlightDisplayWidget(this);
#ifndef __mobile__
widget = new FlightDisplayWidget(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _hilDockWidgetName) {
widget = new HILDockWidget(this);
#endif
widget = new HILDockWidget(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _analyzeDockWidgetName) {
widget = new Linecharts(widgetName, _mapName2Action[widgetName], mavlinkDecoder, this);
} else if (widgetName == _uasInfoViewDockWidgetName) {
QGCTabbedInfoView* pInfoView = new QGCTabbedInfoView(this);
QGCTabbedInfoView* pInfoView = new QGCTabbedInfoView(widgetName, _mapName2Action[widgetName], this);
pInfoView->addSource(mavlinkDecoder);
widget = pInfoView;
} else {
qWarning() << "Attempt to create unknown Inner Dock Widget" << widgetName;
}
if (widget) {
QDockWidget* dockWidget = _mapName2DockWidget[widgetName];
Q_CHECK_PTR(dockWidget);
widget->setParent(dockWidget);
dockWidget->setWidget(widget);
}
_mapName2DockWidget[widgetName] = widget;
}
void MainWindow::_hideAllDockWidgets(void)
{
foreach(QDockWidget* dockWidget, _mapName2DockWidget) {
foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
dockWidget->setVisible(false);
}
}
......@@ -483,7 +443,7 @@ void MainWindow::_showDockWidgetAction(bool show)
{
QAction* action = dynamic_cast<QAction*>(QObject::sender());
Q_ASSERT(action);
_showDockWidget(action->data().toString(), show);
_showDockWidget(action->text(), show);
}
#endif
......@@ -511,14 +471,6 @@ void MainWindow::_buildSetupView(void)
}
}
void MainWindow::_buildAnalyzeView(void)
{
if (!_analyzeView) {
_analyzeView = new QGCDataPlot2D(this);
_analyzeView->setVisible(false);
}
}
void MainWindow::fullScreenActionItemCallback(bool)
{
_ui.actionNormal->setChecked(false);
......@@ -592,6 +544,10 @@ void MainWindow::storeSettings()
// Save the last current view in any case
settings.setValue("CURRENT_VIEW", _currentView);
settings.setValue(_getWindowStateKey(), saveState());
#ifndef __mobile__
_storeVisibleWidgetsSettings();
#endif
}
void MainWindow::configureWindowName()
......@@ -627,18 +583,10 @@ void MainWindow::connectCommonActions()
{
// Bind together the perspective actions
QActionGroup* perspectives = new QActionGroup(_ui.menuPerspectives);
perspectives->addAction(_ui.actionAnalyze);
perspectives->addAction(_ui.actionFlight);
perspectives->addAction(_ui.actionPlan);
perspectives->addAction(_ui.actionSetup);
perspectives->setExclusive(true);
// Mark the right one as selected
if (_currentView == VIEW_ANALYZE)
{
_ui.actionAnalyze->setChecked(true);
_ui.actionAnalyze->activate(QAction::Trigger);
}
if (_currentView == VIEW_FLIGHT)
{
_ui.actionFlight->setChecked(true);
......@@ -663,7 +611,6 @@ void MainWindow::connectCommonActions()
// Views actions
connect(_ui.actionFlight, SIGNAL(triggered()), this, SLOT(loadFlightView()));
connect(_ui.actionAnalyze, SIGNAL(triggered()), this, SLOT(loadAnalyzeView()));
connect(_ui.actionPlan, SIGNAL(triggered()), this, SLOT(loadPlanView()));
// Help Actions
......@@ -733,38 +680,17 @@ void MainWindow::commsWidgetDestroyed(QObject *obj)
void MainWindow::_vehicleAdded(Vehicle* vehicle)
{
connect(vehicle->uas(), SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)));
if (!linechartWidget)
{
linechartWidget = new Linecharts(this);
linechartWidget->setVisible(false);
}
linechartWidget->addSource(mavlinkDecoder);
if (_analyzeView != linechartWidget)
{
_analyzeView = linechartWidget;
}
}
/// Stores the state of the toolbar, status bar and widgets associated with the current view
void MainWindow::_storeCurrentViewState(void)
{
#ifndef __mobile__
// Save list of visible widgets
bool firstWidget = true;
QString widgetNames = "";
foreach(QDockWidget* dockWidget, _mapName2DockWidget) {
if (dockWidget->isVisible()) {
if (!firstWidget) {
widgetNames += ",";
foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
dockWidget->saveSettings();
}
widgetNames += dockWidget->objectName();
firstWidget = false;
}
}
settings.setValue(_getWindowStateKey() + "WIDGETS", widgetNames);
#endif
settings.setValue(_getWindowStateKey(), saveState());
settings.setValue(_getWindowGeometryKey(), saveGeometry());
}
......@@ -773,7 +699,6 @@ void MainWindow::_storeCurrentViewState(void)
void MainWindow::_loadCurrentViewState(void)
{
QWidget* centerView = NULL;
QString defaultWidgets;
switch (_currentView) {
case VIEW_SETUP:
......@@ -781,16 +706,9 @@ void MainWindow::_loadCurrentViewState(void)
centerView = _setupView;
break;
case VIEW_ANALYZE:
_buildAnalyzeView();
centerView = _analyzeView;
defaultWidgets = "PARAMETER_INTERFACE_DOCKWIDGET,FILE_VIEW_DOCKWIDGET";
break;
case VIEW_FLIGHT:
_buildFlightView();
centerView = _flightView;
defaultWidgets = "COMMUNICATION_CONSOLE_DOCKWIDGET,UAS_INFO_INFOVIEW_DOCKWIDGET";
break;
case VIEW_MISSIONEDITOR:
......@@ -820,22 +738,6 @@ void MainWindow::_loadCurrentViewState(void)
_centralLayout->setContentsMargins(0, 0, 0, 0);
_currentViewWidget->setVisible(true);
#ifndef __mobile__
// Hide all widgets from previous view
_hideAllDockWidgets();
// Restore the widgets for the new view
QString widgetNames = settings.value(_getWindowStateKey() + "WIDGETS", defaultWidgets).toString();
qDebug() << widgetNames;
if (!widgetNames.isEmpty()) {
QStringList split = widgetNames.split(",");
foreach (QString widgetName, split) {
Q_ASSERT(!widgetName.isEmpty());
_showDockWidget(widgetName, true);
}
}
#endif
if (settings.contains(_getWindowStateKey())) {
restoreState(settings.value(_getWindowStateKey()).toByteArray());
}
......@@ -845,17 +747,6 @@ void MainWindow::_loadCurrentViewState(void)
emit repaintCanvas();
}
void MainWindow::loadAnalyzeView()
{
if (_currentView != VIEW_ANALYZE)
{
_storeCurrentViewState();
_currentView = VIEW_ANALYZE;
_ui.actionAnalyze->setChecked(true);
_loadCurrentViewState();
}
}
void MainWindow::loadPlanView()
{
if (_currentView != VIEW_MISSIONEDITOR)
......@@ -949,3 +840,42 @@ void MainWindow::_showQmlTestWidget(void)
new QmlTestWidget();
}
#endif
#ifndef __mobile__
void MainWindow::_loadVisibleWidgetsSettings(void)
{
QSettings settings;
QString widgets = settings.value(_visibleWidgetsKey).toString();
if (!widgets.isEmpty()) {
QStringList nameList = widgets.split(",");
foreach (QString name, nameList) {
_showDockWidget(name, true);
}
}
}
void MainWindow::_storeVisibleWidgetsSettings(void)
{
QString widgetNames;
bool firstWidget = true;
foreach (QString name, _mapName2DockWidget.keys()) {
if (_mapName2DockWidget[name]->isVisible()) {
if (!firstWidget) {
widgetNames += ",";
} else {
firstWidget = false;
}
widgetNames += name;
}
}
QSettings settings;
settings.setValue(_visibleWidgetsKey, widgetNames);
}
#endif
......@@ -35,26 +35,27 @@ This file is part of the QGROUNDCONTROL project
#include <QStatusBar>
#include <QStackedWidget>
#include <QSettings>
#include <qlist.h>
#include <QList>
#include "ui_MainWindow.h"
#include "LinkManager.h"
#include "LinkInterface.h"
#include "UASInterface.h"
#include "CameraView.h"
#if (defined QGC_MOUSE_ENABLED_WIN) | (defined QGC_MOUSE_ENABLED_LINUX)
#include "Mouse6dofInput.h"
#endif // QGC_MOUSE_ENABLED_WIN
#include "MainToolBar.h"
#include "LogCompressor.h"
#include "FlightDisplayView.h"
#include "QGCMAVLinkInspector.h"
#include "QGCMAVLinkLogPlayer.h"
#include "MAVLinkDecoder.h"
#include "Vehicle.h"
#include "QGCDockWidget.h"
#if (defined QGC_MOUSE_ENABLED_WIN) | (defined QGC_MOUSE_ENABLED_LINUX)
#include "Mouse6dofInput.h"
#endif // QGC_MOUSE_ENABLED_WIN
class QGCFirmwareUpdate;
class QSplashScreen;
class QGCStatusBar;
class Linecharts;
......@@ -120,7 +121,6 @@ public slots:
void loadSetupView();
void loadFlightView();
void loadAnalyzeView();
void loadPlanView();
void manageLinks();
......@@ -185,7 +185,7 @@ protected:
typedef enum _VIEW_SECTIONS
{
VIEW_ANALYZE, // Engineering/Analyze view mode. Used for analyzing data and modifying onboard parameters
VIEW_UNUSED5, // Unused (don't remove, or it will screw up saved settigns indices)
VIEW_UNUSED3, // Unused (don't remove, or it will screw up saved settigns indices)
VIEW_FLIGHT, // Flight/Fly/Operate view mode. Used for 1st-person observation of the vehicle.
VIEW_UNUSED4, // Unused (don't remove, or it will screw up saved settigns indices)
......@@ -203,7 +203,6 @@ protected:
void loadSettings();
void storeSettings();
QSettings settings;
// Center widgets
......@@ -261,7 +260,6 @@ private:
QPointer<QWidget> _planView;
QPointer<QWidget> _flightView;
QPointer<QWidget> _setupView;
QPointer<QWidget> _analyzeView;
QPointer<QWidget> _missionEditorView;
#ifndef __mobile__
......@@ -270,19 +268,18 @@ private:
static const char* _customCommandWidgetName;
static const char* _filesDockWidgetName;
static const char* _uasStatusDetailsDockWidgetName;
static const char* _mapViewDockWidgetName;
static const char* _pfdDockWidgetName;
static const char* _uasInfoViewDockWidgetName;
static const char* _hilDockWidgetName;
static const char* _analyzeDockWidgetName;
QMap<QString, QDockWidget*> _mapName2DockWidget;
QMap<QDockWidget*, QAction*> _mapDockWidget2Action;
QMap<QString, QGCDockWidget*> _mapName2DockWidget;
QMap<QString, QAction*> _mapName2Action;
#endif
void _buildPlanView(void);
void _buildFlightView(void);
void _buildSetupView(void);
void _buildAnalyzeView(void);
void _buildTerminalView(void);
void _buildMissionEditorView(void);
......@@ -290,11 +287,14 @@ private:
void _loadCurrentViewState(void);
#ifndef __mobile__
void _createDockWidget(const QString& title, const QString& name, Qt::DockWidgetArea area, QWidget* innerWidget);
void _createInnerDockWidget(const QString& widgetName);
void _buildCommonWidgets(void);
void _hideAllDockWidgets(void);
void _showDockWidget(const QString &name, bool show);
void _loadVisibleWidgetsSettings(void);
void _storeVisibleWidgetsSettings(void);
static const char* _visibleWidgetsKey;
#endif
bool _autoReconnect;
......
......@@ -80,7 +80,6 @@
<addaction name="actionSetup"/>
<addaction name="actionPlan"/>
<addaction name="actionFlight"/>
<addaction name="actionAnalyze"/>
<addaction name="separator"/>
<addaction name="actionFullscreen"/>
<addaction name="actionNormal"/>
......@@ -134,14 +133,6 @@
<string>Plan</string>
</property>
</action>
<action name="actionAnalyze">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Analyze</string>
</property>
</action>
<action name="actionFlight">
<property name="checkable">
<bool>true</bool>
......@@ -237,9 +228,7 @@
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="../../qgroundcontrol.qrc"/>
</resources>
<resources/>
<connections>
<connection>
<sender>actionExit</sender>
......
......@@ -25,12 +25,14 @@
#include "ui_MultiVehicleDockWidget.h"
#include "MultiVehicleManager.h"
MultiVehicleDockWidget::MultiVehicleDockWidget(QWidget *parent)
: QWidget(parent)
MultiVehicleDockWidget::MultiVehicleDockWidget(const QString& title, QAction* action, QWidget *parent)
: QGCDockWidget(title, action, parent)
, _ui(new Ui::MultiVehicleDockWidget)
{
_ui->setupUi(this);
setWindowTitle(title);
connect(MultiVehicleManager::instance(), &MultiVehicleManager::activeVehicleChanged, this, &MultiVehicleDockWidget::_activeVehicleChanged);
connect(MultiVehicleManager::instance(), &MultiVehicleManager::vehicleAdded, this, &MultiVehicleDockWidget::_vehicleAdded);
connect(MultiVehicleManager::instance(), &MultiVehicleManager::vehicleRemoved, this, &MultiVehicleDockWidget::_vehicleRemoved);
......@@ -38,8 +40,11 @@ MultiVehicleDockWidget::MultiVehicleDockWidget(QWidget *parent)
void MultiVehicleDockWidget::init(void)
{
foreach (Vehicle* vehicle, MultiVehicleManager::instance()->vehicles()) {
_vehicleAdded(vehicle);
}
if (MultiVehicleManager::instance()->activeVehicle()) {
_vehicleAdded(MultiVehicleManager::instance()->activeVehicle());
_activeVehicleChanged(MultiVehicleManager::instance()->activeVehicle());
}
}
......
......@@ -24,9 +24,9 @@
#ifndef MultiVehicleDockWidget_H
#define MultiVehicleDockWidget_H
#include <QWidget>
#include <QMap>
#include "QGCDockWidget.h"
#include "Vehicle.h"
namespace Ui
......@@ -37,12 +37,12 @@ namespace Ui
/// Provides a base class for a dock widget which automatically handles
/// Vehicles coming and going. It does this by using a stacked widget which
/// holds individual Vehicle specific widgets.
class MultiVehicleDockWidget : public QWidget
class MultiVehicleDockWidget : public QGCDockWidget
{
Q_OBJECT
public:
explicit MultiVehicleDockWidget(QWidget *parent = 0);
explicit MultiVehicleDockWidget(const QString& title, QAction* action, QWidget *parent = 0);
~MultiVehicleDockWidget();
/// Must be called in the derived class contructor to initialize the base class
......
......@@ -17,7 +17,7 @@
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
<string>HIL Config</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="1,100,1" columnstretch="40,0">
<item row="0" column="0">
......
......@@ -12,8 +12,8 @@
const float QGCMAVLinkInspector::updateHzLowpass = 0.2f;
const unsigned int QGCMAVLinkInspector::updateInterval = 1000U;
QGCMAVLinkInspector::QGCMAVLinkInspector(MAVLinkProtocol* protocol, QWidget *parent) :
QWidget(parent),
QGCMAVLinkInspector::QGCMAVLinkInspector(const QString& title, QAction* action, MAVLinkProtocol* protocol, QWidget *parent) :
QGCDockWidget(title, action, parent),
_protocol(protocol),
selectedSystemID(0),
selectedComponentID(0),
......@@ -58,6 +58,8 @@ QGCMAVLinkInspector::QGCMAVLinkInspector(MAVLinkProtocol* protocol, QWidget *par
// Attach the UI's refresh rate to a timer.
connect(&updateTimer, SIGNAL(timeout()), this, SLOT(refreshView()));
updateTimer.start(updateInterval);
loadSettings();
}
void QGCMAVLinkInspector::_vehicleAdded(Vehicle* vehicle)
......
#ifndef QGCMAVLINKINSPECTOR_H
#define QGCMAVLINKINSPECTOR_H
#include <QWidget>
#include <QMap>
#include <QTimer>
#include "QGCDockWidget.h"
#include "MAVLinkProtocol.h"
#include "Vehicle.h"
......@@ -15,12 +15,12 @@ namespace Ui {
class QTreeWidgetItem;
class UASInterface;
class QGCMAVLinkInspector : public QWidget
class QGCMAVLinkInspector : public QGCDockWidget
{
Q_OBJECT
public:
explicit QGCMAVLinkInspector(MAVLinkProtocol* protocol, QWidget *parent = 0);
explicit QGCMAVLinkInspector(const QString& title, QAction* action, MAVLinkProtocol* protocol, QWidget *parent = 0);
~QGCMAVLinkInspector();
public slots:
......
......@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>MAVLink Inspector</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="2,8,2,8,3">
<property name="leftMargin">
......
#include "QGCTabbedInfoView.h"
QGCTabbedInfoView::QGCTabbedInfoView(QWidget *parent) : QWidget(parent)
QGCTabbedInfoView::QGCTabbedInfoView(const QString& title, QAction* action, QWidget *parent)
: QGCDockWidget(title, action, parent)
{
ui.setupUi(this);
messageView = new UASMessageViewWidget(this);
......@@ -11,6 +12,8 @@ QGCTabbedInfoView::QGCTabbedInfoView(QWidget *parent) : QWidget(parent)
//ui.tabWidget->addTab(actionsWidget,"Actions");
//ui.tabWidget->addTab(rawView,"Status");
ui.tabWidget->addTab(messageView,"Messages");
loadSettings();
}
void QGCTabbedInfoView::addSource(MAVLinkDecoder *decoder)
{
......
#ifndef QGCTABBEDINFOVIEW_H
#define QGCTABBEDINFOVIEW_H
#include <QWidget>
#include "ui_QGCTabbedInfoView.h"
#include "QGCDockWidget.h"
#include "MAVLinkDecoder.h"
#include "UASMessageView.h"
#include "UASQuickView.h"
#include "UASRawStatusView.h"
class QGCTabbedInfoView : public QWidget
#include "ui_QGCTabbedInfoView.h"
class QGCTabbedInfoView : public QGCDockWidget
{
Q_OBJECT
public:
explicit QGCTabbedInfoView(QWidget *parent = 0);
explicit QGCTabbedInfoView(const QString& title, QAction* action, QWidget *parent = 0);
~QGCTabbedInfoView();
void addSource(MAVLinkDecoder *decoder);
private:
......
......@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>Info View</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
......
......@@ -4,8 +4,8 @@
#include "MultiVehicleManager.h"
#include "QGCUASFileView.h"
QGCUASFileViewMulti::QGCUASFileViewMulti(QWidget *parent) :
QWidget(parent),
QGCUASFileViewMulti::QGCUASFileViewMulti(const QString& title, QAction* action, QWidget *parent) :
QGCDockWidget(title, action, parent),
ui(new Ui::QGCUASFileViewMulti)
{
ui->setupUi(this);
......@@ -18,6 +18,8 @@ QGCUASFileViewMulti::QGCUASFileViewMulti(QWidget *parent) :
_vehicleAdded(MultiVehicleManager::instance()->activeVehicle());
_activeVehicleChanged(MultiVehicleManager::instance()->activeVehicle());
}
loadSettings();
}
void QGCUASFileViewMulti::_vehicleRemoved(Vehicle* vehicle)
......
#ifndef QGCUASFILEVIEWMULTI_H
#define QGCUASFILEVIEWMULTI_H
#include <QWidget>
#include <QMap>
#include "QGCDockWidget.h"
#include "QGCUASFileView.h"
#include "UAS.h"
......@@ -12,12 +12,12 @@ namespace Ui
class QGCUASFileViewMulti;
}
class QGCUASFileViewMulti : public QWidget
class QGCUASFileViewMulti : public QGCDockWidget
{
Q_OBJECT
public:
explicit QGCUASFileViewMulti(QWidget *parent = 0);
explicit QGCUASFileViewMulti(const QString& title, QAction* action, QWidget *parent = 0);
~QGCUASFileViewMulti();
protected:
......
......@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>Onboard Files</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
......
......@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>Status Details</string>
</property>
<property name="styleSheet">
<string notr="true"/>
......
......@@ -5,99 +5,27 @@
#include "MainWindow.h"
#include "UAS.h"
Linecharts::Linecharts(QWidget *parent) :
QStackedWidget(parent),
plots(),
active(true)
Linecharts::Linecharts(const QString& title, QAction* action, MAVLinkDecoder* decoder, QWidget *parent)
: MultiVehicleDockWidget(title, action, parent)
, _mavlinkDecoder(decoder)
{
this->setVisible(false);
// Add each MAV
foreach (Vehicle* vehicle, MultiVehicleManager::instance()->vehicles()) {
addVehicle(vehicle);
}
connect(MultiVehicleManager::instance(), &MultiVehicleManager::vehicleAdded, this, &Linecharts::addVehicle);
}
init();
void Linecharts::showEvent(QShowEvent* event)
{
// React only to internal (pre-display)
// events
Q_UNUSED(event)
QWidget* prevWidget = currentWidget();
if (prevWidget)
{
LinechartWidget* chart = dynamic_cast<LinechartWidget*>(prevWidget);
if (chart) {
this->active = true;
chart->setActive(true);
}
}
QWidget::showEvent(event);
emit visibilityChanged(true);
}
void Linecharts::hideEvent(QHideEvent* event)
{
// React only to internal (pre-display)
// events
Q_UNUSED(event)
QWidget* prevWidget = currentWidget();
if (prevWidget) {
LinechartWidget* chart = dynamic_cast<LinechartWidget*>(prevWidget);
if (chart) {
this->active = false;
chart->setActive(false);
}
}
QWidget::hideEvent(event);
emit visibilityChanged(false);
this->setVisible(false);
}
void Linecharts::addVehicle(Vehicle* vehicle)
QWidget* Linecharts::_newVehicleWidget(Vehicle* vehicle, QWidget* parent)
{
UAS* uas = vehicle->uas();
// FIXME Add removeSystem() call
// Compatibility hack
int uasid = 0; /*uas->getUASID()*/
if (!plots.contains(uasid))
{
LinechartWidget* widget = new LinechartWidget(uasid, this);
addWidget(widget);
plots.insert(uasid, widget);
LinechartWidget* widget = new LinechartWidget(vehicle->id(), parent);
// Connect valueChanged signals
connect(uas, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), widget, SLOT(appendData(int,QString,QString,QVariant,quint64)));
connect(vehicle->uas(), &UAS::valueChanged, widget, &LinechartWidget::appendData);
// Connect decoder
connect(_mavlinkDecoder, &MAVLinkDecoder::valueChanged, widget, &LinechartWidget::appendData);
connect(widget, SIGNAL(logfileWritten(QString)), this, SIGNAL(logfileWritten(QString)));
// Set system active if this is the only system
// if (active)
// {
// if (plots.size() == 1)
// {
// FIXME XXX HACK
// Connect generic sources
for (int i = 0; i < genericSources.count(); ++i)
{
connect(genericSources[i], SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), plots.values().first(), SLOT(appendData(int,QString,QString,QVariant,quint64)));
}
// Select system
widget->setActive(true);
//widget->selectActiveSystem(0);
}
// }
// }
}
void Linecharts::addSource(QObject* obj)
{
genericSources.append(obj);
// FIXME XXX HACK
if (plots.size() > 0)
{
// Connect generic source
connect(obj, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), plots.values().first(), SLOT(appendData(int,QString,QString,QVariant,quint64)));
}
return widget;
}
......@@ -7,34 +7,26 @@
#include "LinechartWidget.h"
#include "Vehicle.h"
#include "MultiVehicleDockWidget.h"
#include "MAVLinkDecoder.h"
class Linecharts : public QStackedWidget
class Linecharts : public MultiVehicleDockWidget
{
Q_OBJECT
public:
explicit Linecharts(QWidget *parent = 0);
explicit Linecharts(const QString& title, QAction* action, MAVLinkDecoder* decoder, QWidget *parent = 0);
signals:
/** @brief This signal is emitted once a logfile has been finished writing */
void logfileWritten(QString fileName);
void visibilityChanged(bool visible);
public slots:
/** @brief Add a new system to the list of plots */
void addVehicle(Vehicle* vehicle);
/** @brief Add a new generic message source (not a system) */
void addSource(QObject* obj);
protected:
// Override from MultiVehicleDockWidget
virtual QWidget* _newVehicleWidget(Vehicle* vehicle, QWidget* parent);
QMap<int, LinechartWidget*> plots;
QVector<QObject*> genericSources;
bool active;
/** @brief Start updating widget */
void showEvent(QShowEvent* event);
/** @brief Stop updating widget */
void hideEvent(QHideEvent* event);
private:
MAVLinkDecoder* _mavlinkDecoder;
};
#endif // LINECHARTS_H
......@@ -41,7 +41,7 @@ This file is part of the QGROUNDCONTROL project
#include "UAS.h"
MainToolBar::MainToolBar(QWidget* parent)
: QGCQmlWidgetHolder(parent)
: QGCQmlWidgetHolder(QString(), NULL, parent)
, _vehicle(NULL)
, _mav(NULL)
, _toolBar(NULL)
......@@ -161,12 +161,6 @@ void MainToolBar::onFlyViewMenu()
}
}
void MainToolBar::onAnalyzeView()
{
setCurrentView(MainWindow::VIEW_ANALYZE);
MainWindow::instance()->loadAnalyzeView();
}
void MainToolBar::onDisconnect(QString conf)
{
if(conf.isEmpty()) {
......@@ -248,9 +242,6 @@ void MainToolBar::setCurrentView(int currentView)
{
ViewType_t view = ViewNone;
switch((MainWindow::VIEW_SECTIONS)currentView) {
case MainWindow::VIEW_ANALYZE:
view = ViewAnalyze;
break;
case MainWindow::VIEW_MISSIONEDITOR:
view = ViewPlan;
break;
......
......@@ -64,7 +64,6 @@ public:
Q_INVOKABLE void onPlanView();
Q_INVOKABLE void onFlyView();
Q_INVOKABLE void onFlyViewMenu();
Q_INVOKABLE void onAnalyzeView();
Q_INVOKABLE void onConnect(QString conf);
Q_INVOKABLE void onDisconnect(QString conf);
Q_INVOKABLE void onEnterMessageArea(int x, int y);
......
......@@ -626,7 +626,6 @@ Rectangle {
setupButton.repaintChevron = true;
planButton.repaintChevron = true;
flyButton.repaintChevron = true;
analyzeButton.repaintChevron = true;
}
}
......@@ -670,19 +669,6 @@ Rectangle {
}
z: 800
}
QGCToolBarButton {
id: analyzeButton
width: getProportionalDimmension(90)
height: cellHeight
exclusiveGroup: mainActionGroup
text: qsTr("Analyze")
checked: (mainToolBar.currentView === MainToolBar.ViewAnalyze)
onClicked: {
mainToolBar.onAnalyzeView();
}
z: 700
}
} // Row
//---------------------------------------------------------------------
......
......@@ -43,7 +43,8 @@ This file is part of the PIXHAWK project
#include "QGC.h"
#include "UAS.h"
UASInfoWidget::UASInfoWidget(QWidget *parent, QString name) : QWidget(parent)
UASInfoWidget::UASInfoWidget(const QString& title, QAction* action, QWidget *parent, QString name)
: QGCDockWidget(title, action, parent)
{
ui.setupUi(this);
this->name = name;
......@@ -72,6 +73,8 @@ UASInfoWidget::UASInfoWidget(QWidget *parent, QString name) : QWidget(parent)
updateTimer->start(updateInterval);
this->setVisible(false);
loadSettings();
}
UASInfoWidget::~UASInfoWidget()
......
......@@ -32,10 +32,10 @@ This file is part of the QGROUNDCONTROL project
#ifndef _UASINFOWIDGET_H_
#define _UASINFOWIDGET_H_
#include <QWidget>
#include <QTimer>
#include <QMap>
#include "QGCDockWidget.h"
#include "UASInterface.h"
#include "ui_UASInfo.h"
#include "Vehicle.h"
......@@ -44,11 +44,11 @@ This file is part of the QGROUNDCONTROL project
* @brief Info indicator for the currently active UAS
*
**/
class UASInfoWidget : public QWidget
class UASInfoWidget : public QGCDockWidget
{
Q_OBJECT
public:
UASInfoWidget(QWidget *parent = 0, QString name = "");
UASInfoWidget(const QString& title, QAction* action, QWidget *parent = 0, QString name = "");
~UASInfoWidget();
public slots:
......
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