diff --git a/files/pixhawk/hexarotor/widgets/mavconn.qgw b/files/pixhawk/hexarotor/widgets/mavconn.qgw deleted file mode 100644 index ff33f3786baccbb9cf2237611ab28dc946c90b8a..0000000000000000000000000000000000000000 --- a/files/pixhawk/hexarotor/widgets/mavconn.qgw +++ /dev/null @@ -1,62 +0,0 @@ -[MAVCONN%20Control] -QGC_TOOL_WIDGET_ITEMS\1\TYPE=COMMANDBUTTON -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_DESCRIPTION=DO: Control Video -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_BUTTONTEXT=CAPTURE -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_COMMANDID=200 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAMS_VISIBLE=false -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM1=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM2=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM3=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM4=2 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM5=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM6=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM7=0 -QGC_TOOL_WIDGET_ITEMS\2\TYPE=COMMANDBUTTON -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_DESCRIPTION=DO: Control Video -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_BUTTONTEXT=STOP -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_COMMANDID=200 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAMS_VISIBLE=false -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM1=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM2=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM3=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM4=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM5=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM6=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM7=0 -QGC_TOOL_WIDGET_ITEMS\3\TYPE=COMMANDBUTTON -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_DESCRIPTION=PREFLIGHT: Calibration -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_BUTTONTEXT=CALIBRATE -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_COMMANDID=241 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAMS_VISIBLE=false -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM1=1 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM2=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM3=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM4=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM5=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM6=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM7=0 -QGC_TOOL_WIDGET_ITEMS\4\TYPE=SLIDER -QGC_TOOL_WIDGET_ITEMS\4\QGC_PARAM_SLIDER_DESCRIPTION=Setpoint ON<->OFF -QGC_TOOL_WIDGET_ITEMS\4\QGC_PARAM_SLIDER_PARAMID= -QGC_TOOL_WIDGET_ITEMS\4\QGC_PARAM_SLIDER_COMPONENTID=0 -QGC_TOOL_WIDGET_ITEMS\4\QGC_PARAM_SLIDER_MIN=1 -QGC_TOOL_WIDGET_ITEMS\4\QGC_PARAM_SLIDER_MAX=0 -QGC_TOOL_WIDGET_ITEMS\5\TYPE=SLIDER -QGC_TOOL_WIDGET_ITEMS\5\QGC_PARAM_SLIDER_DESCRIPTION=Glob. Loc ON<->OFF -QGC_TOOL_WIDGET_ITEMS\5\QGC_PARAM_SLIDER_PARAMID= -QGC_TOOL_WIDGET_ITEMS\5\QGC_PARAM_SLIDER_COMPONENTID=0 -QGC_TOOL_WIDGET_ITEMS\5\QGC_PARAM_SLIDER_MIN=1 -QGC_TOOL_WIDGET_ITEMS\5\QGC_PARAM_SLIDER_MAX=0 -QGC_TOOL_WIDGET_ITEMS\6\TYPE=SLIDER -QGC_TOOL_WIDGET_ITEMS\6\QGC_PARAM_SLIDER_DESCRIPTION=GPS ENU HL<->ASL -QGC_TOOL_WIDGET_ITEMS\6\QGC_PARAM_SLIDER_PARAMID= -QGC_TOOL_WIDGET_ITEMS\6\QGC_PARAM_SLIDER_COMPONENTID=0 -QGC_TOOL_WIDGET_ITEMS\6\QGC_PARAM_SLIDER_MIN=0 -QGC_TOOL_WIDGET_ITEMS\6\QGC_PARAM_SLIDER_MAX=1 -QGC_TOOL_WIDGET_ITEMS\7\TYPE=SLIDER -QGC_TOOL_WIDGET_ITEMS\7\QGC_PARAM_SLIDER_DESCRIPTION=Yaw PX<->ASL -QGC_TOOL_WIDGET_ITEMS\7\QGC_PARAM_SLIDER_PARAMID= -QGC_TOOL_WIDGET_ITEMS\7\QGC_PARAM_SLIDER_COMPONENTID=0 -QGC_TOOL_WIDGET_ITEMS\7\QGC_PARAM_SLIDER_MIN=0 -QGC_TOOL_WIDGET_ITEMS\7\QGC_PARAM_SLIDER_MAX=1 -QGC_TOOL_WIDGET_ITEMS\size=7 diff --git a/files/pixhawk/quadrotor/parameter_tooltips/tooltips.txt b/files/pixhawk/quadrotor/parameter_tooltips/tooltips.txt deleted file mode 100644 index 610873647651e034a665f5d2d85dd53cf41a8a47..0000000000000000000000000000000000000000 --- a/files/pixhawk/quadrotor/parameter_tooltips/tooltips.txt +++ /dev/null @@ -1,3 +0,0 @@ -EEPROM,variable name,Min,Max,Default,Multiplier,Enabled (0 = no, 1 = yes),Comment -HDNG2RLL_P, 0, 5, 0.7, 1, 1, NAV_ROLL_P - Navigation control gains. Tuning values for the navigation control PID loops. The P term is the primary tuning value. This determines how the control deflection varies in proportion to the required correction. -SYS_TYPE, 0, 15, 1, 1, 1, System type (airframe) \ No newline at end of file diff --git a/files/pixhawk/quadrotor/widgets/mavconn.qgw b/files/pixhawk/quadrotor/widgets/mavconn.qgw deleted file mode 100644 index e7b6e644f1ec9a866d50d7bec4aedd9fcf7e4d94..0000000000000000000000000000000000000000 --- a/files/pixhawk/quadrotor/widgets/mavconn.qgw +++ /dev/null @@ -1,38 +0,0 @@ -[MAVCONN%20Control] -QGC_TOOL_WIDGET_ITEMS\1\TYPE=COMMANDBUTTON -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_DESCRIPTION=START Recording -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_BUTTONTEXT=CAPTURE -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_COMMANDID=200 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAMS_VISIBLE=false -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM1=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM2=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM3=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM4=2 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM5=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM6=0 -QGC_TOOL_WIDGET_ITEMS\1\QGC_COMMAND_BUTTON_PARAM7=0 -QGC_TOOL_WIDGET_ITEMS\2\TYPE=COMMANDBUTTON -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_DESCRIPTION=STOP Recording -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_BUTTONTEXT=STOP -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_COMMANDID=200 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAMS_VISIBLE=false -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM1=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM2=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM3=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM4=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM5=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM6=0 -QGC_TOOL_WIDGET_ITEMS\2\QGC_COMMAND_BUTTON_PARAM7=0 -QGC_TOOL_WIDGET_ITEMS\3\TYPE=COMMANDBUTTON -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_DESCRIPTION=PREFLIGHT: Calibration -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_BUTTONTEXT=CALIBRATE -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_COMMANDID=241 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAMS_VISIBLE=false -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM1=1 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM2=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM3=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM4=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM5=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM6=0 -QGC_TOOL_WIDGET_ITEMS\3\QGC_COMMAND_BUTTON_PARAM7=0 -QGC_TOOL_WIDGET_ITEMS\size=3 diff --git a/files/px4/parameter_tooltips/tooltips.txt b/files/px4/parameter_tooltips/tooltips.txt deleted file mode 100644 index 854f5a0162b25c750085b561f4a88b33ab53282c..0000000000000000000000000000000000000000 --- a/files/px4/parameter_tooltips/tooltips.txt +++ /dev/null @@ -1,11 +0,0 @@ -^ Name ^ Min ^ Max ^ Default ^ Multiplier ^ Enabled ^ Comment ^ -| BAT_V_EMPTY | 0.9 | 100.0 | 3.2 | 1 | 1 | Voltage of an empty battery cell | -| BAT_V_FULL | 1.0 | 200.0 | 4.05 | 1 | 1 | Voltage of a full battery cell | -| BAT_N_CELLS | 1 | 100 | 3 | 1 | 1 | Number of SERIAL battery cells. Typically this ranges from 2S to 6S in small-scale UAVs | -| BAT_V_SCALING | 0.001 | 1.0 | 0.00838 | 1 | 1 | Conversion from ADC ticks to battery voltage. Depends on the connected board, calibrate with a multimeter. | -| MC_ATTRATE_P | 0.0 | 20.0 | 0.20 | 1 | 1 | Multirotor attitude rate control P gain. This gain controls how much of the motor thrust should be used to control angular velocity. A larger number will increase the control response, but will make the system also more twitchy. | -| MC_ATTRATE_D | 0.0 | 20.0 | 0.05 | 1 | 1 | Multirotor attitude rate control D gain. A large value will allow to damp oscillations due to a high P gain, but will make the system response suspectible to noise.| -| MC_ATT_P | 0.0 | 20.0 | 0.20 | 1 | 1 | Multirotor attitude control proportional (P) gain. This defines how strong the response of the system will be to an attitude error| -| MC_ATT_D | 0.0 | 20.0 | 0.05 | 1 | 1 | Multirotor attitude control D gain. A large value will allow to damp oscillations due to a high P gain, but will make the system response suspectible to noise.| -| FW_ROLLRATE_P | 0.0 | 20.0 | 0.30 | 1 | 1 | Fixed wing roll rate control P gain. This gain controls how strong the ailerons or rudder should be actuated in order to achieve a certain roll rate. A larger number will increase the control response, but will make the system also more twitchy. | -| FW_HEADING_P | 0.0 | 20.0 | 4.00 | 1 | 1 | Fixed wing heading error to bank angle gain | \ No newline at end of file diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index cb4e270280bb11e9cda3724cba96d7f6ae467f5c..9c43027499415e1b1c228d169517be64508d36da 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -452,7 +452,6 @@ HEADERS += \ src/ui/QGCHilFlightGearConfiguration.h \ src/ui/QGCHilJSBSimConfiguration.h \ src/ui/QGCHilXPlaneConfiguration.h \ - src/ui/submainwindow.h \ src/ui/uas/UASQuickView.h \ src/ui/uas/UASQuickViewItem.h \ src/ui/linechart/ChartPlot.h \ @@ -481,7 +480,6 @@ HEADERS += \ src/ui/px4_configuration/PX4Bootloader.h \ src/ui/px4_configuration/PX4FirmwareUpgradeThread.h \ src/ui/px4_configuration/PX4FirmwareUpgrade.h \ - src/ui/menuactionhelper.h \ src/uas/UASManagerInterface.h \ src/uas/QGCUASParamManagerInterface.h \ src/uas/QGCUASFileManager.h \ @@ -497,7 +495,8 @@ HEADERS += \ src/QGCPalette.h \ src/QGCQmlWidgetHolder.h \ src/ui/QGCParamTreeWidget.h \ - src/ui/QGCMapRCToParamDialog.h + src/ui/QGCMapRCToParamDialog.h \ + src/QGCDockWidget.h \ SOURCES += \ src/main.cc \ @@ -598,7 +597,6 @@ SOURCES += \ src/ui/QGCHilFlightGearConfiguration.cc \ src/ui/QGCHilJSBSimConfiguration.cc \ src/ui/QGCHilXPlaneConfiguration.cc \ - src/ui/submainwindow.cpp \ src/ui/uas/UASQuickViewItem.cc \ src/ui/uas/UASQuickView.cc \ src/ui/linechart/ChartPlot.cc \ @@ -627,7 +625,6 @@ SOURCES += \ src/ui/px4_configuration/PX4Bootloader.cc \ src/ui/px4_configuration/PX4FirmwareUpgradeThread.cc \ src/ui/px4_configuration/PX4FirmwareUpgrade.cc \ - src/ui/menuactionhelper.cpp \ src/uas/QGCUASFileManager.cc \ src/ui/QGCUASFileView.cc \ src/CmdLineOptParser.cc \ @@ -640,7 +637,8 @@ SOURCES += \ src/QGCPalette.cc \ src/QGCQmlWidgetHolder.cpp \ src/ui/QGCParamTreeWidget.cpp \ - src/ui/QGCMapRCToParamDialog.cpp + src/ui/QGCMapRCToParamDialog.cpp \ + src/QGCDockWidget.cc \ # # Unit Test specific configuration goes here diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 7c1a60248bf2fc00aa8335796ba3ea3f519e4d9f..cdc054dedc0c79db035197f902dd1dfe48abff80 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -476,15 +476,12 @@ void QGCApplication::criticalMessageBoxOnMainThread(const QString& title, const void QGCApplication::saveTempFlightDataLogOnMainThread(QString tempLogfile) { - QString defaultSuffix("mavlink"); QString saveFilename = QGCFileDialog::getSaveFileName( MainWindow::instance(), - tr("Select file to save Flight Data Log"), + tr("Save Flight Data Log"), qgcApp()->mavlinkLogFilesLocation(), tr("Flight Data Log (*.mavlink)"), - 0,0, - &defaultSuffix, - true); + "mavlink"); if (!saveFilename.isEmpty()) { QFile::copy(tempLogfile, saveFilename); } diff --git a/src/QGCConfig.h b/src/QGCConfig.h index fad5b727d4924eb0b33d4df0e25440635778f71a..a119bc823a921ce09dccd48f344422223752e6d4 100644 --- a/src/QGCConfig.h +++ b/src/QGCConfig.h @@ -12,7 +12,7 @@ // If you need to make an incompatible changes to stored settings, bump this version number // up by 1. This will caused store settings to be cleared on next boot. -#define QGC_SETTINGS_VERSION 2 +#define QGC_SETTINGS_VERSION 3 #define QGC_APPLICATION_NAME "QGroundControl" #define QGC_ORG_NAME "QGroundControl.org" diff --git a/src/QGCDockWidget.cc b/src/QGCDockWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..b087abbbaa70742ac87249e48dca6d326d56dd35 --- /dev/null +++ b/src/QGCDockWidget.cc @@ -0,0 +1,39 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + + ======================================================================*/ + +#include "QGCDockWidget.h" + +#include + +QGCDockWidget::QGCDockWidget(const QString& title, QWidget *parent, Qt::WindowFlags flags) : + QDockWidget(title, parent, flags) +{ + +} + +// Instead of destroying the widget just hide it +void QGCDockWidget::closeEvent(QCloseEvent* event) +{ + event->ignore(); + setVisible(false); +} diff --git a/src/QGCDockWidget.h b/src/QGCDockWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..ffc2fb1352b59f28a88bda264475849a50d11241 --- /dev/null +++ b/src/QGCDockWidget.h @@ -0,0 +1,44 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + + ======================================================================*/ + +#ifndef QGCDockWidget_h +#define QGCDockWidget_h + +#include + +/// @file +/// @brief Subclass of QDockWidget so we can intercept the closeEvent. +/// +/// @author Don Gagne + +class QGCDockWidget : public QDockWidget { + Q_OBJECT + +public: + QGCDockWidget(const QString& title, QWidget *parent = 0, Qt::WindowFlags flags = 0); + + void closeEvent(QCloseEvent* event); +}; + + +#endif diff --git a/src/QGCFileDialog.cc b/src/QGCFileDialog.cc index 285cf5ea97fadf31f76887e92723cd63ef0d68b4..3f48704611a3aaaa87d23916dd9783f2b520e435 100644 --- a/src/QGCFileDialog.cc +++ b/src/QGCFileDialog.cc @@ -35,7 +35,7 @@ QString QGCFileDialog::getExistingDirectory( const QString& dir, Options options) { - _validate(NULL, options); + _validate(options); #ifdef QT_DEBUG if (qgcApp()->runningUnitTests()) { @@ -52,18 +52,17 @@ QString QGCFileDialog::getOpenFileName( const QString& caption, const QString& dir, const QString& filter, - QString* selectedFilter, Options options) { - _validate(selectedFilter, options); + _validate(options); #ifdef QT_DEBUG if (qgcApp()->runningUnitTests()) { - return UnitTest::_getOpenFileName(parent, caption, dir, filter, selectedFilter, options); + return UnitTest::_getOpenFileName(parent, caption, dir, filter, options); } else #endif { - return QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options); + return QFileDialog::getOpenFileName(parent, caption, dir, filter, NULL, options); } } @@ -72,49 +71,49 @@ QStringList QGCFileDialog::getOpenFileNames( const QString& caption, const QString& dir, const QString& filter, - QString* selectedFilter, Options options) { - _validate(selectedFilter, options); + _validate(options); #ifdef QT_DEBUG if (qgcApp()->runningUnitTests()) { - return UnitTest::_getOpenFileNames(parent, caption, dir, filter, selectedFilter, options); + return UnitTest::_getOpenFileNames(parent, caption, dir, filter, options); } else #endif { - return QFileDialog::getOpenFileNames(parent, caption, dir, filter, selectedFilter, options); + return QFileDialog::getOpenFileNames(parent, caption, dir, filter, NULL, options); } } -QString QGCFileDialog::getSaveFileName(QWidget* parent, +QString QGCFileDialog::getSaveFileName( + QWidget* parent, const QString& caption, const QString& dir, const QString& filter, - QString* selectedFilter, - Options options, - QString* defaultSuffix, - bool strict) + const QString& defaultSuffix, + bool strict, + Options options) { - _validate(selectedFilter, options); + _validate(options); #ifdef QT_DEBUG if (qgcApp()->runningUnitTests()) { - return UnitTest::_getSaveFileName(parent, caption, dir, filter, selectedFilter, options, defaultSuffix); + return UnitTest::_getSaveFileName(parent, caption, dir, filter, defaultSuffix, options); } else #endif { + QString defaultSuffixCopy(defaultSuffix); QFileDialog dlg(parent, caption, dir, filter); dlg.setAcceptMode(QFileDialog::AcceptSave); if (options) { dlg.setOptions(options); } - if (defaultSuffix) { + if (!defaultSuffixCopy.isEmpty()) { //-- Make sure dot is not present - if (defaultSuffix->startsWith(".")) { - defaultSuffix->remove(0,1); + if (defaultSuffixCopy.startsWith(".")) { + defaultSuffixCopy.remove(0,1); } - dlg.setDefaultSuffix(*defaultSuffix); + dlg.setDefaultSuffix(defaultSuffixCopy); } while (true) { if (dlg.exec()) { @@ -131,16 +130,15 @@ QString QGCFileDialog::getSaveFileName(QWidget* parent, return result; } //-- Do we have a default extension? - QString localDefaultSuffix; - if (!defaultSuffix) { + if (defaultSuffixCopy.isEmpty()) { //-- We don't, so get the first one in the filter - localDefaultSuffix = _getFirstExtensionInFilter(filter); - defaultSuffix = &localDefaultSuffix; + defaultSuffixCopy = _getFirstExtensionInFilter(filter); } - Q_ASSERT(defaultSuffix->isEmpty() == false); + //-- If this is set to strict, we have to have a default extension + Q_ASSERT(defaultSuffixCopy.isEmpty() == false); //-- Forcefully append our desired extension result += "."; - result += *defaultSuffix; + result += defaultSuffixCopy; //-- Check and see if this new file already exists fi.setFile(result); if (fi.exists()) { @@ -203,17 +201,13 @@ QString QGCFileDialog::_getFirstExtensionInFilter(const QString& filter) { } /// @brief Validates and updates the parameters for the file dialog calls -void QGCFileDialog::_validate(QString* selectedFilter, Options& options) +void QGCFileDialog::_validate(Options& options) { // You can't use QGCFileDialog if QGCApplication is not created yet. Q_ASSERT(qgcApp()); Q_ASSERT_X(QThread::currentThread() == qgcApp()->thread(), "Threading issue", "QGCFileDialog can only be called from main thread"); - // Support for selectedFilter is not yet implemented through the unit test framework - Q_UNUSED(selectedFilter); - Q_ASSERT(selectedFilter == NULL); - // On OSX native dialog can hang so we always use Qt dialogs options |= DontUseNativeDialog; diff --git a/src/QGCFileDialog.h b/src/QGCFileDialog.h index a55c92332ceea5e476ec7e3d5542af5c85697821..b88cf1638fdc544774c7f97fc5cf30e3bd71213d 100644 --- a/src/QGCFileDialog.h +++ b/src/QGCFileDialog.h @@ -31,10 +31,21 @@ /// @author Don Gagne /*! - Subclass of QFileDialog which re-implements the static public functions. The reason for this - is that the QFileDialog implementations of these use the native os dialogs. On OSX these - these can intermittently hang. So instead here we use the native dialogs. It also allows - use to catch these dialogs for unit testing. + Subclass of QFileDialog which re-implements the static public functions. The reason for this + is that the QFileDialog implementations of these use the native os dialogs. On OSX these + these can intermittently hang. So instead here we use the native dialogs. It also allows + use to catch these dialogs for unit testing. + @remark If you need to know what type of file was returned by these functions, you can use something like: + @code{.cpp} + QString filename = QGCFileDialog::getSaveFileName(this, tr("Save File"), "~/", "Foo files (*.foo);;All Files (*.*)", "foo"); + if (!filename.isEmpty()) { + QFileInfo fi(filename); + QString fileExtension(fi.suffix()); + if (fileExtension == QString("foo")) { + // do something + } + } + @endcode */ class QGCFileDialog : public QFileDialog { @@ -62,7 +73,6 @@ public: @param[in] caption The caption displayed at the top of the dialog. @param[in] dir The initial directory shown to the user. @param[in] filter The filter used for selecting the file type. - @param[out] selectedFilter **NOT IMPLEMENTED - Set to NULL** Returns the filter that the user selected in the file dialog. @param[in] options Set the various options that affect the look and feel of the dialog. @return The full path and filename to be opened or \c QString("") if none. @sa QFileDialog::getOpenFileName() @@ -72,7 +82,6 @@ public: const QString& caption = QString(), const QString& dir = QString(), const QString& filter = QString(), - QString* selectedFilter = 0, Options options = 0); //! Static helper that invokes a File Open dialog where the user can select one or more files to be opened. @@ -81,7 +90,6 @@ public: @param[in] caption The caption displayed at the top of the dialog. @param[in] dir The initial directory shown to the user. @param[in] filter The filter used for selecting the file type. - @param[out] selectedFilter **NOT IMPLEMENTED - Set to NULL** Returns the filter that the user selected in the file dialog. @param[in] options Set the various options that affect the look and feel of the dialog. @return A QStringList object containing zero or more files to be opened. @sa QFileDialog::getOpenFileNames() @@ -91,7 +99,6 @@ public: const QString& caption = QString(), const QString& dir = QString(), const QString& filter = QString(), - QString* selectedFilter = 0, Options options = 0); //! Static helper that invokes a File Save dialog where the user can select a directory and enter a filename to be saved. @@ -100,10 +107,9 @@ public: @param[in] caption The caption displayed at the top of the dialog. @param[in] dir The initial directory shown to the user. @param[in] filter The filter used for selecting the file type. - @param[out] selectedFilter **NOT IMPLEMENTED - Set to NULL** Returns the filter that the user selected in the file dialog. - @param[in] options Set the various options that affect the look and feel of the dialog. @param[in] defaultSuffix Specifies a string that will be added to the filename if it has no suffix already. The suffix is typically used to indicate the file type (e.g. "txt" indicates a text file). @param[in] strict Makes the default suffix mandatory. Only files with those extensions will be allowed. + @param[in] options Set the various options that affect the look and feel of the dialog. @return The full path and filename to be used to save the file or \c QString("") if none. @sa QFileDialog::getSaveFileName() @remark If a default suffix is given, it will be appended to the filename if the user does not enter one themselves. That is, if the user simply enters \e foo and the default suffix is set to \e bar, @@ -114,18 +120,17 @@ public: const QString& caption = QString(), const QString& dir = QString(), const QString& filter = QString(), - QString* selectedFilter = 0, - Options options = 0, - QString* defaultSuffix = 0, - bool strict = false); - + const QString& defaultSuffix = QString(), + bool strict = false, + Options options = 0); + private slots: - /// @brief The exec slot is private becasue when only want QGCFileDialog users to use the static methods. Otherwise it will break - /// unit testing. + /// @brief The exec slot is private because we only want QGCFileDialog users to use the static methods. Otherwise it will break + /// unit testing. int exec(void) { return QGCFileDialog::exec(); } private: - static void _validate(QString* selectedFilter, Options& options); + static void _validate(Options& options); static bool _validateExtension(const QString& filter, const QString& extension); static QString _getFirstExtensionInFilter(const QString& filter); }; diff --git a/src/VehicleSetup/SetupView.cc b/src/VehicleSetup/SetupView.cc index c1ec1106bf5a9e6c64d20555110b7014da40e294..d48af88e498e9917abcf5b00ac5ed29d393b8236 100644 --- a/src/VehicleSetup/SetupView.cc +++ b/src/VehicleSetup/SetupView.cc @@ -51,7 +51,7 @@ SetupView::SetupView(QWidget* parent) : setResizeMode(SizeRootObjectToView); - _setActiveUAS(NULL); + _setActiveUAS(UASManager::instance()->getActiveUAS()); } SetupView::~SetupView() @@ -120,7 +120,7 @@ void SetupView::_setConnectedView(void) void SetupView::_firmwareButtonClicked(void) { - if (_uasCurrent->isArmed()) { + if (_uasCurrent && _uasCurrent->isArmed()) { QGCMessageBox::warning("Setup", "Firmware Update cannot be performed while vehicle is armed."); return; } diff --git a/src/qgcunittest/UnitTest.cc b/src/qgcunittest/UnitTest.cc index eaa164675935b082db1f2b7aeae04b9428dd4f79..4a403c1c0642937dc24842ce9b0b4d845e5d2d55 100644 --- a/src/qgcunittest/UnitTest.cc +++ b/src/qgcunittest/UnitTest.cc @@ -273,10 +273,11 @@ QString UnitTest::_fileDialogResponseSingle(enum FileDialogType type) return retFile; } -QString UnitTest::_getExistingDirectory(QWidget* parent, - const QString& caption, - const QString& dir, - QFileDialog::Options options) +QString UnitTest::_getExistingDirectory( + QWidget* parent, + const QString& caption, + const QString& dir, + QFileDialog::Options options) { Q_UNUSED(parent); Q_UNUSED(caption); @@ -286,12 +287,12 @@ QString UnitTest::_getExistingDirectory(QWidget* parent, return _fileDialogResponseSingle(getExistingDirectory); } -QString UnitTest::_getOpenFileName(QWidget* parent, - const QString& caption, - const QString& dir, - const QString& filter, - QString* selectedFilter, - QFileDialog::Options options) +QString UnitTest::_getOpenFileName( + QWidget* parent, + const QString& caption, + const QString& dir, + const QString& filter, + QFileDialog::Options options) { Q_UNUSED(parent); Q_UNUSED(caption); @@ -299,18 +300,15 @@ QString UnitTest::_getOpenFileName(QWidget* parent, Q_UNUSED(filter); Q_UNUSED(options); - // Support for selectedFilter is not yet implemented - Q_ASSERT(selectedFilter == NULL); - return _fileDialogResponseSingle(getOpenFileName); } -QStringList UnitTest::_getOpenFileNames(QWidget* parent, - const QString& caption, - const QString& dir, - const QString& filter, - QString* selectedFilter, - QFileDialog::Options options) +QStringList UnitTest::_getOpenFileNames( + QWidget* parent, + const QString& caption, + const QString& dir, + const QString& filter, + QFileDialog::Options options) { Q_UNUSED(parent); Q_UNUSED(caption); @@ -318,9 +316,6 @@ QStringList UnitTest::_getOpenFileNames(QWidget* parent, Q_UNUSED(filter); Q_UNUSED(options); - // Support for selectedFilter is not yet implemented - Q_ASSERT(selectedFilter == NULL); - QStringList retFiles; if (!_fileDialogResponseSet || _fileDialogExpectedType != getOpenFileNames) { @@ -340,13 +335,13 @@ QStringList UnitTest::_getOpenFileNames(QWidget* parent, return retFiles; } -QString UnitTest::_getSaveFileName(QWidget* parent, - const QString& caption, - const QString& dir, - const QString& filter, - QString* selectedFilter, - QFileDialog::Options options, - QString* defaultSuffix) +QString UnitTest::_getSaveFileName( + QWidget* parent, + const QString& caption, + const QString& dir, + const QString& filter, + const QString& defaultSuffix, + QFileDialog::Options options) { Q_UNUSED(parent); Q_UNUSED(caption); @@ -354,11 +349,9 @@ QString UnitTest::_getSaveFileName(QWidget* parent, Q_UNUSED(filter); Q_UNUSED(options); - if(defaultSuffix) - Q_ASSERT(defaultSuffix->startsWith(".") == false); - - // Support for selectedFilter is not yet implemented - Q_ASSERT(selectedFilter == NULL); + if(!defaultSuffix.isEmpty()) { + Q_ASSERT(defaultSuffix.startsWith(".") == false); + } return _fileDialogResponseSingle(getSaveFileName); } diff --git a/src/qgcunittest/UnitTest.h b/src/qgcunittest/UnitTest.h index 44e39ea6c1cbedc1090a3f0143b93e8ae27c76d6..bbc78acb191500f23203e74edba0fb0f7569e2a1 100644 --- a/src/qgcunittest/UnitTest.h +++ b/src/qgcunittest/UnitTest.h @@ -118,33 +118,34 @@ private: // When the app is running in unit test mode the QGCFileDialog methods are re-routed here. - static QString _getExistingDirectory(QWidget* parent, - const QString& caption, - const QString& dir, - QFileDialog::Options options); - - static QString _getOpenFileName(QWidget* parent, - const QString& caption, - const QString& dir, - const QString& filter, - QString* selectedFilter, - QFileDialog::Options options); - - static QStringList _getOpenFileNames(QWidget* parent, - const QString& caption, - const QString& dir, - const QString& filter, - QString* selectedFilter, - QFileDialog::Options options); - - static QString _getSaveFileName(QWidget* parent, - const QString& caption, - const QString& dir, - const QString& filter, - QString* selectedFilter, - QFileDialog::Options options, - QString* defaultSuffix); - + static QString _getExistingDirectory( + QWidget* parent, + const QString& caption, + const QString& dir, + QFileDialog::Options options); + + static QString _getOpenFileName( + QWidget* parent, + const QString& caption, + const QString& dir, + const QString& filter, + QFileDialog::Options options); + + static QStringList _getOpenFileNames( + QWidget* parent, + const QString& caption, + const QString& dir, + const QString& filter, + QFileDialog::Options options); + + static QString _getSaveFileName( + QWidget* parent, + const QString& caption, + const QString& dir, + const QString& filter, + const QString& defaultSuffix, + QFileDialog::Options options); + static QString _fileDialogResponseSingle(enum FileDialogType type); // This allows the private calls to the file dialog methods diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index ce0f3118452d081a7ce524d624a1655a9e5b4cdd..53f9aa3434c63c35e8676f752fd162f68f3c36a6 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -28,7 +28,6 @@ This file is part of the QGROUNDCONTROL project */ #include -#include #include #include #include @@ -66,11 +65,11 @@ This file is part of the QGROUNDCONTROL project #include "SetupView.h" #include "SerialSettingsDialog.h" #include "terminalconsole.h" -#include "menuactionhelper.h" #include "QGCUASFileViewMulti.h" #include "QGCApplication.h" #include "QGCFileDialog.h" #include "QGCMessageBox.h" +#include "QGCDockWidget.h" #ifdef QGC_OSG_ENABLED #include "Q3DWidgetFactory.h" @@ -78,6 +77,22 @@ This file is part of the QGROUNDCONTROL project #include "LogCompressor.h" +const char* MainWindow::_uasControlDockWidgetName = "UNMANNED_SYSTEM_CONTROL_DOCKWIDGET"; +const char* MainWindow::_uasListDockWidgetName = "UNMANNED_SYSTEM_LIST_DOCKWIDGET"; +const char* MainWindow::_waypointsDockWidgetName = "WAYPOINT_LIST_DOCKWIDGET"; +const char* MainWindow::_mavlinkDockWidgetName = "MAVLINK_INSPECTOR_DOCKWIDGET"; +const char* MainWindow::_parametersDockWidgetName = "PARAMETER_INTERFACE_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::_hsiDockWidgetName = "HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET"; +const char* MainWindow::_hdd1DockWidgetName = "HEAD_DOWN_DISPLAY_1_DOCKWIDGET"; +const char* MainWindow::_hdd2DockWidgetName = "HEAD_DOWN_DISPLAY_2_DOCKWIDGET"; +const char* MainWindow::_pfdDockWidgetName = "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET"; +const char* MainWindow::_hudDockWidgetName = "HEAD_UP_DISPLAY_DOCKWIDGET"; +const char* MainWindow::_uasInfoViewDockWidgetName = "UAS_INFO_INFOVIEW_DOCKWIDGET"; +const char* MainWindow::_debugConsoleDockWidgetName = "COMMUNICATION_CONSOLE_DOCKWIDGET"; + static MainWindow* _instance = NULL; ///< @brief MainWindow singleton MainWindow* MainWindow::_create(QSplashScreen* splashScreen) @@ -106,12 +121,12 @@ void MainWindow::deleteInstance(void) /// by MainWindow::_create method. Hence no other code should have access to /// constructor. MainWindow::MainWindow(QSplashScreen* splashScreen) : - currentView(VIEW_FLIGHT), centerStackActionGroup(new QActionGroup(this)), autoReconnect(false), simulationLink(NULL), lowPowerMode(false), - menuActionHelper(new MenuActionHelper()), + _currentView(VIEW_FLIGHT), + _currentViewWidget(NULL), _splashScreen(splashScreen) { Q_ASSERT(_instance == NULL); @@ -121,52 +136,42 @@ MainWindow::MainWindow(QSplashScreen* splashScreen) : connect(this, &MainWindow::initStatusChanged, splashScreen, &QSplashScreen::showMessage); } - connect(menuActionHelper, SIGNAL(needToShowDockWidget(QString,bool)),SLOT(showDockWidget(QString,bool))); - loadSettings(); - if (settings.contains("ADVANCED_MODE")) - { - menuActionHelper->setAdvancedMode(settings.value("ADVANCED_MODE").toBool()); - } - // Select the proper view. Default to the flight view or load the last one used if it's supported. - if (!settings.contains("CURRENT_VIEW")) - { - settings.setValue("CURRENT_VIEW", currentView); - } - else - { - VIEW_SECTIONS currentViewCandidate = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt(); - switch (currentViewCandidate) { - case VIEW_ENGINEER: - case VIEW_MISSION: - case VIEW_FLIGHT: - case VIEW_SIMULATION: - case VIEW_SETUP: - case VIEW_TERMINAL: - -// And only re-load views if they're supported with the current QGC build + VIEW_SECTIONS currentViewCandidate = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", _currentView).toInt(); + switch (currentViewCandidate) { + case VIEW_ENGINEER: + case VIEW_MISSION: + case VIEW_FLIGHT: + case VIEW_SIMULATION: + case VIEW_SETUP: + case VIEW_TERMINAL: #ifdef QGC_OSG_ENABLED - case VIEW_LOCAL3D: + case VIEW_LOCAL3D: #endif #ifdef QGC_GOOGLE_EARTH_ENABLED - case VIEW_GOOGLEEARTH: + case VIEW_GOOGLEEARTH: #endif - - currentView = currentViewCandidate; - default: - // If an invalid view candidate was found in the settings file, just use the default view and re-save. - settings.setValue("CURRENT_VIEW", currentView); - break; - } + _currentView = currentViewCandidate; + break; + + default: + // Leave _currentView to the default + break; } + + // Put it back, which will set it to a valid value + settings.setValue("CURRENT_VIEW", _currentView); emit initStatusChanged(tr("Setting up user interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); // Setup user interface ui.setupUi(this); - menuActionHelper->setMenu(ui.menuTools); + + // Setup central widget with a layout to hold the views + _centralLayout = new QVBoxLayout(); + centralWidget()->setLayout(_centralLayout); // Set dock options setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks); @@ -185,10 +190,6 @@ MainWindow::MainWindow(QSplashScreen* splashScreen) : // Setup UI state machines centerStackActionGroup->setExclusive(true); - centerStack = new QStackedWidget(this); - setCentralWidget(centerStack); - - // Load Toolbar toolBar = new QGCToolBar(this); this->addToolBar(toolBar); @@ -214,8 +215,7 @@ MainWindow::MainWindow(QSplashScreen* splashScreen) : emit initStatusChanged(tr("Building common widgets."), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); - buildCommonWidgets(); - connectCommonWidgets(); + _buildCommonWidgets(); emit initStatusChanged(tr("Building common actions"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); @@ -266,13 +266,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen) : // Set low power mode enableLowPowerMode(lowPowerMode); - // Initialize window state - windowStateVal = windowState(); - emit initStatusChanged(tr("Restoring last view state"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); // Restore the window setup - loadViewState(); + _loadCurrentViewState(); emit initStatusChanged(tr("Restoring last window size"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); // Restore the window position and size @@ -362,31 +359,7 @@ MainWindow::~MainWindow() joystick = NULL; } - // Get and delete all dockwidgets and contained - // widgets - QObjectList childList(this->children()); - - QObjectList::iterator i; - QDockWidget* dockWidget; - for (i = childList.begin(); i != childList.end(); ++i) - { - dockWidget = dynamic_cast(*i); - if (dockWidget) - { - // Remove dock widget from main window - // removeDockWidget(dockWidget); - // delete dockWidget->widget(); - delete dockWidget; - dockWidget = NULL; - } - else if (dynamic_cast(*i)) - { - delete dynamic_cast(*i); - *i = NULL; - } - } // Delete all UAS objects - delete menuActionHelper; for (int i=0;ideleteLater(); @@ -404,10 +377,10 @@ QString MainWindow::getWindowStateKey() { if (UASManager::instance()->getActiveUAS()) { - return QString::number(currentView)+"_windowstate_" + UASManager::instance()->getActiveUAS()->getAutopilotTypeName(); + return QString::number(_currentView)+"_windowstate_" + UASManager::instance()->getActiveUAS()->getAutopilotTypeName(); } else - return QString::number(currentView)+"_windowstate_"; + return QString::number(_currentView)+"_windowstate_"; } QString MainWindow::getWindowGeometryKey() @@ -415,64 +388,61 @@ QString MainWindow::getWindowGeometryKey() return "_geometry"; } -void MainWindow::buildCustomWidget() +void MainWindow::_buildCustomWidgets(void) { + Q_ASSERT(_customWidgets.count() == 0); + // Create custom widgets - QList widgets = QGCToolWidget::createWidgetsFromSettings(this); + _customWidgets = QGCToolWidget::createWidgetsFromSettings(this); - if (widgets.size() > 0) + if (_customWidgets.size() > 0) { ui.menuTools->addSeparator(); } - - for(int i = 0; i < widgets.size(); ++i) - { + + foreach(QGCToolWidget* tool, _customWidgets) { // Check if this widget already has a parent, do not create it in this case - QGCToolWidget* tool = widgets.at(i); QDockWidget* dock = dynamic_cast(tool->parentWidget()); - if (!dock) - { - QSettings settings; - settings.beginGroup("QGC_MAINWINDOW"); - - // Load dock widget location (default is bottom) - Qt::DockWidgetArea location = tool->getDockWidgetArea(currentView); - - int view = settings.value(QString("TOOL_PARENT_") + tool->objectName(),-1).toInt(); - settings.endGroup(); - - QDockWidget* dock; - - switch (view) - { - case VIEW_ENGINEER: - dock = createDockWidget(engineeringView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location); - break; - default: // Flight view is the default. - case VIEW_FLIGHT: - dock = createDockWidget(pilotView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location); - break; - case VIEW_SIMULATION: - dock = createDockWidget(simView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location); - break; - case VIEW_MISSION: - dock = createDockWidget(plannerView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location); - break; - case VIEW_GOOGLEEARTH: - dock = createDockWidget(googleEarthView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location); - break; - case VIEW_LOCAL3D: - dock = createDockWidget(local3DView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location); - break; - } - - // XXX temporary "fix" - dock->hide(); + + if (!dock) { + _createDockWidget(tool->getTitle(), tool->objectName(), Qt::BottomDockWidgetArea, tool); } } } -void MainWindow::buildCommonWidgets() +void MainWindow::_createDockWidget(const QString& title, const QString& name, Qt::DockWidgetArea area, QWidget* innerWidget) +{ + Q_ASSERT(!_mapName2DockWidget.contains(name)); + + QGCDockWidget* dockWidget = new QGCDockWidget(title, 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); + } + + // Add to menu + + QAction* action = new QAction(title, NULL); + action->setCheckable(true); + action->setData(name); + + connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction); + + ui.menuTools->addAction(action); + + _mapName2DockWidget[name] = dockWidget; + _mapDockWidget2Action[dockWidget] = action; + + addDockWidget(area, dockWidget); +} + +void MainWindow::_buildCommonWidgets(void) { // Add generic MAVLink decoder mavlinkDecoder = new MAVLinkDecoder(MAVLinkProtocol::instance(), this); @@ -483,274 +453,246 @@ void MainWindow::buildCommonWidgets() logPlayer = new QGCMAVLinkLogPlayer(MAVLinkProtocol::instance(), statusBar()); statusBar()->addPermanentWidget(logPlayer); - // Initialize all of the views, if they haven't been already, and add their central widgets - if (!plannerView) - { - plannerView = new SubMainWindow(this); - plannerView->setObjectName("VIEW_MISSION"); - plannerView->setCentralWidget(new QGCMapTool(this)); - addToCentralStackedWidget(plannerView, VIEW_MISSION, "Maps"); - } - if (!pilotView) - { - pilotView = new SubMainWindow(this); - pilotView->setObjectName("VIEW_FLIGHT"); - pilotView->setCentralWidget(new PrimaryFlightDisplay(this)); - addToCentralStackedWidget(pilotView, VIEW_FLIGHT, "Pilot"); - } - if (!terminalView) - { - terminalView = new SubMainWindow(this); - terminalView->setObjectName("VIEW_TERMINAL"); - TerminalConsole *terminalConsole = new TerminalConsole(this); - terminalView->setCentralWidget(terminalConsole); - addToCentralStackedWidget(terminalView, VIEW_TERMINAL, tr("Terminal View")); - } - if (!setupView) - { - setupView = new SubMainWindow(this); - setupView->setObjectName("VIEW_SETUP"); - setupView->setCentralWidget((QWidget*)new SetupView(this)); - addToCentralStackedWidget(setupView, VIEW_SETUP, "Setup"); - } - if (!engineeringView) - { - engineeringView = new SubMainWindow(this); - engineeringView->setObjectName("VIEW_ENGINEER"); - engineeringView->setCentralWidget(new QGCDataPlot2D(this)); - addToCentralStackedWidget(engineeringView, VIEW_ENGINEER, tr("Logfile Plot")); - } -#ifdef QGC_GOOGLE_EARTH_ENABLED - if (!googleEarthView) - { - googleEarthView = new SubMainWindow(this); - googleEarthView->setObjectName("VIEW_GOOGLEEARTH"); - googleEarthView->setCentralWidget(new QGCGoogleEarthView(this)); - addToCentralStackedWidget(googleEarthView, VIEW_GOOGLEEARTH, tr("Google Earth View")); + // 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 struct DockWidgetInfo rgDockWidgetInfo[] = { + { _uasControlDockWidgetName, "Control", Qt::LeftDockWidgetArea }, + { _uasListDockWidgetName, "Unmanned Systems", Qt::RightDockWidgetArea }, + { _waypointsDockWidgetName, "Mission Plan", Qt::BottomDockWidgetArea }, + { _mavlinkDockWidgetName, "MAVLink Inspector", Qt::RightDockWidgetArea }, + { _parametersDockWidgetName, "Onboard Parameters", Qt::RightDockWidgetArea }, + { _filesDockWidgetName, "Onboard Files", Qt::RightDockWidgetArea }, + { _uasStatusDetailsDockWidgetName, "Status Details", Qt::RightDockWidgetArea }, + { _mapViewDockWidgetName, "Map view", Qt::RightDockWidgetArea }, + { _hsiDockWidgetName, "Horizontal Situation", Qt::BottomDockWidgetArea }, + { _hdd1DockWidgetName, "Flight Display", Qt::RightDockWidgetArea }, + { _hdd2DockWidgetName, "Actuator Status", Qt::RightDockWidgetArea }, + { _pfdDockWidgetName, "Primary Flight Display", Qt::RightDockWidgetArea }, + { _hudDockWidgetName, "Video Downlink", Qt::RightDockWidgetArea }, + { _uasInfoViewDockWidgetName, "Info View", Qt::LeftDockWidgetArea }, + { _debugConsoleDockWidgetName, "Communications Console", Qt::LeftDockWidgetArea } + }; + static const size_t cDockWidgetInfo = sizeof(rgDockWidgetInfo) / sizeof(rgDockWidgetInfo[0]); + + for (size_t i=0; ititle, pDockInfo->name, pDockInfo->area, NULL /* no inner widget yet */); } -#endif -#ifdef QGC_OSG_ENABLED - if (!local3DView) - { - q3DWidget = Q3DWidgetFactory::get("PIXHAWK", this); - q3DWidget->setObjectName("VIEW_3DWIDGET"); - local3DView = new SubMainWindow(this); - local3DView->setObjectName("VIEW_LOCAL3D"); - local3DView->setCentralWidget(q3DWidget); - addToCentralStackedWidget(local3DView, VIEW_LOCAL3D, tr("Local 3D View")); - } -#endif + _buildCustomWidgets(); +} - if (!simView) - { - simView = new SubMainWindow(this); - simView->setObjectName("VIEW_SIMULATOR"); - simView->setCentralWidget(new QGCMapTool(this)); - addToCentralStackedWidget(simView, VIEW_SIMULATION, tr("Simulation View")); +void MainWindow::_buildPlannerView(void) +{ + if (!_plannerView) { + _plannerView = new QGCMapTool(this); + _plannerView->setVisible(false); } +} - // Add dock widgets for the planner view - createDockWidget(plannerView, new UASListWidget(this), tr("Unmanned Systems"), "UNMANNED_SYSTEM_LIST_DOCKWIDGET", VIEW_MISSION, Qt::LeftDockWidgetArea); - createDockWidget(plannerView, new QGCWaypointListMulti(this), tr("Mission Plan"), "WAYPOINT_LIST_DOCKWIDGET", VIEW_MISSION, Qt::BottomDockWidgetArea); - - // Add dock widgets for the pilot view - createDockWidget(pilotView, new DebugConsole(this), tr("Communications Console"), "COMMUNICATION_CONSOLE_DOCKWIDGET", VIEW_FLIGHT, Qt::LeftDockWidgetArea); - QGCTabbedInfoView *infoview = new QGCTabbedInfoView(this); - infoview->addSource(mavlinkDecoder); - createDockWidget(pilotView, infoview, tr("Info View"), "UAS_INFO_INFOVIEW_DOCKWIDGET", VIEW_FLIGHT, Qt::LeftDockWidgetArea); - - // Add dock widgets for the simulation view - createDockWidget(simView,new UASControlWidget(this),tr("Control"),"UNMANNED_SYSTEM_CONTROL_DOCKWIDGET",VIEW_SIMULATION,Qt::LeftDockWidgetArea); - createDockWidget(simView,new QGCWaypointListMulti(this),tr("Mission Plan"),"WAYPOINT_LIST_DOCKWIDGET",VIEW_SIMULATION,Qt::BottomDockWidgetArea); - createDockWidget(simView, new ParameterInterface(this), tr("Onboard Parameters"), "PARAMETER_INTERFACE_DOCKWIDGET", VIEW_SIMULATION, Qt::RightDockWidgetArea); - createDockWidget(simView, new PrimaryFlightDisplay(this), tr("Primary Flight Display"), "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET", VIEW_SIMULATION, Qt::RightDockWidgetArea); - - // Add dock widgets for the engineering view - createDockWidget(engineeringView, new QGCMAVLinkInspector(MAVLinkProtocol::instance(), this), tr("MAVLink Inspector"), "MAVLINK_INSPECTOR_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea); - createDockWidget(engineeringView, new ParameterInterface(this), tr("Onboard Parameters"), "PARAMETER_INTERFACE_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea); - createDockWidget(engineeringView, new QGCUASFileViewMulti(this), tr("Onboard Files"), "FILE_VIEW_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea); - createDockWidget(engineeringView, new HUD(320, 240, this), tr("Video Downlink"), "HEAD_UP_DISPLAY_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea); - - // Add some extra widgets to the Tool Widgets menu - menuActionHelper->createToolAction(tr("Map View"), "MAP_VIEW_DOCKWIDGET"); - menuActionHelper->createToolAction(tr("Status Details"), "UAS_STATUS_DETAILS_DOCKWIDGET"); - menuActionHelper->createToolAction(tr("Flight Display"), "HEAD_DOWN_DISPLAY_1_DOCKWIDGET"); - menuActionHelper->createToolAction(tr("Actuator Status"), "HEAD_DOWN_DISPLAY_2_DOCKWIDGET"); - - // Add any custom widgets last to all menus and layouts - buildCustomWidget(); +void MainWindow::_buildPilotView(void) +{ + if (!_pilotView) { + _pilotView = new PrimaryFlightDisplay(this); + _pilotView->setVisible(false); + } } -void MainWindow::addTool(SubMainWindow *parent,VIEW_SECTIONS view,QDockWidget* widget, const QString& title, Qt::DockWidgetArea area) +void MainWindow::_buildSetupView(void) { - menuActionHelper->createToolActionForCustomDockWidget(title, widget->objectName(), widget, view); - parent->addDockWidget(area,widget); + if (!_setupView) { + _setupView = new SetupView(this); + _setupView->setVisible(false); + } } -QDockWidget* MainWindow::createDockWidget(QWidget *subMainWindowParent,QWidget *child,const QString& title,const QString& objectName,VIEW_SECTIONS view,Qt::DockWidgetArea area,const QSize& minSize) +void MainWindow::_buildEngineeringView(void) { - SubMainWindow *parent = qobject_cast(subMainWindowParent); - Q_ASSERT(parent); - QDockWidget* dockWidget = menuActionHelper->createDockWidget(title, objectName); - child->setObjectName(objectName); - dockWidget->setWidget(child); //Set child objectName before setting dockwidget, since the dock widget might react to object name changes - connect(child, SIGNAL(destroyed()), dockWidget, SLOT(deleteLater())); //Our dockwidget only has only child widget, so kill the dock widget if the child is deleted + if (!_engineeringView) { + _engineeringView = new QGCDataPlot2D(this); + _engineeringView->setVisible(false); + } +} - if (minSize.height() >= 0) - dockWidget->setMinimumHeight(minSize.height()); - if (minSize.width() >= 0) - dockWidget->setMinimumWidth(minSize.width()); - addTool(parent,view,dockWidget,title,area); - return dockWidget; +void MainWindow::_buildSimView(void) +{ + if (!_simView) { + _simView = new QGCMapTool(this); + _simView->setVisible(false); + } } -void MainWindow::showDockWidget(const QString& name, bool show) +void MainWindow::_buildTerminalView(void) { - QDockWidget *dockWidget = menuActionHelper->getDockWidget(currentView, name); - if(dockWidget) - dockWidget->setVisible(show); - else if (show) - loadDockWidget(name); + if (!_terminalView) { + _terminalView = new TerminalConsole(this); + _terminalView->setVisible(false); + } } -void MainWindow::fullScreenActionItemCallback() +void MainWindow::_buildGoogleEarthView(void) { - ui.actionNormal->setChecked(false); +#ifdef QGC_GOOGLE_EARTH_ENABLED + if (!_googleEarthView) { + _googleEarthView = new QGCGoogleEarthView(this); + _googleEarthView->setVisible(false); + } +#endif } -void MainWindow::normalActionItemCallback() +void MainWindow::_buildLocal3DView(void) { - ui.actionFullscreen->setChecked(false); +#ifdef QGC_OSG_ENABLED + if (!_local3DView) { + _local3DView = Q3DWidgetFactory::get("PIXHAWK", this); + _local3DView->setVisible(false); + } +#endif } -void MainWindow::loadDockWidget(const QString& name) +/// Shows or hides the specified dock widget, creating if necessary +void MainWindow::_showDockWidget(const QString& name, bool show) { - if(menuActionHelper->containsDockWidget(currentView, name)) + if (!_mapName2DockWidget.contains(name)) { + qWarning() << "Attempt to show unknown dock widget" << name; return; - - if (name.startsWith("HIL_CONFIG")) - { - //It's a HIL widget. - showHILConfigurationWidget(UASManager::instance()->getActiveUAS()); - } - else if (name == "UNMANNED_SYSTEM_CONTROL_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new UASControlWidget(this),tr("Control"),"UNMANNED_SYSTEM_CONTROL_DOCKWIDGET",currentView,Qt::LeftDockWidgetArea); - } - else if (name == "UNMANNED_SYSTEM_LIST_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new UASListWidget(this),tr("Unmanned Systems"),"UNMANNED_SYSTEM_LIST_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "WAYPOINT_LIST_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new QGCWaypointListMulti(this),tr("Mission Plan"),"WAYPOINT_LIST_DOCKWIDGET",currentView,Qt::BottomDockWidgetArea); - } - else if (name == "MAVLINK_INSPECTOR_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new QGCMAVLinkInspector(MAVLinkProtocol::instance(),this),tr("MAVLink Inspector"),"MAVLINK_INSPECTOR_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "PARAMETER_INTERFACE_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new ParameterInterface(this),tr("Onboard Parameters"),"PARAMETER_INTERFACE_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "FILE_VIEW_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new QGCUASFileViewMulti(this),tr("Onboard Files"),"FILE_VIEW_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "UAS_STATUS_DETAILS_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new UASInfoWidget(this),tr("Status Details"),"UAS_STATUS_DETAILS_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); } - else if (name == "MAP_VIEW_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new QGCMapTool(this),tr("Map view"),"MAP_VIEW_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET") - { - //This is now a permanently detached window. - } - else if (name == "HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new HSIDisplay(this),tr("Horizontal Situation"),"HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET",currentView,Qt::BottomDockWidgetArea); + + // Create the inner widget if we need to + if (!_mapName2DockWidget[name]->widget()) { + _createInnerDockWidget(name); } - else if (name == "HEAD_DOWN_DISPLAY_1_DOCKWIDGET") - { + + Q_ASSERT(_mapName2DockWidget.contains(name)); + QDockWidget* dockWidget = _mapName2DockWidget[name]; + Q_ASSERT(dockWidget); + + dockWidget->setVisible(show); + + Q_ASSERT(_mapDockWidget2Action.contains(dockWidget)); + _mapDockWidget2Action[dockWidget]->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; + + if (widgetName == _uasControlDockWidgetName) { + widget = new UASControlWidget(this); + } else if (widgetName == _uasListDockWidgetName) { + widget = new UASListWidget(this); + } else if (widgetName == _waypointsDockWidgetName) { + widget = new QGCWaypointListMulti(this); + } else if (widgetName == _mavlinkDockWidgetName) { + widget = new QGCMAVLinkInspector(MAVLinkProtocol::instance(),this); + } else if (widgetName == _parametersDockWidgetName) { + widget = new ParameterInterface(this); + } else if (widgetName == _filesDockWidgetName) { + widget = new QGCUASFileViewMulti(this); + } else if (widgetName == _uasStatusDetailsDockWidgetName) { + widget = new UASInfoWidget(this); + } else if (widgetName == _mapViewDockWidgetName) { + widget = new QGCMapTool(this); + } else if (widgetName == _hsiDockWidgetName) { + widget = new HSIDisplay(this); + } else if (widgetName == _hdd1DockWidgetName) { QStringList acceptList; acceptList.append("-3.3,ATTITUDE.roll,rad,+3.3,s"); acceptList.append("-3.3,ATTITUDE.pitch,deg,+3.3,s"); acceptList.append("-3.3,ATTITUDE.yaw,deg,+3.3,s"); HDDisplay *hddisplay = new HDDisplay(acceptList,"Flight Display",this); hddisplay->addSource(mavlinkDecoder); - createDockWidget(centerStack->currentWidget(),hddisplay,tr("Flight Display"),"HEAD_DOWN_DISPLAY_1_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "HEAD_DOWN_DISPLAY_2_DOCKWIDGET") - { + + widget = hddisplay; + } else if (widgetName == _hdd2DockWidgetName) { QStringList acceptList; acceptList.append("0,RAW_PRESSURE.pres_abs,hPa,65500"); HDDisplay *hddisplay = new HDDisplay(acceptList,"Actuator Status",this); hddisplay->addSource(mavlinkDecoder); - createDockWidget(centerStack->currentWidget(),hddisplay,tr("Actuator Status"),"HEAD_DOWN_DISPLAY_2_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new PrimaryFlightDisplay(this),tr("Primary Flight Display"),"PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "HEAD_UP_DISPLAY_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new HUD(320,240,this),tr("Video Downlink"),"HEAD_UP_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); - } - else if (name == "UAS_INFO_QUICKVIEW_DOCKWIDGET") - { - createDockWidget(centerStack->currentWidget(),new UASQuickView(this),tr("Quick View"),"UAS_INFO_QUICKVIEW_DOCKWIDGET",currentView,Qt::LeftDockWidgetArea); + + widget = hddisplay; + } else if (widgetName == _pfdDockWidgetName) { + widget = new PrimaryFlightDisplay(this); + } else if (widgetName == _hudDockWidgetName) { + widget = new HUD(320,240,this); + } else if (widgetName == _uasInfoViewDockWidgetName) { + widget = new QGCTabbedInfoView(this); + } else if (widgetName == _debugConsoleDockWidgetName) { + widget = new DebugConsole(this); + } else { + qWarning() << "Attempt to create unknown Inner Dock Widget" << widgetName; } - else - { - if (customWidgetNameToFilenameMap.contains(name)) - { - loadCustomWidget(customWidgetNameToFilenameMap[name],currentView); - } - else - { - qDebug() << "Error loading window:" << name; - } + + if (widget) { + QDockWidget* dockWidget = _mapName2DockWidget[widgetName]; + Q_CHECK_PTR(dockWidget); + + widget->setParent(dockWidget); + dockWidget->setWidget(widget); } } -void MainWindow::addToCentralStackedWidget(QWidget* widget, VIEW_SECTIONS viewSection, const QString& title) +void MainWindow::_showHILConfigurationWidgets(void) { - Q_UNUSED(viewSection); - Q_UNUSED(title); - Q_ASSERT(widget->objectName().length() != 0); + UASInterface* uas = UASManager::instance()->getActiveUAS(); + + if (!uas) { + return; + } + + UAS* mav = dynamic_cast(uas); + Q_ASSERT(mav); + + int uasId = mav->getUASID(); - // Check if this widget already has been added - if (centerStack->indexOf(widget) == -1) - { - centerStack->addWidget(widget); + if (!_mapUasId2HilDockWidget.contains(uasId)) { + + // Create QDockWidget + QGCDockWidget* dockWidget = new QGCDockWidget(tr("HIL Config %1").arg(uasId), this); + Q_CHECK_PTR(dockWidget); + dockWidget->setObjectName(tr("HIL_CONFIG_%1").arg(uasId)); + dockWidget->setVisible (false); + + // Create inner widget and set it + QWidget* widget = new QGCHilConfiguration(mav, dockWidget); + + widget->setParent(dockWidget); + dockWidget->setWidget(widget); + + _mapUasId2HilDockWidget[uasId] = dockWidget; + + addDockWidget(Qt::LeftDockWidgetArea, dockWidget); + } + + if (_currentView == VIEW_SIMULATION) { + // HIL dock widgets only show up on simulation view + foreach (QDockWidget* dockWidget, _mapUasId2HilDockWidget) { + dockWidget->setVisible(true); + } } } - -void MainWindow::showCentralWidget() +void MainWindow::fullScreenActionItemCallback() { - QAction* act = qobject_cast(sender()); - QWidget* widget = act->data().value(); - centerStack->setCurrentWidget(widget); + ui.actionNormal->setChecked(false); } -void MainWindow::showHILConfigurationWidget(UASInterface* uas) +void MainWindow::normalActionItemCallback() { - // Add simulation configuration widget - UAS* mav = dynamic_cast(uas); - - if (mav && !hilDocks.contains(mav->getUASID())) - { - QGCHilConfiguration* hconf = new QGCHilConfiguration(mav, this); - QString hilDockName = tr("HIL Config %1").arg(uas->getUASName()); - QString hilDockObjectName = QString("HIL_CONFIG_%1").arg(uas->getUASName().toUpper().replace(' ','_')); - QDockWidget* hilDock = createDockWidget(simView, hconf,hilDockName, hilDockObjectName,VIEW_SIMULATION,Qt::LeftDockWidgetArea); - hilDocks.insert(mav->getUASID(), hilDock); - } + ui.actionFullscreen->setChecked(false); } void MainWindow::closeEvent(QCloseEvent *event) @@ -789,25 +731,13 @@ void MainWindow::closeEvent(QCloseEvent *event) Q_ASSERT(!link->isConnected()); } - storeViewState(); + _storeCurrentViewState(); storeSettings(); UASManager::instance()->storeSettings(); event->accept(); } -/** - * Connect the signals and slots of the common window widgets - */ -void MainWindow::connectCommonWidgets() -{ - if (infoDockWidget && infoDockWidget->widget()) - { - connect(MAVLinkProtocol::instance(), SIGNAL(receiveLossChanged(int, float)), - infoDockWidget->widget(), SLOT(updateSendLoss(int, float))); - } -} - -void MainWindow::createCustomWidget() +void MainWindow::_createNewCustomWidget(void) { if (QGCToolWidget::instances()->isEmpty()) { @@ -825,112 +755,27 @@ void MainWindow::createCustomWidget() QString title = tr("Custom Tool %1").arg(customToolIndex ); QGCToolWidget* tool = new QGCToolWidget(objectName, title); - createDockWidget(centerStack->currentWidget(),tool,title,objectName,currentView,Qt::BottomDockWidgetArea); - - QSettings settings; - settings.beginGroup("QGC_MAINWINDOW"); - settings.setValue(QString("TOOL_PARENT_") + tool->objectName(),currentView); - settings.endGroup(); -} - -void MainWindow::loadCustomWidget() -{ - QString widgetFileExtension(".qgw"); - QString fileName = QGCFileDialog::getOpenFileName(this, tr("Specify Widget File Name"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr("QGroundControl Widget (*%1)").arg(widgetFileExtension)); - if (fileName != "") loadCustomWidget(fileName); -} -void MainWindow::loadCustomWidget(const QString& fileName, int view) -{ - QGCToolWidget* tool = new QGCToolWidget("", "", this); - if (tool->loadSettings(fileName, true)) - { - qDebug() << "Loading custom tool:" << tool->getTitle() << tool->objectName(); - switch ((VIEW_SECTIONS)view) - { - case VIEW_ENGINEER: - createDockWidget(engineeringView,tool,tool->getTitle(),tool->objectName()+"DOCK",(VIEW_SECTIONS)view,Qt::LeftDockWidgetArea); - break; - default: // Flight view is the default. - case VIEW_FLIGHT: - createDockWidget(pilotView,tool,tool->getTitle(),tool->objectName()+"DOCK",(VIEW_SECTIONS)view,Qt::LeftDockWidgetArea); - break; - case VIEW_SIMULATION: - createDockWidget(simView,tool,tool->getTitle(),tool->objectName()+"DOCK",(VIEW_SECTIONS)view,Qt::LeftDockWidgetArea); - break; - case VIEW_MISSION: - createDockWidget(plannerView,tool,tool->getTitle(),tool->objectName()+"DOCK",(VIEW_SECTIONS)view,Qt::LeftDockWidgetArea); - break; - } - } - else - { - return; - } -} - -void MainWindow::loadCustomWidget(const QString& fileName, bool singleinstance) -{ - QGCToolWidget* tool = new QGCToolWidget("", "", this); - if (tool->loadSettings(fileName, true) || !singleinstance) - { - qDebug() << "Loading custom tool:" << tool->getTitle() << tool->objectName(); - QSettings settings; - settings.beginGroup("QGC_MAINWINDOW"); - - int view = settings.value(QString("TOOL_PARENT_") + tool->objectName(),-1).toInt(); - switch (view) - { - case VIEW_ENGINEER: - createDockWidget(engineeringView,tool,tool->getTitle(),tool->objectName()+"DOCK",(VIEW_SECTIONS)view,Qt::LeftDockWidgetArea); - break; - default: // Flight view is the default. - case VIEW_FLIGHT: - createDockWidget(pilotView,tool,tool->getTitle(),tool->objectName()+"DOCK",(VIEW_SECTIONS)view,Qt::LeftDockWidgetArea); - break; - case VIEW_SIMULATION: - createDockWidget(simView,tool,tool->getTitle(),tool->objectName()+"DOCK",(VIEW_SECTIONS)view,Qt::LeftDockWidgetArea); - break; - case VIEW_MISSION: - createDockWidget(plannerView,tool,tool->getTitle(),tool->objectName()+"DOCK",(VIEW_SECTIONS)view,Qt::LeftDockWidgetArea); - break; - } - - - settings.endGroup(); - } - else - { - return; - } + tool->resize(100, 100); + _createDockWidget(title, objectName, Qt::BottomDockWidgetArea, tool); + + _mapName2DockWidget[objectName]->setVisible(true); } -void MainWindow::loadCustomWidgetsFromDefaults(const QString& systemType, const QString& autopilotType) +void MainWindow::_loadCustomWidgetFromFile(void) { - QString defaultsDir = qApp->applicationDirPath() + "/files/" + autopilotType.toLower() + "/widgets/"; - QString platformDir = qApp->applicationDirPath() + "/files/" + autopilotType.toLower() + "/" + systemType.toLower() + "/widgets/"; - - QDir widgets(defaultsDir); - QStringList files = widgets.entryList(); - QDir platformWidgets(platformDir); - files.append(platformWidgets.entryList()); - - if (files.count() == 0) - { - qDebug() << "No default custom widgets for system " << systemType << "autopilot" << autopilotType << " found"; - qDebug() << "Tried with path: " << defaultsDir; - } - - // Load all custom widgets found in the AP folder - for(int i = 0; i < files.count(); ++i) - { - QString file = files[i]; - if (file.endsWith(".qgw")) - { - // Will only be loaded if not already a custom widget with - // the same name is present - loadCustomWidget(defaultsDir+"/"+file, true); + QString fileName = QGCFileDialog::getOpenFileName( + this, tr("Load Widget File"), + QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), + tr("QGroundControl Widget (*.qgw);;All Files (*)")); + if (!fileName.isEmpty()) { + QGCToolWidget* tool = new QGCToolWidget("", "", this); + if (tool->loadSettings(fileName, true)) { + QString objectName = tool->objectName() + "DOCK"; + _createDockWidget(tool->getTitle(), objectName, Qt::LeftDockWidgetArea, tool); + _mapName2DockWidget[objectName]->widget()->setVisible(true); } } + // TODO Add error dialog if widget could not be loaded } void MainWindow::loadSettings() @@ -940,10 +785,7 @@ void MainWindow::loadSettings() settings.beginGroup("QGC_MAINWINDOW"); autoReconnect = settings.value("AUTO_RECONNECT", autoReconnect).toBool(); lowPowerMode = settings.value("LOW_POWER_MODE", lowPowerMode).toBool(); - bool dockWidgetTitleBarEnabled = settings.value("DOCK_WIDGET_TITLEBARS",menuActionHelper->dockWidgetTitleBarsEnabled()).toBool(); settings.endGroup(); - - enableDockWidgetTitleBars(dockWidgetTitleBarEnabled); } void MainWindow::storeSettings() @@ -958,13 +800,13 @@ void MainWindow::storeSettings() settings.setValue(getWindowGeometryKey(), saveGeometry()); // Save the last current view in any case - settings.setValue("CURRENT_VIEW", currentView); + settings.setValue("CURRENT_VIEW", _currentView); // Save the current window state, but only if a system is connected (else no real number of widgets would be present)) if (UASManager::instance()->getUASList().length() > 0) settings.setValue(getWindowStateKey(), saveState()); // Save the current UAS view if a UAS is connected - if (UASManager::instance()->getUASList().length() > 0) settings.setValue("CURRENT_VIEW_WITH_UAS_CONNECTED", currentView); + if (UASManager::instance()->getUASList().length() > 0) settings.setValue("CURRENT_VIEW_WITH_UAS_CONNECTED", _currentView); // And save any custom weidgets QGCToolWidget::storeWidgetsToSettings(settings); @@ -996,16 +838,16 @@ void MainWindow::configureWindowName() void MainWindow::startVideoCapture() { + // TODO: What is this? What kind of "Video" is saved to bmp? QString format("bmp"); QString initialPath = QDir::currentPath() + tr("/untitled.") + format; QString screenFileName = QGCFileDialog::getSaveFileName( - this, tr("Save As"), + this, tr("Save Video Capture"), initialPath, tr("%1 Files (*.%2);;All Files (*)") .arg(format.toUpper()) .arg(format), - 0,0, - &format); + format); delete videoTimer; videoTimer = new QTimer(this); } @@ -1027,14 +869,6 @@ void MainWindow::saveScreen() window.save(screenFileName, format.toLatin1()); } } -void MainWindow::enableDockWidgetTitleBars(bool enabled) -{ - menuActionHelper->setDockWidgetTitleBarsEnabled(enabled); - QSettings settings; - settings.beginGroup("QGC_MAINWINDOW"); - settings.setValue("DOCK_WIDGET_TITLEBARS",enabled); - settings.endGroup(); -} void MainWindow::enableAutoReconnect(bool enabled) { @@ -1068,42 +902,42 @@ void MainWindow::connectCommonActions() #endif // Mark the right one as selected - if (currentView == VIEW_ENGINEER) + if (_currentView == VIEW_ENGINEER) { ui.actionEngineersView->setChecked(true); ui.actionEngineersView->activate(QAction::Trigger); } - if (currentView == VIEW_FLIGHT) + if (_currentView == VIEW_FLIGHT) { ui.actionFlightView->setChecked(true); ui.actionFlightView->activate(QAction::Trigger); } - if (currentView == VIEW_SIMULATION) + if (_currentView == VIEW_SIMULATION) { ui.actionSimulationView->setChecked(true); ui.actionSimulationView->activate(QAction::Trigger); } - if (currentView == VIEW_MISSION) + if (_currentView == VIEW_MISSION) { ui.actionMissionView->setChecked(true); ui.actionMissionView->activate(QAction::Trigger); } - if (currentView == VIEW_SETUP) + if (_currentView == VIEW_SETUP) { ui.actionSetup->setChecked(true); ui.actionSetup->activate(QAction::Trigger); } - if (currentView == VIEW_TERMINAL) + if (_currentView == VIEW_TERMINAL) { ui.actionTerminalView->setChecked(true); ui.actionTerminalView->activate(QAction::Trigger); } - if (currentView == VIEW_GOOGLEEARTH) + if (_currentView == VIEW_GOOGLEEARTH) { ui.actionGoogleEarthView->setChecked(true); ui.actionGoogleEarthView->activate(QAction::Trigger); } - if (currentView == VIEW_LOCAL3D) + if (_currentView == VIEW_LOCAL3D) { ui.actionLocal3DView->setChecked(true); ui.actionLocal3DView->activate(QAction::Trigger); @@ -1118,8 +952,6 @@ void MainWindow::connectCommonActions() // Connect actions from ui connect(ui.actionAdd_Link, SIGNAL(triggered()), this, SLOT(addLink())); - ui.actionAdvanced_Mode->setChecked(menuActionHelper->isAdvancedMode()); - connect(ui.actionAdvanced_Mode,SIGNAL(toggled(bool)),this,SLOT(setAdvancedMode(bool))); // Connect internal actions connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(UASCreated(UASInterface*))); @@ -1148,8 +980,8 @@ void MainWindow::connectCommonActions() connect(ui.actionProject_Roadmap, SIGNAL(triggered()), this, SLOT(showRoadMap())); // Custom widget actions - connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget())); - connect(ui.actionLoadCustomWidgetFile, SIGNAL(triggered()), this, SLOT(loadCustomWidget())); + connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(_createNewCustomWidget())); + connect(ui.actionLoadCustomWidgetFile, SIGNAL(triggered()), this, SLOT(_loadCustomWidgetFromFile())); // Audio output ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted()); @@ -1299,8 +1131,7 @@ void MainWindow::setActiveUAS(UASInterface* uas) Q_UNUSED(uas); if (settings.contains(getWindowStateKey())) { - SubMainWindow *win = qobject_cast(centerStack->currentWidget()); - win->restoreState(settings.value(getWindowStateKey()).toByteArray()); + restoreState(settings.value(getWindowStateKey()).toByteArray()); } } @@ -1313,10 +1144,6 @@ void MainWindow::UASSpecsChanged(int uas) void MainWindow::UASCreated(UASInterface* uas) { - // The pilot, operator and engineer views were not available on startup, enable them now - ui.actionFlightView->setEnabled(true); - ui.actionMissionView->setEnabled(true); - ui.actionEngineersView->setEnabled(true); // The UAS actions are not enabled without connection to system ui.actionLiftoff->setEnabled(true); ui.actionLand->setEnabled(true); @@ -1387,31 +1214,27 @@ void MainWindow::UASCreated(UASInterface* uas) break; } - connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int))); connect(uas, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64))); connect(uas, SIGNAL(misconfigurationDetected(UASInterface*)), this, SLOT(handleMisconfiguration(UASInterface*))); // HIL - showHILConfigurationWidget(uas); + _showHILConfigurationWidgets(); if (!linechartWidget) { linechartWidget = new Linecharts(this); + linechartWidget->setVisible(false); } linechartWidget->addSource(mavlinkDecoder); - if (engineeringView->centralWidget() != linechartWidget) + if (_engineeringView != linechartWidget) { - engineeringView->setCentralWidget(linechartWidget); - linechartWidget->show(); + _engineeringView = linechartWidget; } - // Load default custom widgets for this autopilot type - loadCustomWidgetsFromDefaults(uas->getSystemTypeName(), uas->getAutopilotTypeName()); - // Reload view state in case new widgets were added - loadViewState(); + _loadCurrentViewState(); } void MainWindow::UASDeleted(UASInterface* uas) @@ -1420,104 +1243,146 @@ void MainWindow::UASDeleted(UASInterface* uas) // TODO: Update the UI when a UAS is deleted } -/** - * Stores the current view state - */ -void MainWindow::storeViewState() +/// Stores the state of the toolbar, status bar and widgets associated with the current view +void MainWindow::_storeCurrentViewState(void) { - // Save current state - SubMainWindow *win = qobject_cast(centerStack->currentWidget()); - QList widgets = win->findChildren(); - QString widgetnames = ""; - for (int i=0;iobjectName() + ","; + // HIL dock widgets are dynamic and are not part of the saved state + _hideAllHilDockWidgets(); + + // Save list of visible widgets + + bool firstWidget = true; + QString widgetNames = ""; + foreach(QDockWidget* dockWidget, _mapName2DockWidget) { + if (dockWidget->isVisible()) { + if (!firstWidget) { + widgetNames += ","; + } + widgetNames += dockWidget->objectName(); + firstWidget = false; + } } - widgetnames = widgetnames.mid(0,widgetnames.length()-1); - - settings.setValue(getWindowStateKey() + "WIDGETS",widgetnames); - settings.setValue(getWindowStateKey(), win->saveState()); - settings.setValue(getWindowStateKey()+"CENTER_WIDGET", centerStack->currentIndex()); - // Although we want save the state of the window, we do not want to change the top-leve state (minimized, maximized, etc) - // therefore this state is stored here and restored after applying the rest of the settings in the new - // perspective. - windowStateVal = this->windowState(); + + settings.setValue(getWindowStateKey() + "WIDGETS", widgetNames); + settings.setValue(getWindowStateKey(), saveState()); settings.setValue(getWindowGeometryKey(), saveGeometry()); } -void MainWindow::loadViewState() +/// Restores the state of the toolbar, status bar and widgets associated with the current view +void MainWindow::_loadCurrentViewState(void) { - // Restore center stack state - int index = settings.value(getWindowStateKey()+"CENTER_WIDGET", -1).toInt(); - - if (index != -1) - { - centerStack->setCurrentIndex(index); - } - else - { - // Hide custom widgets - if (detectionDockWidget) detectionDockWidget->hide(); - if (watchdogControlDockWidget) watchdogControlDockWidget->hide(); - - // Load defaults - switch (currentView) - { + QWidget* centerView = NULL; + QString defaultWidgets; + + switch (_currentView) { case VIEW_SETUP: - centerStack->setCurrentWidget(setupView); + _buildSetupView(); + centerView = _setupView; break; + case VIEW_ENGINEER: - centerStack->setCurrentWidget(engineeringView); + _buildEngineeringView(); + centerView = _engineeringView; + defaultWidgets = "MAVLINK_INSPECTOR_DOCKWIDGET,PARAMETER_INTERFACE_DOCKWIDGET,FILE_VIEW_DOCKWIDGET,HEAD_UP_DISPLAY_DOCKWIDGET"; break; - default: // Default to the flight view + case VIEW_FLIGHT: - centerStack->setCurrentWidget(pilotView); + _buildPilotView(); + centerView = _pilotView; + defaultWidgets = "COMMUNICATION_CONSOLE_DOCKWIDGET,UAS_INFO_INFOVIEW_DOCKWIDGET"; break; + case VIEW_MISSION: - centerStack->setCurrentWidget(plannerView); + _buildPlannerView(); + centerView = _plannerView; + defaultWidgets = "UNMANNED_SYSTEM_LIST_DOCKWIDGET,WAYPOINT_LIST_DOCKWIDGET"; break; + case VIEW_SIMULATION: - centerStack->setCurrentWidget(simView); + _buildSimView(); + centerView = _simView; + defaultWidgets = "UNMANNED_SYSTEM_CONTROL_DOCKWIDGET,WAYPOINT_LIST_DOCKWIDGET,PARAMETER_INTERFACE_DOCKWIDGET,PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET"; break; + case VIEW_TERMINAL: - centerStack->setCurrentWidget(terminalView); + _buildTerminalView(); + centerView = _terminalView; break; + case VIEW_GOOGLEEARTH: - centerStack->setCurrentWidget(googleEarthView); + _buildGoogleEarthView(); + centerView = _googleEarthView; break; + case VIEW_LOCAL3D: - centerStack->setCurrentWidget(local3DView); + _buildLocal3DView(); + centerView = _local3DView; break; + } + + // Remove old view + if (_currentViewWidget) { + _currentViewWidget->setVisible(false); + Q_ASSERT(_centralLayout->count() == 1); + QLayoutItem *child = _centralLayout->takeAt(0); + Q_ASSERT(child); + delete child; + } + + // Add the new one + Q_ASSERT(centerView); + Q_ASSERT(_centralLayout->count() == 0); + _currentViewWidget = centerView; + _centralLayout->addWidget(_currentViewWidget); + _currentViewWidget->setVisible(true); + + // Hide all widgets from previous view + _hideAllDockWidgets(); + + // Restore the widgets for the new view + QString widgetNames = settings.value(getWindowStateKey() + "WIDGETS", defaultWidgets).toString(); + if (!widgetNames.isEmpty()) { + QStringList split = widgetNames.split(","); + foreach (QString widgetName, split) { + Q_ASSERT(!widgetName.isEmpty()); + _showDockWidget(widgetName, true); } } - // Restore the widget positions and size - if (settings.contains(getWindowStateKey() + "WIDGETS")) - { - QString widgetstr = settings.value(getWindowStateKey() + "WIDGETS").toString(); - QStringList split = widgetstr.split(","); - foreach (QString widgetname,split) - { - if (widgetname != "") - { - //qDebug() << "Loading widget:" << widgetname; - loadDockWidget(widgetname); - } - } + if (settings.contains(getWindowStateKey())) { + restoreState(settings.value(getWindowStateKey()).toByteArray()); } - if (settings.contains(getWindowStateKey())) - { - SubMainWindow *win = qobject_cast(centerStack->currentWidget()); - win->restoreState(settings.value(getWindowStateKey()).toByteArray()); + + // HIL dock widget are dynamic and don't take part in the saved window state, so this + // need to happen after we restore state + _showHILConfigurationWidgets(); +} + +void MainWindow::_hideAllHilDockWidgets(void) +{ + foreach(QDockWidget* dockWidget, _mapUasId2HilDockWidget) { + dockWidget->setVisible(false); + } +} + +void MainWindow::_hideAllDockWidgets(void) +{ + foreach(QDockWidget* dockWidget, _mapName2DockWidget) { + dockWidget->setVisible(false); } + + _hideAllHilDockWidgets(); } -void MainWindow::setAdvancedMode(bool isAdvancedMode) + +void MainWindow::_showDockWidgetAction(bool show) { - menuActionHelper->setAdvancedMode(isAdvancedMode); - ui.actionAdvanced_Mode->setChecked(isAdvancedMode); - settings.setValue("ADVANCED_MODE",isAdvancedMode); + QAction* action = dynamic_cast(QObject::sender()); + Q_ASSERT(action); + + _showDockWidget(action->data().toString(), show); } + void MainWindow::handleMisconfiguration(UASInterface* uas) { static QTime lastTime; @@ -1548,88 +1413,88 @@ void MainWindow::handleMisconfiguration(UASInterface* uas) void MainWindow::loadEngineerView() { - if (currentView != VIEW_ENGINEER) + if (_currentView != VIEW_ENGINEER) { - storeViewState(); - currentView = VIEW_ENGINEER; + _storeCurrentViewState(); + _currentView = VIEW_ENGINEER; ui.actionEngineersView->setChecked(true); - loadViewState(); + _loadCurrentViewState(); } } void MainWindow::loadOperatorView() { - if (currentView != VIEW_MISSION) + if (_currentView != VIEW_MISSION) { - storeViewState(); - currentView = VIEW_MISSION; + _storeCurrentViewState(); + _currentView = VIEW_MISSION; ui.actionMissionView->setChecked(true); - loadViewState(); + _loadCurrentViewState(); } } void MainWindow::loadSetupView() { - if (currentView != VIEW_SETUP) + if (_currentView != VIEW_SETUP) { - storeViewState(); - currentView = VIEW_SETUP; + _storeCurrentViewState(); + _currentView = VIEW_SETUP; ui.actionSetup->setChecked(true); - loadViewState(); + _loadCurrentViewState(); } } void MainWindow::loadTerminalView() { - if (currentView != VIEW_TERMINAL) + if (_currentView != VIEW_TERMINAL) { - storeViewState(); - currentView = VIEW_TERMINAL; + _storeCurrentViewState(); + _currentView = VIEW_TERMINAL; ui.actionTerminalView->setChecked(true); - loadViewState(); + _loadCurrentViewState(); } } void MainWindow::loadGoogleEarthView() { - if (currentView != VIEW_GOOGLEEARTH) + if (_currentView != VIEW_GOOGLEEARTH) { - storeViewState(); - currentView = VIEW_GOOGLEEARTH; + _storeCurrentViewState(); + _currentView = VIEW_GOOGLEEARTH; ui.actionGoogleEarthView->setChecked(true); - loadViewState(); + _loadCurrentViewState(); } } void MainWindow::loadLocal3DView() { - if (currentView != VIEW_LOCAL3D) + if (_currentView != VIEW_LOCAL3D) { - storeViewState(); - currentView = VIEW_LOCAL3D; + _storeCurrentViewState(); + _currentView = VIEW_LOCAL3D; ui.actionLocal3DView->setChecked(true); - loadViewState(); + _loadCurrentViewState(); } } void MainWindow::loadPilotView() { - if (currentView != VIEW_FLIGHT) + if (_currentView != VIEW_FLIGHT) { - storeViewState(); - currentView = VIEW_FLIGHT; + _storeCurrentViewState(); + _currentView = VIEW_FLIGHT; ui.actionFlightView->setChecked(true); - loadViewState(); + _loadCurrentViewState(); } } void MainWindow::loadSimulationView() { - if (currentView != VIEW_SIMULATION) + if (_currentView != VIEW_SIMULATION) { - storeViewState(); - currentView = VIEW_SIMULATION; + _storeCurrentViewState(); + _currentView = VIEW_SIMULATION; ui.actionSimulationView->setChecked(true); - loadViewState(); + _loadCurrentViewState(); } } @@ -1638,11 +1503,6 @@ QList MainWindow::listLinkMenuActions() return ui.menuNetwork->actions(); } -bool MainWindow::dockWidgetTitleBarsEnabled() const -{ - return menuActionHelper->dockWidgetTitleBarsEnabled(); -} - /// @brief Hides the spash screen if it is currently being shown void MainWindow::hideSplashScreen(void) { diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index e11b30065109bdf84dfb52c096a729a1fa91a3bb..b10ea3fa24552b4a9a97d995033e6bcdfc52f253 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -47,7 +47,6 @@ This file is part of the QGROUNDCONTROL project #include "CameraView.h" #include "UASListWidget.h" #include "MAVLinkSimulationLink.h" -#include "submainwindow.h" #include "input/JoystickInput.h" #if (defined QGC_MOUSE_ENABLED_WIN) | (defined QGC_MOUSE_ENABLED_LINUX) #include "Mouse6dofInput.h" @@ -68,6 +67,7 @@ This file is part of the QGROUNDCONTROL project #include "MAVLinkDecoder.h" #include "QGCUASFileViewMulti.h" #include "QGCFlightGearLink.h" +#include "QGCToolWidget.h" class QGCMapTool; class QGCMAVLinkMessageSender; @@ -110,9 +110,6 @@ public: return autoReconnect; } - /** @brief Get title bar mode setting */ - bool dockWidgetTitleBarsEnabled() const; - /** @brief Get low power mode setting */ bool lowPowerModeEnabled() const { @@ -144,8 +141,6 @@ public slots: void stopVideoCapture(); void saveScreen(); - /** @brief Sets advanced mode, allowing for editing of tool widget locations */ - void setAdvancedMode(bool isAdvancedMode); void handleMisconfiguration(UASInterface* uas); /** @brief Load configuration views */ void loadSetupView(); @@ -171,48 +166,20 @@ public slots: /** @brief Show the project roadmap */ void showRoadMap(); - /** @breif Enable title bars on dock widgets when no in advanced mode */ - void enableDockWidgetTitleBars(bool enabled); /** @brief Automatically reconnect last link */ void enableAutoReconnect(bool enabled); /** @brief Save power by reducing update rates */ void enableLowPowerMode(bool enabled) { lowPowerMode = enabled; } - /** @brief Add a custom tool widget */ - void createCustomWidget(); - - /** @brief Load a custom tool widget from a file chosen by user (QGCFileDialog) */ - void loadCustomWidget(); - - /** @brief Load a custom tool widget from a file */ - void loadCustomWidget(const QString& fileName, bool singleinstance=false); - void loadCustomWidget(const QString& fileName, int view); - - /** @brief Load custom widgets from default file */ - void loadCustomWidgetsFromDefaults(const QString& systemType, const QString& autopilotType); - - /** @brief Loads and shows the HIL Configuration Widget for the given UAS*/ - void showHILConfigurationWidget(UASInterface *uas); - void closeEvent(QCloseEvent* event); - /** - * @brief Shows a Widget from the center stack based on the action sender - * - * This slot is written to be used in conjunction with the addCentralWidget() function - * It shows the Widget based on the action sender - * - */ - void showCentralWidget(); - /** @brief Update the window name */ void configureWindowName(); void commsWidgetDestroyed(QObject *obj); protected slots: - void showDockWidget(const QString &name, bool show); /** * @brief Unchecks the normalActionItem. * Used as a triggered() callback by the fullScreenAction to make sure only one of it or the @@ -250,54 +217,15 @@ protected: VIEW_MISSION, // Mission/Map/Plan view mode. Used for setting mission waypoints and high-level system commands. VIEW_FLIGHT, // Flight/Fly/Operate view mode. Used for 1st-person observation of the vehicle. VIEW_SIMULATION, // HIL Simulation view. Useful overview of the entire system when doing hardware-in-the-loop simulations. - UNUSED1, // Unused spacer for backwards compatibility with older settings files. VIEW_SETUP, // Setup view. Used for initializing the system for operation. Includes UI for calibration, firmware updating/checking, and parameter modifcation. - UNUSED2, // Unused spacer for backwards compatibility with older settings files. VIEW_TERMINAL, // Terminal interface. Used for communicating with the remote system, usually in a special configuration input mode. VIEW_LOCAL3D, // A local 3D view. Provides a local 3D view that makes visualizing 3D attitude/orientation/pose easy while in operation. VIEW_GOOGLEEARTH // 3D Google Earth view. A 3D terrain view, though the vehicle is still 2D. } VIEW_SECTIONS; - /** - * @brief Adds an already instantiated QDockedWidget to the Tools Menu - * - * This function does all the hosekeeping to have a QDockedWidget added to the - * tools menu and connects the QMenuAction to a slot that shows the widget and - * checks/unchecks the tools menu item - * - * @param widget The QDockWidget being added - * @param title The entry that will appear in the Menu and in the QDockedWidget title bar - * @param location The default location for the QDockedWidget in case there is no previous key in the settings - */ - void addTool(SubMainWindow *parent,VIEW_SECTIONS view,QDockWidget* widget, const QString& title, Qt::DockWidgetArea area); - void loadDockWidget(const QString &name); - - QDockWidget* createDockWidget(QWidget *subMainWindowParent,QWidget *child,const QString& title,const QString& objectname,VIEW_SECTIONS view,Qt::DockWidgetArea area,const QSize& minSize = QSize()); - /** - * @brief Adds an already instantiated QWidget to the center stack - * - * This function does all the hosekeeping to have a QWidget added to the tools menu - * tools menu and connects the QMenuAction to a slot that shows the widget and - * checks/unchecks the tools menu item. This is used for all the central widgets (those in - * the center stack. - * - * @param widget The QWidget being added - * @param title The entry that will appear in the Menu - */ - void addToCentralStackedWidget(QWidget* widget, VIEW_SECTIONS viewSection, const QString& title); - /** @brief Catch window resize events */ void resizeEvent(QResizeEvent * event); - /** @brief Keeps track of the current view */ - VIEW_SECTIONS currentView; - - void storeViewState(); - void loadViewState(); - - void buildCustomWidget(); - void buildCommonWidgets(); - void connectCommonWidgets(); void connectCommonActions(); void loadSettings(); @@ -307,20 +235,8 @@ protected: LinkInterface* udpLink; QSettings settings; - QStackedWidget *centerStack; QActionGroup* centerStackActionGroup; - // Center widgets - QPointer plannerView; - QPointer pilotView; - QPointer setupView; - QPointer softwareConfigView; - QPointer engineeringView; - QPointer simView; - QPointer terminalView; - QPointer googleEarthView; - QPointer local3DView; - // Center widgets QPointer linechartWidget; #ifdef QGC_OSG_ENABLED @@ -331,38 +247,12 @@ protected: #endif QPointer firmwareUpdateWidget; - // Dock widgets - QPointer controlDockWidget; - QPointer controlParameterWidget; - QPointer infoDockWidget; - QPointer cameraDockWidget; - QPointer listDockWidget; - QPointer waypointsDockWidget; - QPointer detectionDockWidget; - QPointer debugConsoleDockWidget; - QPointer parametersDockWidget; - QPointer headDown1DockWidget; - QPointer headDown2DockWidget; - QPointer watchdogControlDockWidget; - - QPointer headUpDockWidget; - QPointer video1DockWidget; - QPointer video2DockWidget; - QPointer rgbd1DockWidget; - QPointer rgbd2DockWidget; - QPointer logPlayerDockWidget; - - QPointer hsiDockWidget; - QPointer rcViewDockWidget; - QPointer hudDockWidget; - QPointer toolBar; QPointer mavlinkInspectorWidget; QPointer mavlinkDecoder; QPointer mavlinkSenderWidget; QGCMAVLinkLogPlayer* logPlayer; - QMap hilDocks; QPointer fileWidget; @@ -395,13 +285,15 @@ protected: QTimer* videoTimer; bool autoReconnect; MAVLinkSimulationLink* simulationLink; - Qt::WindowStates windowStateVal; bool lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets QGCFlightGearLink* fgLink; QTimer windowNameUpdateTimer; private slots: void _addLinkMenu(LinkInterface* link); + void _showDockWidgetAction(bool show); + void _loadCustomWidgetFromFile(void); + void _createNewCustomWidget(void); private: /// Constructor is private since all creation should be through MainWindow::_create @@ -409,16 +301,69 @@ private: void _openUrl(const QString& url, const QString& errorMessage); + // Center widgets + QPointer _plannerView; + QPointer _pilotView; + QPointer _setupView; + QPointer _engineeringView; + QPointer _simView; + QPointer _terminalView; + QPointer _googleEarthView; + QPointer _local3DView; + + VIEW_SECTIONS _currentView; ///< Currently displayed view + QWidget* _currentViewWidget; ///< Currently displayed view widget + + // Dock widget names + static const char* _uasControlDockWidgetName; + static const char* _uasListDockWidgetName; + static const char* _waypointsDockWidgetName; + static const char* _mavlinkDockWidgetName; + static const char* _parametersDockWidgetName; + static const char* _filesDockWidgetName; + static const char* _uasStatusDetailsDockWidgetName; + static const char* _mapViewDockWidgetName; + static const char* _hsiDockWidgetName; + static const char* _hdd1DockWidgetName; + static const char* _hdd2DockWidgetName; + static const char* _pfdDockWidgetName; + static const char* _hudDockWidgetName; + static const char* _uasInfoViewDockWidgetName; + static const char* _debugConsoleDockWidgetName; + + QMap _mapName2DockWidget; + QMap _mapUasId2HilDockWidget; + QMap _mapDockWidget2Action; + + void _buildPlannerView(void); + void _buildPilotView(void); + void _buildSetupView(void); + void _buildEngineeringView(void); + void _buildSimView(void); + void _buildTerminalView(void); + void _buildGoogleEarthView(void); + void _buildLocal3DView(void); + + void _storeCurrentViewState(void); + void _loadCurrentViewState(void); + + void _createDockWidget(const QString& title, const QString& name, Qt::DockWidgetArea area, QWidget* innerWidget); + void _createInnerDockWidget(const QString& widgetName); + void _buildCustomWidgets(void); + void _buildCommonWidgets(void); + void _hideAllHilDockWidgets(void); + void _hideAllDockWidgets(void); + void _showDockWidget(const QString &name, bool show); + void _showHILConfigurationWidgets(void); + + QList _customWidgets; + + QVBoxLayout* _centralLayout; + QList commsWidgetList; - QMap customWidgetNameToFilenameMap; MenuActionHelper *menuActionHelper; Ui::MainWindow ui; - /** @brief Set the appropriate titlebar for a given dock widget. - * Relies on the isAdvancedMode and dockWidgetTitleBarEnabled member variables. - */ - void setDockWidgetTitleBar(QDockWidget* widget); - QString getWindowStateKey(); QString getWindowGeometryKey(); diff --git a/src/ui/MainWindow.ui b/src/ui/MainWindow.ui index 4be510fc5022d69faed3e882ec17b4f59e6b6d5d..3435f990cd78d7fcaba42b19093583944f2f9566 100644 --- a/src/ui/MainWindow.ui +++ b/src/ui/MainWindow.ui @@ -62,7 +62,6 @@ - diff --git a/src/ui/QGCBaseParamWidget.cc b/src/ui/QGCBaseParamWidget.cc index 2b89db964b0782f09836246b645813fa4aa2373a..76c4f2abb949d2162695d671e766c20f4aa7e316 100644 --- a/src/ui/QGCBaseParamWidget.cc +++ b/src/ui/QGCBaseParamWidget.cc @@ -105,17 +105,11 @@ void QGCBaseParamWidget::saveParametersToFile() { if (!mav) return; - QString defaultSuffix("params"); QString fileName = QGCFileDialog::getSaveFileName( - this, - tr("Save Parameters"), - qgcApp()->savedParameterFilesLocation(), - tr("Parameter File (*.params)"), - 0, 0, - &defaultSuffix, - true); + this, tr("Save Parameters"), qgcApp()->savedParameterFilesLocation(), tr("Parameter File (*.params)"), "params", true); if (!fileName.isEmpty()) { QFile file(fileName); + // TODO Display error message to the user if the file can't be created if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { return; } @@ -130,15 +124,15 @@ void QGCBaseParamWidget::loadParametersFromFile() { if (!mav) return; - - QString fileName = QGCFileDialog::getOpenFileName(this, tr("Load File"), qgcApp()->savedParameterFilesLocation(), tr("Parameter file (*.params)")); + QString fileName = QGCFileDialog::getOpenFileName( + this, tr("Load Parameters"), qgcApp()->savedParameterFilesLocation(), + tr("Parameter file (*.params);;All Files (*)")); QFile file(fileName); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + // TODO Display error message to the user if the file can't be opened + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { return; - + } QTextStream in(&file); paramMgr->readPendingParamsFromStream(in); file.close(); } - - diff --git a/src/ui/QGCDataPlot2D.cc b/src/ui/QGCDataPlot2D.cc index 952fa0e0d7c99ec50e217ffd79ee992d2b7823d1..f443eef7dcb606c7b1fa170b1518d360579370b2 100644 --- a/src/ui/QGCDataPlot2D.cc +++ b/src/ui/QGCDataPlot2D.cc @@ -100,13 +100,17 @@ void QGCDataPlot2D::loadFile() void QGCDataPlot2D::loadFile(QString file) { + // TODO This "filename" is a private/protected member variable. It should be named in such way + // it indicates so. This same name is used in several places within this file in local scopes. fileName = file; - if (QFileInfo(fileName).isReadable()) { - if (fileName.contains(".raw") || fileName.contains(".imu")) { + QFileInfo fi(fileName); + if (fi.isReadable()) { + if (fi.suffix() == QString("raw") || fi.suffix() == QString("imu")) { loadRawLog(fileName); - } else if (fileName.contains(".txt") || fileName.contains(".csv") || fileName.contains(".csv")) { + } else if (fi.suffix() == QString("txt") || fi.suffix() == QString("csv")) { loadCsvLog(fileName); } + // TODO Else, tell the user it doesn't know what to do with the file... } } @@ -115,12 +119,10 @@ void QGCDataPlot2D::loadFile(QString file) */ QString QGCDataPlot2D::getSavePlotFilename() { - QString defaultSuffix("pdf"); QString fileName = QGCFileDialog::getSaveFileName( - this, "Export File Name", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), + this, "Save Plot File", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), "PDF Documents (*.pdf);;SVG Images (*.svg)", - 0,0, - &defaultSuffix); + "pdf"); return fileName; } @@ -133,11 +135,13 @@ void QGCDataPlot2D::savePlot() if (fileName.isEmpty()) return; + // TODO This will change once we add "strict" file types in file selection dialogs while(!(fileName.endsWith(".svg") || fileName.endsWith(".pdf"))) { - QMessageBox::StandardButton button = QGCMessageBox::critical(tr("Unsuitable file extension for PDF or SVG"), - tr("Please choose .pdf or .svg as file extension. Click OK to change the file extension, cancel to not save the file."), - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Ok); + QMessageBox::StandardButton button = QGCMessageBox::warning( + tr("Unsuitable file extension for Plot document type."), + tr("Please choose .pdf or .svg as file extension. Click OK to change the file extension, cancel to not save the file."), + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Ok); // Abort if cancelled if (button == QMessageBox::Cancel) { return; @@ -264,16 +268,16 @@ void QGCDataPlot2D::selectFile() // Open a file dialog prompting the user for the file to load. // Note the special case for the Pixhawk. if (ui->inputFileType->currentText().contains("pxIMU") || ui->inputFileType->currentText().contains("RAW")) { - fileName = QGCFileDialog::getOpenFileName(this, tr("Specify log file name"), QString(), "Logfile (*.imu *.raw)"); + fileName = QGCFileDialog::getOpenFileName(this, tr("Load Log File"), QString(), "Log files (*.imu *.raw)"); } else { - fileName = QGCFileDialog::getOpenFileName(this, tr("Specify log file name"), QString(), "Logfile (*.csv *.txt *.log)"); + fileName = QGCFileDialog::getOpenFileName(this, tr("Load Log File"), QString(), "Log files (*.csv *.txt *.log)"); } - // Check if the user hit cancel, which results in a Null string. + // Check if the user hit cancel, which results in an empty string. // If this is the case, we just stop. - if (fileName.isNull()) + if (fileName.isEmpty()) { return; } @@ -282,9 +286,11 @@ void QGCDataPlot2D::selectFile() QFileInfo fileInfo(fileName); if (!fileInfo.isReadable()) { - QGCMessageBox::critical(tr("Could not open file"), - tr("The file is owned by user %1. Is the file currently used by another program?").arg(fileInfo.owner())); - ui->filenameLabel->setText(tr("Could not open %1").arg(fileInfo.baseName()+"."+fileInfo.completeSuffix())); + // TODO This needs some TLC. File used by another program sounds like a Windows only issue. + QGCMessageBox::critical( + tr("Could not open file"), + tr("The file is owned by user %1. Is the file currently used by another program?").arg(fileInfo.owner())); + ui->filenameLabel->setText(tr("Could not open %1").arg(fileInfo.fileName())); } else { @@ -690,12 +696,10 @@ bool QGCDataPlot2D::linearRegression(double *x, double *y, int n, double *a, dou void QGCDataPlot2D::saveCsvLog() { - QString defaultSuffix("csv"); QString fileName = QGCFileDialog::getSaveFileName( - this, "Export CSV File Name", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), + this, "Save CSV Log File", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), "CSV file (*.csv);;Text file (*.txt)", - 0,0, - &defaultSuffix); + "csv"); if (fileName.isEmpty()) return; //User cancelled diff --git a/src/ui/QGCMAVLinkLogPlayer.cc b/src/ui/QGCMAVLinkLogPlayer.cc index f26ee69507f1598a66694295b45083c77fbc7fb7..39a29601dfa76c6dbab8a19dbf512ed9e3068037 100644 --- a/src/ui/QGCMAVLinkLogPlayer.cc +++ b/src/ui/QGCMAVLinkLogPlayer.cc @@ -262,11 +262,12 @@ void QGCMAVLinkLogPlayer::_selectLogFileForPlayback(void) return; } - QString logFile = QGCFileDialog::getOpenFileName(this, - tr("Specify MAVLink log file name to replay"), - qgcApp()->mavlinkLogFilesLocation(), - tr("MAVLink or Binary Logfile (*.mavlink *.bin *.log)")); - + QString logFile = QGCFileDialog::getOpenFileName( + this, + tr("Load MAVLink Log File"), + qgcApp()->mavlinkLogFilesLocation(), + tr("MAVLink or Binary Logfile (*.mavlink *.bin *.log);;All Files (*)")); + if (!logFile.isEmpty()) { loadLogFile(logFile); } diff --git a/src/ui/QGCUASFileView.ui b/src/ui/QGCUASFileView.ui index b7e4ce7fc884a5ca0f202225c9bbd3a54bb722a9..1ac6fd1193665f425d4a64f19b73a2ab6a63905d 100644 --- a/src/ui/QGCUASFileView.ui +++ b/src/ui/QGCUASFileView.ui @@ -6,7 +6,7 @@ 0 0 - 414 + 200 518 diff --git a/src/ui/QGCUASFileViewMulti.ui b/src/ui/QGCUASFileViewMulti.ui index 169c00a1f0deca2ace6100bafbb792e8e8a24924..547cfd4dbfc7bcd2804f80084d9ad76823175837 100644 --- a/src/ui/QGCUASFileViewMulti.ui +++ b/src/ui/QGCUASFileViewMulti.ui @@ -6,7 +6,7 @@ 0 0 - 400 + 200 300 diff --git a/src/ui/SettingsDialog.cc b/src/ui/SettingsDialog.cc index baddd51e4fec9f531a163a23776e80b9e876f85a..194bb90396409e962fc31adbe4bfe0793d3b9d0b 100644 --- a/src/ui/SettingsDialog.cc +++ b/src/ui/SettingsDialog.cc @@ -70,10 +70,6 @@ _ui(new Ui::SettingsDialog) _ui->lowPowerCheckBox->setChecked(_mainWindow->lowPowerModeEnabled()); connect(_ui->lowPowerCheckBox, SIGNAL(clicked(bool)), _mainWindow, SLOT(enableLowPowerMode(bool))); - // Dock widget title bars - _ui->titleBarCheckBox->setChecked(_mainWindow->dockWidgetTitleBarsEnabled()); - connect(_ui->titleBarCheckBox,SIGNAL(clicked(bool)),_mainWindow,SLOT(enableDockWidgetTitleBars(bool))); - connect(_ui->deleteSettings, &QAbstractButton::toggled, this, &SettingsDialog::_deleteSettingsToggled); // Application color style diff --git a/src/ui/SettingsDialog.ui b/src/ui/SettingsDialog.ui index 0aa80a3d5139b9aad1449d2478ade248f2fa603c..fef27225338f142fe1a6fb06c4745e9ec15dfdcd 100644 --- a/src/ui/SettingsDialog.ui +++ b/src/ui/SettingsDialog.ui @@ -62,16 +62,6 @@ - - - - Show Docked Widget title bars when NOT in advanced Mode. - - - false - - - diff --git a/src/ui/WaypointList.cc b/src/ui/WaypointList.cc index f962a696fb4bf22badb8fde4b77f11810153e655..8632ecc580a50182812f21aa017b5d2b49b80bb0 100644 --- a/src/ui/WaypointList.cc +++ b/src/ui/WaypointList.cc @@ -217,14 +217,15 @@ void WaypointList::setUAS(UASInterface* uas) void WaypointList::saveWaypoints() { - QString defaultSuffix("waypoints"); - QString fileName = QGCFileDialog::getSaveFileName(this, tr("Save File"), "./unnamed.waypoints", tr("Waypoint File (*.waypoints)"), 0, 0, &defaultSuffix); + // TODO Need better default directory + QString fileName = QGCFileDialog::getSaveFileName(this, tr("Save Waypoint File"), "./untitled.waypoints", tr("Waypoint File (*.waypoints)"), "waypoints", true); WPM->saveWaypoints(fileName); } void WaypointList::loadWaypoints() { - QString fileName = QGCFileDialog::getOpenFileName(this, tr("Load File"), ".", tr("Waypoint File (*.waypoints)")); + // TODO Need better default directory + QString fileName = QGCFileDialog::getOpenFileName(this, tr("Load Waypoint File"), ".", tr("Waypoint File (*.waypoints);;All Files (*)")); WPM->loadWaypoints(fileName); } diff --git a/src/ui/designer/QGCToolWidget.cc b/src/ui/designer/QGCToolWidget.cc index 7cc942ec3c45da5695eeaa5a7d2cfe78adcdcb8a..d81a20f78a7814d1c6754d8d3817858ff04df699 100644 --- a/src/ui/designer/QGCToolWidget.cc +++ b/src/ui/designer/QGCToolWidget.cc @@ -571,29 +571,29 @@ void QGCToolWidget::widgetRemoved() void QGCToolWidget::exportWidget() { - QString defaultSuffix("qgw"); - const QString widgetFileExtension(".qgw"); + //-- Get file to save QString fileName = QGCFileDialog::getSaveFileName( - this, tr("Specify File Name"), + this, tr("Save Widget File"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), - tr("QGroundControl Widget (*%1)").arg(widgetFileExtension), - 0,0, - &defaultSuffix, + tr("QGroundControl Widget (*.qgw)"), + "qgw", true); - //-- Note that if the user enters foo.bar, this will end up foo.bar.qgw - if (!fileName.endsWith(widgetFileExtension)) - { - fileName = fileName.append(widgetFileExtension); + //-- Save it if we have it + if (!fileName.isEmpty()) { + QSettings settings(fileName, QSettings::IniFormat); + storeSettings(settings); } - QSettings settings(fileName, QSettings::IniFormat); - storeSettings(settings); } void QGCToolWidget::importWidget() { - const QString widgetFileExtension(".qgw"); - QString fileName = QGCFileDialog::getOpenFileName(this, tr("Specify File Name"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr("QGroundControl Widget (*%1)").arg(widgetFileExtension)); - loadSettings(fileName); + QString fileName = QGCFileDialog::getOpenFileName( + this, tr("Load Widget File"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), + tr("QGroundControl Widget (*.qgw);;All Files (*)")); + if (!fileName.isEmpty()) { + // TODO There is no error checking. If the load fails, there is nothing telling the user what happened. + loadSettings(fileName); + } } QString QGCToolWidget::getTitle() const diff --git a/src/ui/linechart/LinechartWidget.cc b/src/ui/linechart/LinechartWidget.cc index 02a58875935ba45255dabfc48b0ee51b6466f190..372e284b539d0611590115cdb07ad33c365f0ed7 100644 --- a/src/ui/linechart/LinechartWidget.cc +++ b/src/ui/linechart/LinechartWidget.cc @@ -433,13 +433,11 @@ void LinechartWidget::refresh() QString LinechartWidget::getLogSaveFilename() { - QString defaultSuffix("log"); QString fileName = QGCFileDialog::getSaveFileName(this, - tr("Specify log file name"), + tr("Save Log File"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), - tr("Logfile (*.log)"), - 0,0, - &defaultSuffix, + tr("Log file (*.log)"), + "log", true); return fileName; } diff --git a/src/ui/map3D/Pixhawk3DWidget.cc b/src/ui/map3D/Pixhawk3DWidget.cc index 04e10702c148f02c4f72659946c96a5b5a5bb0ac..d62377c9e04cad9129c0635fa751abfcf60dc634 100644 --- a/src/ui/map3D/Pixhawk3DWidget.cc +++ b/src/ui/map3D/Pixhawk3DWidget.cc @@ -587,11 +587,12 @@ Pixhawk3DWidget::setBirdEyeView(void) void Pixhawk3DWidget::loadTerrainModel(void) { - QString filename = QGCFileDialog::getOpenFileName(this, "Load Terrain Model", - QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), - tr("Collada (*.dae)")); + QString filename = QGCFileDialog::getOpenFileName( + this, "Load Terrain Model", + QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), + tr("Collada (*.dae)")); - if (filename.isNull()) + if (filename.isEmpty()) { return; } diff --git a/src/ui/map3D/Q3DWidget.cc b/src/ui/map3D/Q3DWidget.cc index 82341f0b0161a5bafda5589f8ef86ff3c50a217e..2d2c9e173bb21f6183186a428884af1e92816aae 100644 --- a/src/ui/map3D/Q3DWidget.cc +++ b/src/ui/map3D/Q3DWidget.cc @@ -354,6 +354,7 @@ void Q3DWidget::redraw(void) { emit update(); + emit updateWidget(); #if (QGC_EVENTLOOP_DEBUG) qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__; #endif diff --git a/src/ui/menuactionhelper.cpp b/src/ui/menuactionhelper.cpp deleted file mode 100644 index cba136a8715a7c361619c1d1141159fffa266b94..0000000000000000000000000000000000000000 --- a/src/ui/menuactionhelper.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include "menuactionhelper.h" - -MenuActionHelper::MenuActionHelper(QObject *parent) : QObject(parent), - m_isAdvancedMode(false), - m_dockWidgetTitleBarsEnabled(true), - m_addedCustomSeperator(false) -{ -} - -QAction *MenuActionHelper::createToolAction(const QString &title, const QString &name) -{ - QAction *action = m_menuToDockNameMap.key(name); //For sanity, check that the action is not NULL - if(action) { - qWarning() << "createToolAction was called for action" << name << "which already exists in the menu"; - return action; - } - - action = new QAction(title, NULL); - action->setCheckable(true); - connect(action,SIGNAL(triggered(bool)),this,SLOT(showTool(bool))); - m_menuToDockNameMap[action] = name; - m_menu->addAction(action); - return action; -} - -void MenuActionHelper::removeDockWidget() -{ - // Do not dynamic cast or de-reference QObject, since object is either in destructor or may have already - // been destroyed. - - QObject *dockWidget = QObject::sender(); - Q_ASSERT(dockWidget); - - //qDebug() << "Dockwidget:" << dockWidget->objectName() << "of type" << dockWidget->metaObject()->className(); - - QAction *action = m_menuToDockNameMap.key(dockWidget->objectName()); - if(action) { - m_menuToDockNameMap.remove(action); - action->deleteLater(); - } - QMap >::iterator it; - for (it = m_centralWidgetToDockWidgetsMap.begin(); it != m_centralWidgetToDockWidgetsMap.end(); ++it) { - QMap::iterator it2 = it.value().begin(); - while( it2 != it.value().end()) { - if(it2.value() == dockWidget) - it2 = it.value().erase(it2); - else - ++it2; - } - } - //Don't delete the dockWidget because this could have been called from the dockWidget destructor - m_dockWidgets.removeAll(static_cast(dockWidget)); -} - -QAction *MenuActionHelper::createToolActionForCustomDockWidget(const QString &title, const QString& name, QDockWidget* dockWidget, MainWindow::VIEW_SECTIONS view) { - bool found = false; - QAction *action = NULL; - foreach(QAction *act, m_menuToDockNameMap.keys()) { - if(act->text() == title) { - found = true; - action = act; - } - } - - if(!found) - action = createToolAction(title, name); - else - m_menuToDockNameMap[action] = name; - - m_centralWidgetToDockWidgetsMap[view][name] = dockWidget; - connect(dockWidget, SIGNAL(destroyed()), SLOT(removeDockWidget()),Qt::UniqueConnection); //Use UniqueConnection since we might have already created this connection in createDockWidget - connect(dockWidget, SIGNAL(visibilityChanged(bool)), action, SLOT(setChecked(bool))); - action->setChecked(dockWidget->isVisible()); - return action; -} - -QDockWidget* MenuActionHelper::createDockWidget(const QString& title,const QString& name) -{ - QDockWidget *dockWidget = new QDockWidget(title); - m_dockWidgets.append(dockWidget); - setDockWidgetTitleBar(dockWidget); - dockWidget->setObjectName(name); - connect(dockWidget, SIGNAL(destroyed()), SLOT(removeDockWidget())); - - return dockWidget; -} - -bool MenuActionHelper::containsDockWidget(MainWindow::VIEW_SECTIONS view, const QString &name) const { - - return m_centralWidgetToDockWidgetsMap.contains(view) && m_centralWidgetToDockWidgetsMap[view].contains(name); -} - -QDockWidget *MenuActionHelper::getDockWidget(MainWindow::VIEW_SECTIONS view, const QString &name) const { - if(!m_centralWidgetToDockWidgetsMap.contains(view)) - return NULL; - return m_centralWidgetToDockWidgetsMap[view].value(name); -} - -void MenuActionHelper::showTool(bool show) { - //Called when a menu item is clicked on, regardless of view. - QAction* act = qobject_cast(sender()); - Q_ASSERT(act); - if (m_menuToDockNameMap.contains(act)) { - QString name = m_menuToDockNameMap[act]; - emit needToShowDockWidget(name, show); - } -} - -void MenuActionHelper::setDockWidgetTitleBarsEnabled(bool enabled) -{ - m_dockWidgetTitleBarsEnabled = enabled; - for (int i = 0; i < m_dockWidgets.size(); i++) - setDockWidgetTitleBar(m_dockWidgets[i]); -} - - -void MenuActionHelper::setAdvancedMode(bool advancedMode) -{ - m_isAdvancedMode = advancedMode; - for (int i = 0; i < m_dockWidgets.size(); i++) - setDockWidgetTitleBar(m_dockWidgets[i]); -} - -void MenuActionHelper::setDockWidgetTitleBar(QDockWidget* widget) -{ - Q_ASSERT(widget); - QWidget* oldTitleBar = widget->titleBarWidget(); - - // In advanced mode, we use the default titlebar provided by Qt. - if (m_isAdvancedMode) - { - widget->setTitleBarWidget(0); - } - // Otherwise, if just a textlabel should be shown, make that the titlebar. - else if (m_dockWidgetTitleBarsEnabled) - { - QLabel* label = new QLabel(widget); - label->setText(widget->windowTitle()); - label->installEventFilter(this); //Ignore mouse clicks - widget->installEventFilter(this); //Update label if window title changes. See eventFilter below - widget->setTitleBarWidget(label); - } - // And if nothing should be shown, use an empty widget. - else - { - QWidget* newTitleBar = new QWidget(widget); - widget->setTitleBarWidget(newTitleBar); - } - - // Be sure to clean up the old titlebar. When using QDockWidget::setTitleBarWidget(), - // it doesn't delete the old titlebar object. - delete oldTitleBar; -} - -bool MenuActionHelper::eventFilter(QObject *object,QEvent *event) -{ - if (event->type() == QEvent::WindowTitleChange) - { - QDockWidget *dock = qobject_cast(object); - if(dock) { - // Update the dock title bar label - QLabel *label = dynamic_cast(dock->titleBarWidget()); - if(label) - label->setText(dock->windowTitle()); - // Now update the action label - QString oldObjectName = dock->objectName(); - QAction *action = m_menuToDockNameMap.key(oldObjectName); - if(action) - action->setText(dock->windowTitle()); - //Now modify the object name - it is a strange naming scheme.. - } - } else if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) - { - if(qobject_cast(object)) - return true; - } - return QObject::eventFilter(object,event); -} diff --git a/src/ui/menuactionhelper.h b/src/ui/menuactionhelper.h deleted file mode 100644 index 26c6c5a9e5434e56f0bd983b9a5ac652a7820b2e..0000000000000000000000000000000000000000 --- a/src/ui/menuactionhelper.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef MENUACTIONHELPER_H -#define MENUACTIONHELPER_H - -#include "MainWindow.h" -#include - -class MenuActionHelper : public QObject -{ - Q_OBJECT -public: - MenuActionHelper(QObject *parent = NULL); - ~MenuActionHelper() {} - - /** @brief Get title bar mode setting */ - bool dockWidgetTitleBarsEnabled() const { return m_dockWidgetTitleBarsEnabled; } - void setDockWidgetTitleBarsEnabled(bool enabled); - bool isAdvancedMode() const { return m_isAdvancedMode; } - void setAdvancedMode(bool advancedMode); - QAction *createToolAction(const QString &title, const QString &name = QString()); - QAction *createToolActionForCustomDockWidget(const QString& title, const QString& name, QDockWidget* dockWidget, MainWindow::VIEW_SECTIONS view); - QDockWidget *createDockWidget(const QString& title, const QString& name); - bool containsDockWidget(MainWindow::VIEW_SECTIONS view, const QString &name) const; - QDockWidget *getDockWidget(MainWindow::VIEW_SECTIONS view, const QString &name) const; - - /** QMenu to add QActions to */ - void setMenu(QMenu *menu) { m_menu = menu; } - -protected: - virtual bool eventFilter(QObject *object,QEvent *event); - -private slots: - void removeDockWidget(); - /** @brief Shows a Docked Widget based on the action sender */ - void showTool(bool show); - -signals: - void needToShowDockWidget(const QString& name, bool show); -private: - QMap m_menuToDockNameMap; - QList m_dockWidgets; - QMap > m_centralWidgetToDockWidgetsMap; - bool m_isAdvancedMode; ///< If enabled dock widgets can be moved and floated. - bool m_dockWidgetTitleBarsEnabled; ///< If enabled, dock widget titlebars are displayed when NOT in advanced mode. - QMenu *m_menu; ///< \see setMenu() - bool m_addedCustomSeperator; ///< Whether we have added a seperator between the actions and the custom actions - - void setDockWidgetTitleBar(QDockWidget* widget); - -}; - -#endif // MENUACTIONHELPER_H diff --git a/src/ui/px4_configuration/PX4FirmwareUpgrade.cc b/src/ui/px4_configuration/PX4FirmwareUpgrade.cc index 1db5191c4620ce5dac5972d2c53a20fbb642aed0..7a5726c71dcd9ae565dfa8a63605ff79937f2787 100644 --- a/src/ui/px4_configuration/PX4FirmwareUpgrade.cc +++ b/src/ui/px4_configuration/PX4FirmwareUpgrade.cc @@ -476,11 +476,11 @@ void PX4FirmwareUpgrade::_getFirmwareFile(void) _firmwareFilename = _ui->firmwareCombo->itemData(index).toString(); Q_ASSERT(!_firmwareFilename.isEmpty()); if (_firmwareFilename == "selectfile") { - _firmwareFilename = QGCFileDialog::getOpenFileName(this, - tr("Select Firmware File"), // Dialog title - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), // Initial directory - tr("Firmware Files (*.px4 *.bin)")); // File filter - + _firmwareFilename = QGCFileDialog::getOpenFileName( + this, + tr("Load Firmware File"), // Dialog Caption + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), // Initial directory + tr("Firmware Files (*.px4 *.bin)")); // File filter } if (!_firmwareFilename.isEmpty()) { _downloadFirmware(); @@ -821,4 +821,4 @@ void PX4FirmwareUpgrade::_eraseProgressTick(void) { _eraseTickCount++; _ui->progressBar->setValue((_eraseTickCount*_eraseTickMsec*100) / _eraseTotalMsec); -} \ No newline at end of file +} diff --git a/src/ui/submainwindow.cpp b/src/ui/submainwindow.cpp deleted file mode 100644 index 7705cff1601614e35767efbc0f7de7e8f472b403..0000000000000000000000000000000000000000 --- a/src/ui/submainwindow.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "submainwindow.h" - -SubMainWindow::SubMainWindow(QWidget *parent) : QMainWindow(parent) -{ - -} diff --git a/src/ui/submainwindow.h b/src/ui/submainwindow.h deleted file mode 100644 index 510acf473879f1d199a782067a56cc77561453e0..0000000000000000000000000000000000000000 --- a/src/ui/submainwindow.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SUBMAINWINDOW_H -#define SUBMAINWINDOW_H - -#include - -class SubMainWindow : public QMainWindow -{ - Q_OBJECT -public: - explicit SubMainWindow(QWidget *parent = 0); -signals: - -public slots: - -}; - -#endif // SUBMAINWINDOW_H diff --git a/src/ui/uas/UASView.cc b/src/ui/uas/UASView.cc index ab86b3175b631dca611098caca76d421f61d8067..507272ec7c8f629e36e8e1ce0f6bfc596124fdc3 100644 --- a/src/ui/uas/UASView.cc +++ b/src/ui/uas/UASView.cc @@ -118,7 +118,6 @@ UASView::UASView(UASInterface* uas, QWidget *parent) : connect(removeAction, SIGNAL(triggered()), this, SLOT(triggerUASDeletion())); connect(renameAction, SIGNAL(triggered()), this, SLOT(rename())); connect(selectAction, SIGNAL(triggered()), uas, SLOT(setSelected())); - connect(hilAction, SIGNAL(triggered(bool)), this, SLOT(showHILUi())); connect(selectAirframeAction, SIGNAL(triggered()), this, SLOT(selectAirframe())); connect(setBatterySpecsAction, SIGNAL(triggered()), this, SLOT(setBatterySpecs())); @@ -553,11 +552,6 @@ void UASView::selectAirframe() } } -void UASView::showHILUi() -{ - MainWindow::instance()->showHILConfigurationWidget(uas); -} - void UASView::triggerUASDeletion() { refreshTimer->stop(); diff --git a/src/ui/uas/UASView.h b/src/ui/uas/UASView.h index c536d5be78fa7d2420fe2d64c0178cb898ae0298..4510aca87501fb89606b2c63422ddc821b3bcfbe 100644 --- a/src/ui/uas/UASView.h +++ b/src/ui/uas/UASView.h @@ -65,7 +65,6 @@ public slots: void updateMode(int sysId, QString status, QString description); void updateLoad(UASInterface* uas, double load); //void receiveValue(int uasid, QString id, double value, quint64 time); - void showHILUi(); /** * Request that the UASManager deletes this UAS. This doesn't delete this widget * yet, it waits for the approprait uasDeleted signal.