Commit 18a2d165 authored by dogmaphobic's avatar dogmaphobic

Merge branch 'master' into issue1182

Conflicts:
	src/QGCApplication.cc
	src/QGCFileDialog.cc
	src/QGCFileDialog.h
	src/ui/MainWindow.cc
	src/ui/QGCBaseParamWidget.cc
	src/ui/WaypointList.cc
	src/ui/designer/QGCToolWidget.cc
	src/ui/linechart/LinechartWidget.cc

Merging master
Applied changes to file open/save dialogs.
parents 25408fd1 d652eeb9
[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
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
[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
^ 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
......@@ -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
......
......@@ -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);
}
......
......@@ -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"
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
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 <http://www.gnu.org/licenses/>.
======================================================================*/
#include "QGCDockWidget.h"
#include <QCloseEvent>
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);
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
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 <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef QGCDockWidget_h
#define QGCDockWidget_h
#include <QDockWidget>
/// @file
/// @brief Subclass of QDockWidget so we can intercept the closeEvent.
///
/// @author Don Gagne <don@thegagnes.com>
class QGCDockWidget : public QDockWidget {
Q_OBJECT
public:
QGCDockWidget(const QString& title, QWidget *parent = 0, Qt::WindowFlags flags = 0);
void closeEvent(QCloseEvent* event);
};
#endif
......@@ -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;
......
......@@ -31,10 +31,21 @@
/// @author Don Gagne <don@thegagnes.com>
/*!
Subclass of <a href="http://qt-project.org/doc/qt-5/qfiledialog.html">QFileDialog</a> which re-implements the static public functions. The reason for this
is that the <a href="http://qt-project.org/doc/qt-5/qfiledialog.html">QFileDialog</a> 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 <a href="http://qt-project.org/doc/qt-5/qfiledialog.html">QFileDialog</a> which re-implements the static public functions. The reason for this
is that the <a href="http://qt-project.org/doc/qt-5/qfiledialog.html">QFileDialog</a> 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 <a href="http://qt-project.org/doc/qt-5/qfiledialog.html#getOpenFileName">QFileDialog::getOpenFileName()</a>
......@@ -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 <a href="http://qt-project.org/doc/qt-5/qstringlist.html">QStringList</a> object containing zero or more files to be opened.
@sa <a href="http://qt-project.org/doc/qt-5/qfiledialog.html#getOpenFileNames">QFileDialog::getOpenFileNames()</a>
......@@ -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 <a href="http://qt-project.org/doc/qt-5/qfiledialog.html#getSaveFileName">QFileDialog::getSaveFileName()</a>
@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);
};
......
......@@ -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;
}
......
......@@ -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);
}
......@@ -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
......
This diff is collapsed.
This diff is collapsed.
......@@ -62,7 +62,6 @@
<addaction name="separator"/>
<addaction name="actionMuteAudioOutput"/>
<addaction name="actionSettings"/>
<addaction name="actionAdvanced_Mode"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
......
......@@ -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();
}
......@@ -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
......
......@@ -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);
}
......
......@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>414</width>
<width>200</width>
<height>518</height>
</rect>
</property>
......
......@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<width>200</width>
<height>300</height>
</rect>
</property>
......
......@@ -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
......
......@@ -62,16 +62,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="titleBarCheckBox">
<property name="text">
<string>Show Docked Widget title bars when NOT in advanced Mode.</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="promptFlightDataSave">
<property name="text">
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -354,6 +354,7 @@ void
Q3DWidget::redraw(void)
{
emit update();
emit updateWidget();
#if (QGC_EVENTLOOP_DEBUG)
qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
#endif
......
#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<MainWindow::VIEW_SECTIONS,QMap<QString,QDockWidget*> >::iterator it;
for (it = m_centralWidgetToDockWidgetsMap.begin(); it != m_centralWidgetToDockWidgetsMap.end(); ++it) {
QMap<QString,QDockWidget*>::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<QDockWidget*>(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<QAction *>(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<QDockWidget *>(object);
if(dock) {
// Update the dock title bar label
QLabel *label = dynamic_cast<QLabel *>(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<QLabel *>(object))
return true;
}
return QObject::eventFilter(object,event);
}
#ifndef MENUACTIONHELPER_H
#define MENUACTIONHELPER_H
#include "MainWindow.h"
#include <QDockWidget>
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<QAction*,QString > m_menuToDockNameMap;
QList<QDockWidget*> m_dockWidgets;
QMap<MainWindow::VIEW_SECTIONS,QMap<QString,QDockWidget*> > 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
......@@ -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
}
#include "submainwindow.h"
SubMainWindow::SubMainWindow(QWidget *parent) : QMainWindow(parent)
{
}
#ifndef SUBMAINWINDOW_H
#define SUBMAINWINDOW_H
#include <QMainWindow>
class SubMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit SubMainWindow(QWidget *parent = 0);
signals:
public slots:
};
#endif // SUBMAINWINDOW_H
......@@ -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();
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment