Commit 4d40f298 authored by Don Gagne's avatar Don Gagne

New MainWindow central and dock widget architecture

- Central widget no longer stacked. Views are added/removed to layout
to switch view
- Dock Widgets are globals with single instance of each type
- Both central views and dock widgets are just-in-time created saving
lots of memory
parent 78507bfe
...@@ -451,7 +451,6 @@ HEADERS += \ ...@@ -451,7 +451,6 @@ HEADERS += \
src/ui/QGCHilFlightGearConfiguration.h \ src/ui/QGCHilFlightGearConfiguration.h \
src/ui/QGCHilJSBSimConfiguration.h \ src/ui/QGCHilJSBSimConfiguration.h \
src/ui/QGCHilXPlaneConfiguration.h \ src/ui/QGCHilXPlaneConfiguration.h \
src/ui/submainwindow.h \
src/ui/uas/UASQuickView.h \ src/ui/uas/UASQuickView.h \
src/ui/uas/UASQuickViewItem.h \ src/ui/uas/UASQuickViewItem.h \
src/ui/linechart/ChartPlot.h \ src/ui/linechart/ChartPlot.h \
...@@ -480,7 +479,6 @@ HEADERS += \ ...@@ -480,7 +479,6 @@ HEADERS += \
src/ui/px4_configuration/PX4Bootloader.h \ src/ui/px4_configuration/PX4Bootloader.h \
src/ui/px4_configuration/PX4FirmwareUpgradeThread.h \ src/ui/px4_configuration/PX4FirmwareUpgradeThread.h \
src/ui/px4_configuration/PX4FirmwareUpgrade.h \ src/ui/px4_configuration/PX4FirmwareUpgrade.h \
src/ui/menuactionhelper.h \
src/uas/UASManagerInterface.h \ src/uas/UASManagerInterface.h \
src/uas/QGCUASParamManagerInterface.h \ src/uas/QGCUASParamManagerInterface.h \
src/uas/QGCUASFileManager.h \ src/uas/QGCUASFileManager.h \
...@@ -495,6 +493,7 @@ HEADERS += \ ...@@ -495,6 +493,7 @@ HEADERS += \
src/QGCQuickWidget.h \ src/QGCQuickWidget.h \
src/QGCPalette.h \ src/QGCPalette.h \
src/QGCQmlWidgetHolder.h \ src/QGCQmlWidgetHolder.h \
src/QGCDockWidget.h \
SOURCES += \ SOURCES += \
src/main.cc \ src/main.cc \
...@@ -595,7 +594,6 @@ SOURCES += \ ...@@ -595,7 +594,6 @@ SOURCES += \
src/ui/QGCHilFlightGearConfiguration.cc \ src/ui/QGCHilFlightGearConfiguration.cc \
src/ui/QGCHilJSBSimConfiguration.cc \ src/ui/QGCHilJSBSimConfiguration.cc \
src/ui/QGCHilXPlaneConfiguration.cc \ src/ui/QGCHilXPlaneConfiguration.cc \
src/ui/submainwindow.cpp \
src/ui/uas/UASQuickViewItem.cc \ src/ui/uas/UASQuickViewItem.cc \
src/ui/uas/UASQuickView.cc \ src/ui/uas/UASQuickView.cc \
src/ui/linechart/ChartPlot.cc \ src/ui/linechart/ChartPlot.cc \
...@@ -624,7 +622,6 @@ SOURCES += \ ...@@ -624,7 +622,6 @@ SOURCES += \
src/ui/px4_configuration/PX4Bootloader.cc \ src/ui/px4_configuration/PX4Bootloader.cc \
src/ui/px4_configuration/PX4FirmwareUpgradeThread.cc \ src/ui/px4_configuration/PX4FirmwareUpgradeThread.cc \
src/ui/px4_configuration/PX4FirmwareUpgrade.cc \ src/ui/px4_configuration/PX4FirmwareUpgrade.cc \
src/ui/menuactionhelper.cpp \
src/uas/QGCUASFileManager.cc \ src/uas/QGCUASFileManager.cc \
src/ui/QGCUASFileView.cc \ src/ui/QGCUASFileView.cc \
src/CmdLineOptParser.cc \ src/CmdLineOptParser.cc \
...@@ -636,6 +633,7 @@ SOURCES += \ ...@@ -636,6 +633,7 @@ SOURCES += \
src/QGCQuickWidget.cc \ src/QGCQuickWidget.cc \
src/QGCPalette.cc \ src/QGCPalette.cc \
src/QGCQmlWidgetHolder.cpp \ src/QGCQmlWidgetHolder.cpp \
src/QGCDockWidget.cc \
# #
# Unit Test specific configuration goes here # Unit Test specific configuration goes here
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
// If you need to make an incompatible changes to stored settings, bump this version number // 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. // 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_APPLICATION_NAME "QGroundControl"
#define QGC_ORG_NAME "QGroundControl.org" #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
...@@ -28,7 +28,6 @@ This file is part of the QGROUNDCONTROL project ...@@ -28,7 +28,6 @@ This file is part of the QGROUNDCONTROL project
*/ */
#include <QSettings> #include <QSettings>
#include <QDockWidget>
#include <QNetworkInterface> #include <QNetworkInterface>
#include <QDebug> #include <QDebug>
#include <QTimer> #include <QTimer>
...@@ -66,11 +65,11 @@ This file is part of the QGROUNDCONTROL project ...@@ -66,11 +65,11 @@ This file is part of the QGROUNDCONTROL project
#include "SetupView.h" #include "SetupView.h"
#include "SerialSettingsDialog.h" #include "SerialSettingsDialog.h"
#include "terminalconsole.h" #include "terminalconsole.h"
#include "menuactionhelper.h"
#include "QGCUASFileViewMulti.h" #include "QGCUASFileViewMulti.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#include "QGCFileDialog.h" #include "QGCFileDialog.h"
#include "QGCMessageBox.h" #include "QGCMessageBox.h"
#include "QGCDockWidget.h"
#ifdef QGC_OSG_ENABLED #ifdef QGC_OSG_ENABLED
#include "Q3DWidgetFactory.h" #include "Q3DWidgetFactory.h"
...@@ -78,6 +77,22 @@ This file is part of the QGROUNDCONTROL project ...@@ -78,6 +77,22 @@ This file is part of the QGROUNDCONTROL project
#include "LogCompressor.h" #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 static MainWindow* _instance = NULL; ///< @brief MainWindow singleton
MainWindow* MainWindow::_create(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE mode) MainWindow* MainWindow::_create(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE mode)
...@@ -106,13 +121,13 @@ void MainWindow::deleteInstance(void) ...@@ -106,13 +121,13 @@ void MainWindow::deleteInstance(void)
/// by MainWindow::_create method. Hence no other code should have access to /// by MainWindow::_create method. Hence no other code should have access to
/// constructor. /// constructor.
MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE mode) : MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE mode) :
currentView(VIEW_FLIGHT),
centerStackActionGroup(new QActionGroup(this)), centerStackActionGroup(new QActionGroup(this)),
autoReconnect(false), autoReconnect(false),
simulationLink(NULL), simulationLink(NULL),
lowPowerMode(false), lowPowerMode(false),
customMode(mode), customMode(mode),
menuActionHelper(new MenuActionHelper()), _currentView(VIEW_FLIGHT),
_currentViewWidget(NULL),
_splashScreen(splashScreen) _splashScreen(splashScreen)
{ {
Q_ASSERT(_instance == NULL); Q_ASSERT(_instance == NULL);
...@@ -122,52 +137,42 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE ...@@ -122,52 +137,42 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
connect(this, &MainWindow::initStatusChanged, splashScreen, &QSplashScreen::showMessage); connect(this, &MainWindow::initStatusChanged, splashScreen, &QSplashScreen::showMessage);
} }
connect(menuActionHelper, SIGNAL(needToShowDockWidget(QString,bool)),SLOT(showDockWidget(QString,bool)));
loadSettings(); 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. // Select the proper view. Default to the flight view or load the last one used if it's supported.
if (!settings.contains("CURRENT_VIEW")) VIEW_SECTIONS currentViewCandidate = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", _currentView).toInt();
{ switch (currentViewCandidate) {
settings.setValue("CURRENT_VIEW", currentView); case VIEW_ENGINEER:
} case VIEW_MISSION:
else case VIEW_FLIGHT:
{ case VIEW_SIMULATION:
VIEW_SECTIONS currentViewCandidate = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt(); case VIEW_SETUP:
switch (currentViewCandidate) { case VIEW_TERMINAL:
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
#ifdef QGC_OSG_ENABLED #ifdef QGC_OSG_ENABLED
case VIEW_LOCAL3D: case VIEW_LOCAL3D:
#endif #endif
#ifdef QGC_GOOGLE_EARTH_ENABLED #ifdef QGC_GOOGLE_EARTH_ENABLED
case VIEW_GOOGLEEARTH: case VIEW_GOOGLEEARTH:
#endif #endif
_currentView = currentViewCandidate;
currentView = currentViewCandidate; break;
default:
// If an invalid view candidate was found in the settings file, just use the default view and re-save. default:
settings.setValue("CURRENT_VIEW", currentView); // Leave _currentView to the default
break; 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)); emit initStatusChanged(tr("Setting up user interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
// Setup user interface // Setup user interface
ui.setupUi(this); 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 // Set dock options
setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks); setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);
...@@ -186,10 +191,6 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE ...@@ -186,10 +191,6 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
// Setup UI state machines // Setup UI state machines
centerStackActionGroup->setExclusive(true); centerStackActionGroup->setExclusive(true);
centerStack = new QStackedWidget(this);
setCentralWidget(centerStack);
// Load Toolbar // Load Toolbar
toolBar = new QGCToolBar(this); toolBar = new QGCToolBar(this);
this->addToolBar(toolBar); this->addToolBar(toolBar);
...@@ -215,8 +216,7 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE ...@@ -215,8 +216,7 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
emit initStatusChanged(tr("Building common widgets."), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); emit initStatusChanged(tr("Building common widgets."), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
buildCommonWidgets(); _buildCommonWidgets();
connectCommonWidgets();
emit initStatusChanged(tr("Building common actions"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); emit initStatusChanged(tr("Building common actions"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
...@@ -267,13 +267,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE ...@@ -267,13 +267,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
// Set low power mode // Set low power mode
enableLowPowerMode(lowPowerMode); enableLowPowerMode(lowPowerMode);
// Initialize window state
windowStateVal = windowState();
emit initStatusChanged(tr("Restoring last view state"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); emit initStatusChanged(tr("Restoring last view state"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
// Restore the window setup // Restore the window setup
loadViewState(); _loadCurrentViewState();
emit initStatusChanged(tr("Restoring last window size"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); emit initStatusChanged(tr("Restoring last window size"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
// Restore the window position and size // Restore the window position and size
...@@ -363,31 +360,7 @@ MainWindow::~MainWindow() ...@@ -363,31 +360,7 @@ MainWindow::~MainWindow()
joystick = NULL; 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<QDockWidget*>(*i);
if (dockWidget)
{
// Remove dock widget from main window
// removeDockWidget(dockWidget);
// delete dockWidget->widget();
delete dockWidget;
dockWidget = NULL;
}
else if (dynamic_cast<QWidget*>(*i))
{
delete dynamic_cast<QWidget*>(*i);
*i = NULL;
}
}
// Delete all UAS objects // Delete all UAS objects
delete menuActionHelper;
for (int i=0;i<commsWidgetList.size();i++) for (int i=0;i<commsWidgetList.size();i++)
{ {
commsWidgetList[i]->deleteLater(); commsWidgetList[i]->deleteLater();
...@@ -405,10 +378,10 @@ QString MainWindow::getWindowStateKey() ...@@ -405,10 +378,10 @@ QString MainWindow::getWindowStateKey()
{ {
if (UASManager::instance()->getActiveUAS()) if (UASManager::instance()->getActiveUAS())
{ {
return QString::number(currentView)+"_windowstate_" + QString::number(getCustomMode()) + "_" + UASManager::instance()->getActiveUAS()->getAutopilotTypeName(); return QString::number(_currentView)+"_windowstate_" + QString::number(getCustomMode()) + "_" + UASManager::instance()->getActiveUAS()->getAutopilotTypeName();
} }
else else
return QString::number(currentView)+"_windowstate_" + QString::number(getCustomMode()); return QString::number(_currentView)+"_windowstate_" + QString::number(getCustomMode());
} }
QString MainWindow::getWindowGeometryKey() QString MainWindow::getWindowGeometryKey()
...@@ -416,64 +389,61 @@ QString MainWindow::getWindowGeometryKey() ...@@ -416,64 +389,61 @@ QString MainWindow::getWindowGeometryKey()
return "_geometry"; return "_geometry";
} }
void MainWindow::buildCustomWidget() void MainWindow::_buildCustomWidgets(void)
{ {
Q_ASSERT(_customWidgets.count() == 0);
// Create custom widgets // Create custom widgets
QList<QGCToolWidget*> widgets = QGCToolWidget::createWidgetsFromSettings(this); _customWidgets = QGCToolWidget::createWidgetsFromSettings(this);
if (widgets.size() > 0) if (_customWidgets.size() > 0)
{ {
ui.menuTools->addSeparator(); 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 // Check if this widget already has a parent, do not create it in this case
QGCToolWidget* tool = widgets.at(i);
QDockWidget* dock = dynamic_cast<QDockWidget*>(tool->parentWidget()); QDockWidget* dock = dynamic_cast<QDockWidget*>(tool->parentWidget());
if (!dock)
{ if (!dock) {
QSettings settings; _createDockWidget(tool->getTitle(), tool->objectName(), Qt::BottomDockWidgetArea, tool);
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();
} }
} }
} }
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 // Add generic MAVLink decoder
mavlinkDecoder = new MAVLinkDecoder(MAVLinkProtocol::instance(), this); mavlinkDecoder = new MAVLinkDecoder(MAVLinkProtocol::instance(), this);
...@@ -484,274 +454,246 @@ void MainWindow::buildCommonWidgets() ...@@ -484,274 +454,246 @@ void MainWindow::buildCommonWidgets()
logPlayer = new QGCMAVLinkLogPlayer(MAVLinkProtocol::instance(), statusBar()); logPlayer = new QGCMAVLinkLogPlayer(MAVLinkProtocol::instance(), statusBar());
statusBar()->addPermanentWidget(logPlayer); statusBar()->addPermanentWidget(logPlayer);
// Initialize all of the views, if they haven't been already, and add their central widgets // In order for Qt to save and restore state of widgets all widgets must be created ahead of time. We only create the QDockWidget
if (!plannerView) // 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.
plannerView = new SubMainWindow(this);
plannerView->setObjectName("VIEW_MISSION"); struct DockWidgetInfo {
plannerView->setCentralWidget(new QGCMapTool(this)); const char* name;
addToCentralStackedWidget(plannerView, VIEW_MISSION, "Maps"); const char* title;
} Qt::DockWidgetArea area;
if (!pilotView) };
{
pilotView = new SubMainWindow(this); static const struct DockWidgetInfo rgDockWidgetInfo[] = {
pilotView->setObjectName("VIEW_FLIGHT"); { _uasControlDockWidgetName, "Control", Qt::LeftDockWidgetArea },
pilotView->setCentralWidget(new PrimaryFlightDisplay(this)); { _uasListDockWidgetName, "Unmanned Systems", Qt::RightDockWidgetArea },
addToCentralStackedWidget(pilotView, VIEW_FLIGHT, "Pilot"); { _waypointsDockWidgetName, "Mission Plan", Qt::BottomDockWidgetArea },
} { _mavlinkDockWidgetName, "MAVLink Inspector", Qt::RightDockWidgetArea },
if (!terminalView) { _parametersDockWidgetName, "Onboard Parameters", Qt::RightDockWidgetArea },
{ { _filesDockWidgetName, "Onboard Files", Qt::RightDockWidgetArea },
terminalView = new SubMainWindow(this); { _uasStatusDetailsDockWidgetName, "Status Details", Qt::RightDockWidgetArea },
terminalView->setObjectName("VIEW_TERMINAL"); { _mapViewDockWidgetName, "Map view", Qt::RightDockWidgetArea },
TerminalConsole *terminalConsole = new TerminalConsole(this); { _hsiDockWidgetName, "Horizontal Situation", Qt::BottomDockWidgetArea },
terminalView->setCentralWidget(terminalConsole); { _hdd1DockWidgetName, "Flight Display", Qt::RightDockWidgetArea },
addToCentralStackedWidget(terminalView, VIEW_TERMINAL, tr("Terminal View")); { _hdd2DockWidgetName, "Actuator Status", Qt::RightDockWidgetArea },
} { _pfdDockWidgetName, "Primary Flight Display", Qt::RightDockWidgetArea },
if (!setupView) { _hudDockWidgetName, "Video Downlink", Qt::RightDockWidgetArea },
{ { _uasInfoViewDockWidgetName, "Info View", Qt::LeftDockWidgetArea },
setupView = new SubMainWindow(this); { _debugConsoleDockWidgetName, "Communications Console", Qt::LeftDockWidgetArea }
setupView->setObjectName("VIEW_SETUP"); };
setupView->setCentralWidget((QWidget*)new SetupView(this)); static const size_t cDockWidgetInfo = sizeof(rgDockWidgetInfo) / sizeof(rgDockWidgetInfo[0]);
addToCentralStackedWidget(setupView, VIEW_SETUP, "Setup");
} for (size_t i=0; i<cDockWidgetInfo; i++) {
if (!engineeringView) const struct DockWidgetInfo* pDockInfo = &rgDockWidgetInfo[i];
{
engineeringView = new SubMainWindow(this); _createDockWidget(pDockInfo->title, pDockInfo->name, pDockInfo->area, NULL /* no inner widget yet */);
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"));
} }
#endif
#ifdef QGC_OSG_ENABLED
if (!local3DView)
{
q3DWidget = Q3DWidgetFactory::get("PIXHAWK", this);
q3DWidget->setObjectName("VIEW_3DWIDGET");
local3DView = new SubMainWindow(this); _buildCustomWidgets();
local3DView->setObjectName("VIEW_LOCAL3D"); }
local3DView->setCentralWidget(q3DWidget);
addToCentralStackedWidget(local3DView, VIEW_LOCAL3D, tr("Local 3D View"));
}
#endif
if (!simView) void MainWindow::_buildPlannerView(void)
{ {
simView = new SubMainWindow(this); if (!_plannerView) {
simView->setObjectName("VIEW_SIMULATOR"); _plannerView = new QGCMapTool(this);
simView->setCentralWidget(new QGCMapTool(this)); _plannerView->setVisible(false);
addToCentralStackedWidget(simView, VIEW_SIMULATION, tr("Simulation View"));
} }
}
// Add dock widgets for the planner view void MainWindow::_buildPilotView(void)
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); if (!_pilotView) {
_pilotView = new PrimaryFlightDisplay(this);
// Add dock widgets for the pilot view _pilotView->setVisible(false);
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::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); if (!_setupView) {
parent->addDockWidget(area,widget); _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<SubMainWindow*>(subMainWindowParent); if (!_engineeringView) {
Q_ASSERT(parent); _engineeringView = new QGCDataPlot2D(this);
QDockWidget* dockWidget = menuActionHelper->createDockWidget(title, objectName); _engineeringView->setVisible(false);
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 (minSize.height() >= 0) void MainWindow::_buildSimView(void)
dockWidget->setMinimumHeight(minSize.height()); {
if (minSize.width() >= 0) if (!_simView) {
dockWidget->setMinimumWidth(minSize.width()); _simView = new QGCMapTool(this);
addTool(parent,view,dockWidget,title,area); _simView->setVisible(false);
return dockWidget; }
} }
void MainWindow::showDockWidget(const QString& name, bool show) void MainWindow::_buildTerminalView(void)
{ {
QDockWidget *dockWidget = menuActionHelper->getDockWidget(currentView, name); if (!_terminalView) {
if(dockWidget) _terminalView = new TerminalConsole(this);
dockWidget->setVisible(show); _terminalView->setVisible(false);
else if (show) }
loadDockWidget(name);
} }
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; 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")
{ // Create the inner widget if we need to
createDockWidget(centerStack->currentWidget(),new QGCMapTool(this),tr("Map view"),"MAP_VIEW_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); if (!_mapName2DockWidget[name]->widget()) {
} _createInnerDockWidget(name);
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);
} }
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; QStringList acceptList;
acceptList.append("-3.3,ATTITUDE.roll,rad,+3.3,s"); 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.pitch,deg,+3.3,s");
acceptList.append("-3.3,ATTITUDE.yaw,deg,+3.3,s"); acceptList.append("-3.3,ATTITUDE.yaw,deg,+3.3,s");
HDDisplay *hddisplay = new HDDisplay(acceptList,"Flight Display",this); HDDisplay *hddisplay = new HDDisplay(acceptList,"Flight Display",this);
hddisplay->addSource(mavlinkDecoder); hddisplay->addSource(mavlinkDecoder);
createDockWidget(centerStack->currentWidget(),hddisplay,tr("Flight Display"),"HEAD_DOWN_DISPLAY_1_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
} widget = hddisplay;
else if (name == "HEAD_DOWN_DISPLAY_2_DOCKWIDGET") } else if (widgetName == _hdd2DockWidgetName) {
{
QStringList acceptList; QStringList acceptList;
acceptList.append("0,RAW_PRESSURE.pres_abs,hPa,65500"); acceptList.append("0,RAW_PRESSURE.pres_abs,hPa,65500");
HDDisplay *hddisplay = new HDDisplay(acceptList,"Actuator Status",this); HDDisplay *hddisplay = new HDDisplay(acceptList,"Actuator Status",this);
hddisplay->addSource(mavlinkDecoder); hddisplay->addSource(mavlinkDecoder);
createDockWidget(centerStack->currentWidget(),hddisplay,tr("Actuator Status"),"HEAD_DOWN_DISPLAY_2_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
} widget = hddisplay;
else if (name == "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET") } else if (widgetName == _pfdDockWidgetName) {
{ widget = new PrimaryFlightDisplay(this);
createDockWidget(centerStack->currentWidget(),new PrimaryFlightDisplay(this),tr("Primary Flight Display"),"PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); } else if (widgetName == _hudDockWidgetName) {
} widget = new HUD(320,240,this);
else if (name == "HEAD_UP_DISPLAY_DOCKWIDGET") } else if (widgetName == _uasInfoViewDockWidgetName) {
{ widget = new QGCTabbedInfoView(this);
createDockWidget(centerStack->currentWidget(),new HUD(320,240,this),tr("Video Downlink"),"HEAD_UP_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); } else if (widgetName == _debugConsoleDockWidgetName) {
} widget = new DebugConsole(this);
else if (name == "UAS_INFO_QUICKVIEW_DOCKWIDGET") } else {
{ qWarning() << "Attempt to create unknown Inner Dock Widget" << widgetName;
createDockWidget(centerStack->currentWidget(),new UASQuickView(this),tr("Quick View"),"UAS_INFO_QUICKVIEW_DOCKWIDGET",currentView,Qt::LeftDockWidgetArea);
} }
else
{ if (widget) {
if (customWidgetNameToFilenameMap.contains(name)) QDockWidget* dockWidget = _mapName2DockWidget[widgetName];
{ Q_CHECK_PTR(dockWidget);
loadCustomWidget(customWidgetNameToFilenameMap[name],currentView);
} widget->setParent(dockWidget);
else dockWidget->setWidget(widget);
{
qDebug() << "Error loading window:" << name;
}
} }
} }
void MainWindow::addToCentralStackedWidget(QWidget* widget, VIEW_SECTIONS viewSection, const QString& title) void MainWindow::_showHILConfigurationWidgets(void)
{ {
Q_UNUSED(viewSection); UASInterface* uas = UASManager::instance()->getActiveUAS();
Q_UNUSED(title);
Q_ASSERT(widget->objectName().length() != 0); if (!uas) {
return;
}
UAS* mav = dynamic_cast<UAS*>(uas);
Q_ASSERT(mav);
int uasId = mav->getUASID();
// Check if this widget already has been added if (!_mapUasId2HilDockWidget.contains(uasId)) {
if (centerStack->indexOf(widget) == -1)
{ // Create QDockWidget
centerStack->addWidget(widget); 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::fullScreenActionItemCallback()
void MainWindow::showCentralWidget()
{ {
QAction* act = qobject_cast<QAction *>(sender()); ui.actionNormal->setChecked(false);
QWidget* widget = act->data().value<QWidget *>();
centerStack->setCurrentWidget(widget);
} }
void MainWindow::showHILConfigurationWidget(UASInterface* uas) void MainWindow::normalActionItemCallback()
{ {
// Add simulation configuration widget ui.actionFullscreen->setChecked(false);
UAS* mav = dynamic_cast<UAS*>(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);
}
} }
void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::closeEvent(QCloseEvent *event)
...@@ -790,25 +732,13 @@ void MainWindow::closeEvent(QCloseEvent *event) ...@@ -790,25 +732,13 @@ void MainWindow::closeEvent(QCloseEvent *event)
Q_ASSERT(!link->isConnected()); Q_ASSERT(!link->isConnected());
} }
storeViewState(); _storeCurrentViewState();
storeSettings(); storeSettings();
UASManager::instance()->storeSettings(); UASManager::instance()->storeSettings();
event->accept(); event->accept();
} }
/** void MainWindow::_createNewCustomWidget(void)
* 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()
{ {
if (QGCToolWidget::instances()->isEmpty()) if (QGCToolWidget::instances()->isEmpty())
{ {
...@@ -826,110 +756,23 @@ void MainWindow::createCustomWidget() ...@@ -826,110 +756,23 @@ void MainWindow::createCustomWidget()
QString title = tr("Custom Tool %1").arg(customToolIndex ); QString title = tr("Custom Tool %1").arg(customToolIndex );
QGCToolWidget* tool = new QGCToolWidget(objectName, title); QGCToolWidget* tool = new QGCToolWidget(objectName, title);
createDockWidget(centerStack->currentWidget(),tool,title,objectName,currentView,Qt::BottomDockWidgetArea); tool->resize(100, 100);
_createDockWidget(title, objectName, Qt::BottomDockWidgetArea, tool);
QSettings settings;
settings.beginGroup("QGC_MAINWINDOW"); _mapName2DockWidget[objectName]->setVisible(true);
settings.setValue(QString("TOOL_PARENT_") + tool->objectName(),currentView);
settings.endGroup();
} }
void MainWindow::loadCustomWidget() void MainWindow::_loadCustomWidgetFromFile(void)
{ {
QString widgetFileExtension(".qgw"); QString widgetFileExtension(".qgw");
QString fileName = QGCFileDialog::getOpenFileName(this, tr("Specify Widget File Name"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr("QGroundControl Widget (*%1);;").arg(widgetFileExtension)); QString fileName = QGCFileDialog::getOpenFileName(this, tr("Specify Widget File Name"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr("QGroundControl Widget (*%1);;").arg(widgetFileExtension));
if (fileName != "") loadCustomWidget(fileName); if (fileName != "") {
} QGCToolWidget* tool = new QGCToolWidget("", "", this);
void MainWindow::loadCustomWidget(const QString& fileName, int view) if (tool->loadSettings(fileName, true)) {
{ QString objectName = tool->objectName() + "DOCK";
QGCToolWidget* tool = new QGCToolWidget("", "", this);
if (tool->loadSettings(fileName, true)) _createDockWidget(tool->getTitle(), objectName, Qt::LeftDockWidgetArea, tool);
{ _mapName2DockWidget[objectName]->widget()->setVisible(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;
}
}
void MainWindow::loadCustomWidgetsFromDefaults(const QString& systemType, const QString& autopilotType)
{
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);
} }
} }
} }
...@@ -943,10 +786,7 @@ void MainWindow::loadSettings() ...@@ -943,10 +786,7 @@ void MainWindow::loadSettings()
settings.beginGroup("QGC_MAINWINDOW"); settings.beginGroup("QGC_MAINWINDOW");
autoReconnect = settings.value("AUTO_RECONNECT", autoReconnect).toBool(); autoReconnect = settings.value("AUTO_RECONNECT", autoReconnect).toBool();
lowPowerMode = settings.value("LOW_POWER_MODE", lowPowerMode).toBool(); lowPowerMode = settings.value("LOW_POWER_MODE", lowPowerMode).toBool();
bool dockWidgetTitleBarEnabled = settings.value("DOCK_WIDGET_TITLEBARS",menuActionHelper->dockWidgetTitleBarsEnabled()).toBool();
settings.endGroup(); settings.endGroup();
enableDockWidgetTitleBars(dockWidgetTitleBarEnabled);
} }
void MainWindow::storeSettings() void MainWindow::storeSettings()
...@@ -963,13 +803,13 @@ void MainWindow::storeSettings() ...@@ -963,13 +803,13 @@ void MainWindow::storeSettings()
settings.setValue(getWindowGeometryKey(), saveGeometry()); settings.setValue(getWindowGeometryKey(), saveGeometry());
// Save the last current view in any case // 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)) // 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()); if (UASManager::instance()->getUASList().length() > 0) settings.setValue(getWindowStateKey(), saveState());
// Save the current UAS view if a UAS is connected // 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 // And save any custom weidgets
QGCToolWidget::storeWidgetsToSettings(settings); QGCToolWidget::storeWidgetsToSettings(settings);
...@@ -1030,14 +870,6 @@ void MainWindow::saveScreen() ...@@ -1030,14 +870,6 @@ void MainWindow::saveScreen()
window.save(screenFileName, format.toLatin1()); 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) void MainWindow::enableAutoReconnect(bool enabled)
{ {
...@@ -1071,42 +903,42 @@ void MainWindow::connectCommonActions() ...@@ -1071,42 +903,42 @@ void MainWindow::connectCommonActions()
#endif #endif
// Mark the right one as selected // Mark the right one as selected
if (currentView == VIEW_ENGINEER) if (_currentView == VIEW_ENGINEER)
{ {
ui.actionEngineersView->setChecked(true); ui.actionEngineersView->setChecked(true);
ui.actionEngineersView->activate(QAction::Trigger); ui.actionEngineersView->activate(QAction::Trigger);
} }
if (currentView == VIEW_FLIGHT) if (_currentView == VIEW_FLIGHT)
{ {
ui.actionFlightView->setChecked(true); ui.actionFlightView->setChecked(true);
ui.actionFlightView->activate(QAction::Trigger); ui.actionFlightView->activate(QAction::Trigger);
} }
if (currentView == VIEW_SIMULATION) if (_currentView == VIEW_SIMULATION)
{ {
ui.actionSimulationView->setChecked(true); ui.actionSimulationView->setChecked(true);
ui.actionSimulationView->activate(QAction::Trigger); ui.actionSimulationView->activate(QAction::Trigger);
} }
if (currentView == VIEW_MISSION) if (_currentView == VIEW_MISSION)
{ {
ui.actionMissionView->setChecked(true); ui.actionMissionView->setChecked(true);
ui.actionMissionView->activate(QAction::Trigger); ui.actionMissionView->activate(QAction::Trigger);
} }
if (currentView == VIEW_SETUP) if (_currentView == VIEW_SETUP)
{ {
ui.actionSetup->setChecked(true); ui.actionSetup->setChecked(true);
ui.actionSetup->activate(QAction::Trigger); ui.actionSetup->activate(QAction::Trigger);
} }
if (currentView == VIEW_TERMINAL) if (_currentView == VIEW_TERMINAL)
{ {
ui.actionTerminalView->setChecked(true); ui.actionTerminalView->setChecked(true);
ui.actionTerminalView->activate(QAction::Trigger); ui.actionTerminalView->activate(QAction::Trigger);
} }
if (currentView == VIEW_GOOGLEEARTH) if (_currentView == VIEW_GOOGLEEARTH)
{ {
ui.actionGoogleEarthView->setChecked(true); ui.actionGoogleEarthView->setChecked(true);
ui.actionGoogleEarthView->activate(QAction::Trigger); ui.actionGoogleEarthView->activate(QAction::Trigger);
} }
if (currentView == VIEW_LOCAL3D) if (_currentView == VIEW_LOCAL3D)
{ {
ui.actionLocal3DView->setChecked(true); ui.actionLocal3DView->setChecked(true);
ui.actionLocal3DView->activate(QAction::Trigger); ui.actionLocal3DView->activate(QAction::Trigger);
...@@ -1121,8 +953,6 @@ void MainWindow::connectCommonActions() ...@@ -1121,8 +953,6 @@ void MainWindow::connectCommonActions()
// Connect actions from ui // Connect actions from ui
connect(ui.actionAdd_Link, SIGNAL(triggered()), this, SLOT(addLink())); 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 internal actions
connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(UASCreated(UASInterface*))); connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(UASCreated(UASInterface*)));
...@@ -1151,8 +981,8 @@ void MainWindow::connectCommonActions() ...@@ -1151,8 +981,8 @@ void MainWindow::connectCommonActions()
connect(ui.actionProject_Roadmap, SIGNAL(triggered()), this, SLOT(showRoadMap())); connect(ui.actionProject_Roadmap, SIGNAL(triggered()), this, SLOT(showRoadMap()));
// Custom widget actions // Custom widget actions
connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget())); connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(_createNewCustomWidget()));
connect(ui.actionLoadCustomWidgetFile, SIGNAL(triggered()), this, SLOT(loadCustomWidget())); connect(ui.actionLoadCustomWidgetFile, SIGNAL(triggered()), this, SLOT(_loadCustomWidgetFromFile()));
// Audio output // Audio output
ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted()); ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
...@@ -1302,8 +1132,7 @@ void MainWindow::setActiveUAS(UASInterface* uas) ...@@ -1302,8 +1132,7 @@ void MainWindow::setActiveUAS(UASInterface* uas)
Q_UNUSED(uas); Q_UNUSED(uas);
if (settings.contains(getWindowStateKey())) if (settings.contains(getWindowStateKey()))
{ {
SubMainWindow *win = qobject_cast<SubMainWindow*>(centerStack->currentWidget()); restoreState(settings.value(getWindowStateKey()).toByteArray());
win->restoreState(settings.value(getWindowStateKey()).toByteArray());
} }
} }
...@@ -1316,10 +1145,6 @@ void MainWindow::UASSpecsChanged(int uas) ...@@ -1316,10 +1145,6 @@ void MainWindow::UASSpecsChanged(int uas)
void MainWindow::UASCreated(UASInterface* 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 // The UAS actions are not enabled without connection to system
ui.actionLiftoff->setEnabled(true); ui.actionLiftoff->setEnabled(true);
ui.actionLand->setEnabled(true); ui.actionLand->setEnabled(true);
...@@ -1390,31 +1215,27 @@ void MainWindow::UASCreated(UASInterface* uas) ...@@ -1390,31 +1215,27 @@ void MainWindow::UASCreated(UASInterface* uas)
break; break;
} }
connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int))); 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(valueChanged(int,QString,QString,QVariant,quint64)), this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)));
connect(uas, SIGNAL(misconfigurationDetected(UASInterface*)), this, SLOT(handleMisconfiguration(UASInterface*))); connect(uas, SIGNAL(misconfigurationDetected(UASInterface*)), this, SLOT(handleMisconfiguration(UASInterface*)));
// HIL // HIL
showHILConfigurationWidget(uas); _showHILConfigurationWidgets();
if (!linechartWidget) if (!linechartWidget)
{ {
linechartWidget = new Linecharts(this); linechartWidget = new Linecharts(this);
linechartWidget->setVisible(false);
} }
linechartWidget->addSource(mavlinkDecoder); linechartWidget->addSource(mavlinkDecoder);
if (engineeringView->centralWidget() != linechartWidget) if (_engineeringView != linechartWidget)
{ {
engineeringView->setCentralWidget(linechartWidget); _engineeringView = linechartWidget;
linechartWidget->show();
} }
// Load default custom widgets for this autopilot type
loadCustomWidgetsFromDefaults(uas->getSystemTypeName(), uas->getAutopilotTypeName());
// Reload view state in case new widgets were added // Reload view state in case new widgets were added
loadViewState(); _loadCurrentViewState();
} }
void MainWindow::UASDeleted(UASInterface* uas) void MainWindow::UASDeleted(UASInterface* uas)
...@@ -1423,104 +1244,146 @@ void MainWindow::UASDeleted(UASInterface* uas) ...@@ -1423,104 +1244,146 @@ void MainWindow::UASDeleted(UASInterface* uas)
// TODO: Update the UI when a UAS is deleted // TODO: Update the UI when a UAS is deleted
} }
/** /// Stores the state of the toolbar, status bar and widgets associated with the current view
* Stores the current view state void MainWindow::_storeCurrentViewState(void)
*/
void MainWindow::storeViewState()
{ {
// Save current state // HIL dock widgets are dynamic and are not part of the saved state
SubMainWindow *win = qobject_cast<SubMainWindow*>(centerStack->currentWidget()); _hideAllHilDockWidgets();
QList<QDockWidget*> widgets = win->findChildren<QDockWidget*>();
QString widgetnames = ""; // Save list of visible widgets
for (int i=0;i<widgets.size();i++)
{ bool firstWidget = true;
widgetnames += widgets[i]->objectName() + ","; 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() + "WIDGETS",widgetnames); settings.setValue(getWindowStateKey(), saveState());
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(getWindowGeometryKey(), saveGeometry()); 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 QWidget* centerView;
int index = settings.value(getWindowStateKey()+"CENTER_WIDGET", -1).toInt(); QString defaultWidgets;
if (index != -1) switch (_currentView) {
{
centerStack->setCurrentIndex(index);
}
else
{
// Hide custom widgets
if (detectionDockWidget) detectionDockWidget->hide();
if (watchdogControlDockWidget) watchdogControlDockWidget->hide();
// Load defaults
switch (currentView)
{
case VIEW_SETUP: case VIEW_SETUP:
centerStack->setCurrentWidget(setupView); _buildSetupView();
centerView = _setupView;
break; break;
case VIEW_ENGINEER: case VIEW_ENGINEER:
centerStack->setCurrentWidget(engineeringView); _buildEngineeringView();
centerView = _engineeringView;
defaultWidgets = "MAVLINK_INSPECTOR_DOCKWIDGET,PARAMETER_INTERFACE_DOCKWIDGET,FILE_VIEW_DOCKWIDGET,HEAD_UP_DISPLAY_DOCKWIDGET";
break; break;
default: // Default to the flight view
case VIEW_FLIGHT: case VIEW_FLIGHT:
centerStack->setCurrentWidget(pilotView); _buildPilotView();
centerView = _pilotView;
defaultWidgets = "COMMUNICATION_CONSOLE_DOCKWIDGET,UAS_INFO_INFOVIEW_DOCKWIDGET";
break; break;
case VIEW_MISSION: case VIEW_MISSION:
centerStack->setCurrentWidget(plannerView); _buildPlannerView();
centerView = _plannerView;
defaultWidgets = "UNMANNED_SYSTEM_LIST_DOCKWIDGET,WAYPOINT_LIST_DOCKWIDGET";
break; break;
case VIEW_SIMULATION: 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; break;
case VIEW_TERMINAL: case VIEW_TERMINAL:
centerStack->setCurrentWidget(terminalView); _buildTerminalView();
centerView = _terminalView;
break; break;
case VIEW_GOOGLEEARTH: case VIEW_GOOGLEEARTH:
centerStack->setCurrentWidget(googleEarthView); _buildGoogleEarthView();
centerView = _googleEarthView;
break; break;
case VIEW_LOCAL3D: case VIEW_LOCAL3D:
centerStack->setCurrentWidget(local3DView); _buildLocal3DView();
centerView = _local3DView;
break; 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())) {
if (settings.contains(getWindowStateKey() + "WIDGETS")) restoreState(settings.value(getWindowStateKey()).toByteArray());
{
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()))
{ // HIL dock widget are dynamic and don't take part in the saved window state, so this
SubMainWindow *win = qobject_cast<SubMainWindow*>(centerStack->currentWidget()); // need to happen after we restore state
win->restoreState(settings.value(getWindowStateKey()).toByteArray()); _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); QAction* action = dynamic_cast<QAction*>(QObject::sender());
ui.actionAdvanced_Mode->setChecked(isAdvancedMode); Q_ASSERT(action);
settings.setValue("ADVANCED_MODE",isAdvancedMode);
_showDockWidget(action->data().toString(), show);
} }
void MainWindow::handleMisconfiguration(UASInterface* uas) void MainWindow::handleMisconfiguration(UASInterface* uas)
{ {
static QTime lastTime; static QTime lastTime;
...@@ -1551,88 +1414,88 @@ void MainWindow::handleMisconfiguration(UASInterface* uas) ...@@ -1551,88 +1414,88 @@ void MainWindow::handleMisconfiguration(UASInterface* uas)
void MainWindow::loadEngineerView() void MainWindow::loadEngineerView()
{ {
if (currentView != VIEW_ENGINEER) if (_currentView != VIEW_ENGINEER)
{ {
storeViewState(); _storeCurrentViewState();
currentView = VIEW_ENGINEER; _currentView = VIEW_ENGINEER;
ui.actionEngineersView->setChecked(true); ui.actionEngineersView->setChecked(true);
loadViewState(); _loadCurrentViewState();
} }
} }
void MainWindow::loadOperatorView() void MainWindow::loadOperatorView()
{ {
if (currentView != VIEW_MISSION) if (_currentView != VIEW_MISSION)
{ {
storeViewState(); _storeCurrentViewState();
currentView = VIEW_MISSION; _currentView = VIEW_MISSION;
ui.actionMissionView->setChecked(true); ui.actionMissionView->setChecked(true);
loadViewState(); _loadCurrentViewState();
} }
} }
void MainWindow::loadSetupView() void MainWindow::loadSetupView()
{ {
if (currentView != VIEW_SETUP) if (_currentView != VIEW_SETUP)
{ {
storeViewState(); _storeCurrentViewState();
currentView = VIEW_SETUP; _currentView = VIEW_SETUP;
ui.actionSetup->setChecked(true); ui.actionSetup->setChecked(true);
loadViewState(); _loadCurrentViewState();
} }
} }
void MainWindow::loadTerminalView() void MainWindow::loadTerminalView()
{ {
if (currentView != VIEW_TERMINAL) if (_currentView != VIEW_TERMINAL)
{ {
storeViewState(); _storeCurrentViewState();
currentView = VIEW_TERMINAL; _currentView = VIEW_TERMINAL;
ui.actionTerminalView->setChecked(true); ui.actionTerminalView->setChecked(true);
loadViewState(); _loadCurrentViewState();
} }
} }
void MainWindow::loadGoogleEarthView() void MainWindow::loadGoogleEarthView()
{ {
if (currentView != VIEW_GOOGLEEARTH) if (_currentView != VIEW_GOOGLEEARTH)
{ {
storeViewState(); _storeCurrentViewState();
currentView = VIEW_GOOGLEEARTH; _currentView = VIEW_GOOGLEEARTH;
ui.actionGoogleEarthView->setChecked(true); ui.actionGoogleEarthView->setChecked(true);
loadViewState(); _loadCurrentViewState();
} }
} }
void MainWindow::loadLocal3DView() void MainWindow::loadLocal3DView()
{ {
if (currentView != VIEW_LOCAL3D) if (_currentView != VIEW_LOCAL3D)
{ {
storeViewState(); _storeCurrentViewState();
currentView = VIEW_LOCAL3D; _currentView = VIEW_LOCAL3D;
ui.actionLocal3DView->setChecked(true); ui.actionLocal3DView->setChecked(true);
loadViewState(); _loadCurrentViewState();
} }
} }
void MainWindow::loadPilotView() void MainWindow::loadPilotView()
{ {
if (currentView != VIEW_FLIGHT) if (_currentView != VIEW_FLIGHT)
{ {
storeViewState(); _storeCurrentViewState();
currentView = VIEW_FLIGHT; _currentView = VIEW_FLIGHT;
ui.actionFlightView->setChecked(true); ui.actionFlightView->setChecked(true);
loadViewState(); _loadCurrentViewState();
} }
} }
void MainWindow::loadSimulationView() void MainWindow::loadSimulationView()
{ {
if (currentView != VIEW_SIMULATION) if (_currentView != VIEW_SIMULATION)
{ {
storeViewState(); _storeCurrentViewState();
currentView = VIEW_SIMULATION; _currentView = VIEW_SIMULATION;
ui.actionSimulationView->setChecked(true); ui.actionSimulationView->setChecked(true);
loadViewState(); _loadCurrentViewState();
} }
} }
...@@ -1641,11 +1504,6 @@ QList<QAction*> MainWindow::listLinkMenuActions() ...@@ -1641,11 +1504,6 @@ QList<QAction*> MainWindow::listLinkMenuActions()
return ui.menuNetwork->actions(); return ui.menuNetwork->actions();
} }
bool MainWindow::dockWidgetTitleBarsEnabled() const
{
return menuActionHelper->dockWidgetTitleBarsEnabled();
}
/// @brief Hides the spash screen if it is currently being shown /// @brief Hides the spash screen if it is currently being shown
void MainWindow::hideSplashScreen(void) void MainWindow::hideSplashScreen(void)
{ {
......
...@@ -47,7 +47,6 @@ This file is part of the QGROUNDCONTROL project ...@@ -47,7 +47,6 @@ This file is part of the QGROUNDCONTROL project
#include "CameraView.h" #include "CameraView.h"
#include "UASListWidget.h" #include "UASListWidget.h"
#include "MAVLinkSimulationLink.h" #include "MAVLinkSimulationLink.h"
#include "submainwindow.h"
#include "input/JoystickInput.h" #include "input/JoystickInput.h"
#if (defined QGC_MOUSE_ENABLED_WIN) | (defined QGC_MOUSE_ENABLED_LINUX) #if (defined QGC_MOUSE_ENABLED_WIN) | (defined QGC_MOUSE_ENABLED_LINUX)
#include "Mouse6dofInput.h" #include "Mouse6dofInput.h"
...@@ -68,6 +67,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -68,6 +67,7 @@ This file is part of the QGROUNDCONTROL project
#include "MAVLinkDecoder.h" #include "MAVLinkDecoder.h"
#include "QGCUASFileViewMulti.h" #include "QGCUASFileViewMulti.h"
#include "QGCFlightGearLink.h" #include "QGCFlightGearLink.h"
#include "QGCToolWidget.h"
class QGCMapTool; class QGCMapTool;
class QGCMAVLinkMessageSender; class QGCMAVLinkMessageSender;
...@@ -118,9 +118,6 @@ public: ...@@ -118,9 +118,6 @@ public:
return autoReconnect; return autoReconnect;
} }
/** @brief Get title bar mode setting */
bool dockWidgetTitleBarsEnabled() const;
/** @brief Get low power mode setting */ /** @brief Get low power mode setting */
bool lowPowerModeEnabled() const bool lowPowerModeEnabled() const
{ {
...@@ -165,8 +162,6 @@ public slots: ...@@ -165,8 +162,6 @@ public slots:
void stopVideoCapture(); void stopVideoCapture();
void saveScreen(); void saveScreen();
/** @brief Sets advanced mode, allowing for editing of tool widget locations */
void setAdvancedMode(bool isAdvancedMode);
void handleMisconfiguration(UASInterface* uas); void handleMisconfiguration(UASInterface* uas);
/** @brief Load configuration views */ /** @brief Load configuration views */
void loadSetupView(); void loadSetupView();
...@@ -192,48 +187,20 @@ public slots: ...@@ -192,48 +187,20 @@ public slots:
/** @brief Show the project roadmap */ /** @brief Show the project roadmap */
void showRoadMap(); void showRoadMap();
/** @breif Enable title bars on dock widgets when no in advanced mode */
void enableDockWidgetTitleBars(bool enabled);
/** @brief Automatically reconnect last link */ /** @brief Automatically reconnect last link */
void enableAutoReconnect(bool enabled); void enableAutoReconnect(bool enabled);
/** @brief Save power by reducing update rates */ /** @brief Save power by reducing update rates */
void enableLowPowerMode(bool enabled) { lowPowerMode = enabled; } 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); 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 */ /** @brief Update the window name */
void configureWindowName(); void configureWindowName();
void commsWidgetDestroyed(QObject *obj); void commsWidgetDestroyed(QObject *obj);
protected slots: protected slots:
void showDockWidget(const QString &name, bool show);
/** /**
* @brief Unchecks the normalActionItem. * @brief Unchecks the normalActionItem.
* Used as a triggered() callback by the fullScreenAction to make sure only one of it or the * Used as a triggered() callback by the fullScreenAction to make sure only one of it or the
...@@ -271,54 +238,15 @@ protected: ...@@ -271,54 +238,15 @@ protected:
VIEW_MISSION, // Mission/Map/Plan view mode. Used for setting mission waypoints and high-level system commands. 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_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. 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. 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_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_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_GOOGLEEARTH // 3D Google Earth view. A 3D terrain view, though the vehicle is still 2D.
} VIEW_SECTIONS; } 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 */ /** @brief Catch window resize events */
void resizeEvent(QResizeEvent * event); 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 connectCommonActions();
void loadSettings(); void loadSettings();
...@@ -328,20 +256,8 @@ protected: ...@@ -328,20 +256,8 @@ protected:
LinkInterface* udpLink; LinkInterface* udpLink;
QSettings settings; QSettings settings;
QStackedWidget *centerStack;
QActionGroup* centerStackActionGroup; QActionGroup* centerStackActionGroup;
// Center widgets
QPointer<SubMainWindow> plannerView;
QPointer<SubMainWindow> pilotView;
QPointer<SubMainWindow> setupView;
QPointer<SubMainWindow> softwareConfigView;
QPointer<SubMainWindow> engineeringView;
QPointer<SubMainWindow> simView;
QPointer<SubMainWindow> terminalView;
QPointer<SubMainWindow> googleEarthView;
QPointer<SubMainWindow> local3DView;
// Center widgets // Center widgets
QPointer<Linecharts> linechartWidget; QPointer<Linecharts> linechartWidget;
#ifdef QGC_OSG_ENABLED #ifdef QGC_OSG_ENABLED
...@@ -352,38 +268,12 @@ protected: ...@@ -352,38 +268,12 @@ protected:
#endif #endif
QPointer<QGCFirmwareUpdate> firmwareUpdateWidget; QPointer<QGCFirmwareUpdate> firmwareUpdateWidget;
// Dock widgets
QPointer<QDockWidget> controlDockWidget;
QPointer<QDockWidget> controlParameterWidget;
QPointer<QDockWidget> infoDockWidget;
QPointer<QDockWidget> cameraDockWidget;
QPointer<QDockWidget> listDockWidget;
QPointer<QDockWidget> waypointsDockWidget;
QPointer<QDockWidget> detectionDockWidget;
QPointer<QDockWidget> debugConsoleDockWidget;
QPointer<QDockWidget> parametersDockWidget;
QPointer<QDockWidget> headDown1DockWidget;
QPointer<QDockWidget> headDown2DockWidget;
QPointer<QDockWidget> watchdogControlDockWidget;
QPointer<QDockWidget> headUpDockWidget;
QPointer<QDockWidget> video1DockWidget;
QPointer<QDockWidget> video2DockWidget;
QPointer<QDockWidget> rgbd1DockWidget;
QPointer<QDockWidget> rgbd2DockWidget;
QPointer<QDockWidget> logPlayerDockWidget;
QPointer<QDockWidget> hsiDockWidget;
QPointer<QDockWidget> rcViewDockWidget;
QPointer<QDockWidget> hudDockWidget;
QPointer<QGCToolBar> toolBar; QPointer<QGCToolBar> toolBar;
QPointer<QDockWidget> mavlinkInspectorWidget; QPointer<QDockWidget> mavlinkInspectorWidget;
QPointer<MAVLinkDecoder> mavlinkDecoder; QPointer<MAVLinkDecoder> mavlinkDecoder;
QPointer<QDockWidget> mavlinkSenderWidget; QPointer<QDockWidget> mavlinkSenderWidget;
QGCMAVLinkLogPlayer* logPlayer; QGCMAVLinkLogPlayer* logPlayer;
QMap<int, QDockWidget*> hilDocks;
QPointer<QGCUASFileViewMulti> fileWidget; QPointer<QGCUASFileViewMulti> fileWidget;
...@@ -416,7 +306,6 @@ protected: ...@@ -416,7 +306,6 @@ protected:
QTimer* videoTimer; QTimer* videoTimer;
bool autoReconnect; bool autoReconnect;
MAVLinkSimulationLink* simulationLink; MAVLinkSimulationLink* simulationLink;
Qt::WindowStates windowStateVal;
bool lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets bool lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets
QGCFlightGearLink* fgLink; QGCFlightGearLink* fgLink;
QTimer windowNameUpdateTimer; QTimer windowNameUpdateTimer;
...@@ -424,6 +313,9 @@ protected: ...@@ -424,6 +313,9 @@ protected:
private slots: private slots:
void _addLinkMenu(LinkInterface* link); void _addLinkMenu(LinkInterface* link);
void _showDockWidgetAction(bool show);
void _loadCustomWidgetFromFile(void);
void _createNewCustomWidget(void);
private: private:
/// Constructor is private since all creation should be through MainWindow::_create /// Constructor is private since all creation should be through MainWindow::_create
...@@ -431,16 +323,69 @@ private: ...@@ -431,16 +323,69 @@ private:
void _openUrl(const QString& url, const QString& errorMessage); void _openUrl(const QString& url, const QString& errorMessage);
// Center widgets
QPointer<QWidget> _plannerView;
QPointer<QWidget> _pilotView;
QPointer<QWidget> _setupView;
QPointer<QWidget> _engineeringView;
QPointer<QWidget> _simView;
QPointer<QWidget> _terminalView;
QPointer<QWidget> _googleEarthView;
QPointer<QWidget> _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<QString, QDockWidget*> _mapName2DockWidget;
QMap<int, QDockWidget*> _mapUasId2HilDockWidget;
QMap<QDockWidget*, QAction*> _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<QGCToolWidget*> _customWidgets;
QVBoxLayout* _centralLayout;
QList<QObject*> commsWidgetList; QList<QObject*> commsWidgetList;
QMap<QString,QString> customWidgetNameToFilenameMap;
MenuActionHelper *menuActionHelper; MenuActionHelper *menuActionHelper;
Ui::MainWindow ui; 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 getWindowStateKey();
QString getWindowGeometryKey(); QString getWindowGeometryKey();
......
...@@ -62,7 +62,6 @@ ...@@ -62,7 +62,6 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionMuteAudioOutput"/> <addaction name="actionMuteAudioOutput"/>
<addaction name="actionSettings"/> <addaction name="actionSettings"/>
<addaction name="actionAdvanced_Mode"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionExit"/> <addaction name="actionExit"/>
</widget> </widget>
......
#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
#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
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