Commit 099c7a0a authored by Don Gagne's avatar Don Gagne

Merge pull request #2169 from DonLakeFlyer/EvilSingletons

Remove remaining singletons
parents bd42dc42 e4e71de7
......@@ -239,7 +239,6 @@ HEADERS += \
src/QGCPalette.h \
src/QGCQmlWidgetHolder.h \
src/QGCQuickWidget.h \
src/QGCSingleton.h \
src/QGCTemporaryFile.h \
src/QGCToolbox.h \
src/QmlControls/CoordinateVector.h \
......@@ -353,7 +352,6 @@ SOURCES += \
src/QGCPalette.cc \
src/QGCQmlWidgetHolder.cpp \
src/QGCQuickWidget.cc \
src/QGCSingleton.cc \
src/QGCTemporaryFile.cc \
src/QGCToolbox.cc \
src/QGCGeo.cc \
......
......@@ -27,9 +27,8 @@
#include "ArduCopterFirmwarePlugin.h"
#include "Generic/GenericFirmwarePlugin.h"
IMPLEMENT_QGC_SINGLETON(ArduCopterFirmwarePlugin, ArduCopterFirmwarePlugin)
APMCopterMode::APMCopterMode(uint32_t mode, bool settable) : APMCustomMode(mode, settable)
APMCopterMode::APMCopterMode(uint32_t mode, bool settable) :
APMCustomMode(mode, settable)
{
QMap<uint32_t,QString> enumToString;
enumToString.insert(STABILIZE, "Stabilize");
......
......@@ -61,16 +61,9 @@ public:
class ArduCopterFirmwarePlugin : public APMFirmwarePlugin
{
Q_OBJECT
DECLARE_QGC_SINGLETON(ArduCopterFirmwarePlugin, ArduCopterFirmwarePlugin)
public:
protected:
/// All access to singleton is through instance()
ArduCopterFirmwarePlugin(void);
private:
};
#endif
......@@ -27,9 +27,8 @@
#include "ArduPlaneFirmwarePlugin.h"
#include "Generic/GenericFirmwarePlugin.h"
IMPLEMENT_QGC_SINGLETON(ArduPlaneFirmwarePlugin, ArduPlaneFirmwarePlugin)
APMPlaneMode::APMPlaneMode(uint32_t mode, bool settable) : APMCustomMode(mode, settable)
APMPlaneMode::APMPlaneMode(uint32_t mode, bool settable)
: APMCustomMode(mode, settable)
{
QMap<uint32_t,QString> enumToString;
enumToString.insert(MANUAL, "Manual");
......
......@@ -59,16 +59,9 @@ public:
class ArduPlaneFirmwarePlugin : public APMFirmwarePlugin
{
Q_OBJECT
DECLARE_QGC_SINGLETON(ArduPlaneFirmwarePlugin, ArduPlaneFirmwarePlugin)
public:
protected:
/// All access to singleton is through instance()
ArduPlaneFirmwarePlugin(void);
private:
};
#endif
......@@ -27,9 +27,8 @@
#include "ArduRoverFirmwarePlugin.h"
#include "Generic/GenericFirmwarePlugin.h"
IMPLEMENT_QGC_SINGLETON(ArduRoverFirmwarePlugin, ArduRoverFirmwarePlugin)
APMRoverMode::APMRoverMode(uint32_t mode, bool settable) : APMCustomMode(mode, settable)
APMRoverMode::APMRoverMode(uint32_t mode, bool settable)
: APMCustomMode(mode, settable)
{
QMap<uint32_t,QString> enumToString;
enumToString.insert(MANUAL, "Manual");
......
......@@ -59,16 +59,9 @@ public:
class ArduRoverFirmwarePlugin : public APMFirmwarePlugin
{
Q_OBJECT
DECLARE_QGC_SINGLETON(ArduRoverFirmwarePlugin, ArduRoverFirmwarePlugin)
public:
protected:
/// All access to singleton is through instance()
ArduRoverFirmwarePlugin(void);
private:
};
#endif
......@@ -27,7 +27,6 @@
#ifndef FirmwarePlugin_H
#define FirmwarePlugin_H
#include "QGCSingleton.h"
#include "QGCMAVLink.h"
#include "VehicleComponent.h"
#include "AutoPilotPlugin.h"
......@@ -46,7 +45,7 @@ class Vehicle;
/// in the base class supports mavlink generic firmware. Override the base clase virtuals
/// to create you firmware specific plugin.
class FirmwarePlugin : public QGCSingleton
class FirmwarePlugin : public QObject
{
Q_OBJECT
......@@ -110,9 +109,6 @@ public:
/// Adds the parameter meta data to the Fact
virtual void addMetaDataToFact(Fact* fact) = 0;
protected:
FirmwarePlugin(void) { };
};
#endif
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
......@@ -31,51 +31,67 @@
#include "APM/ArduRoverFirmwarePlugin.h"
#include "PX4/PX4FirmwarePlugin.h"
FirmwarePluginManager::FirmwarePluginManager(QGCApplication* app)
: QGCTool(app)
, _arduCopterFirmwarePlugin(NULL)
, _arduPlaneFirmwarePlugin(NULL)
, _arduRoverFirmwarePlugin(NULL)
, _genericFirmwarePlugin(NULL)
, _px4FirmwarePlugin(NULL)
{
}
FirmwarePluginManager::~FirmwarePluginManager()
{
delete _arduCopterFirmwarePlugin;
delete _arduPlaneFirmwarePlugin;
delete _arduRoverFirmwarePlugin;
delete _genericFirmwarePlugin;
delete _px4FirmwarePlugin;
}
FirmwarePlugin* FirmwarePluginManager::firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType)
{
switch (autopilotType) {
case MAV_AUTOPILOT_ARDUPILOTMEGA:
switch (vehicleType) {
case MAV_TYPE_QUADROTOR:
case MAV_TYPE_HEXAROTOR:
case MAV_TYPE_OCTOROTOR:
case MAV_TYPE_TRICOPTER:
case MAV_TYPE_COAXIAL:
case MAV_TYPE_HELICOPTER:
return ArduCopterFirmwarePlugin::instance();
break;
case MAV_TYPE_FIXED_WING:
return ArduPlaneFirmwarePlugin::instance();
break;
case MAV_TYPE_GROUND_ROVER:
case MAV_TYPE_SURFACE_BOAT:
case MAV_TYPE_SUBMARINE:
return ArduRoverFirmwarePlugin::instance();
break;
case MAV_TYPE_GENERIC:
case MAV_TYPE_ANTENNA_TRACKER:
case MAV_TYPE_GCS:
case MAV_TYPE_AIRSHIP:
case MAV_TYPE_FREE_BALLOON:
case MAV_TYPE_ROCKET:
case MAV_TYPE_FLAPPING_WING:
case MAV_TYPE_KITE:
case MAV_TYPE_ONBOARD_CONTROLLER:
case MAV_TYPE_VTOL_DUOROTOR:
case MAV_TYPE_VTOL_QUADROTOR:
case MAV_TYPE_VTOL_TILTROTOR:
case MAV_TYPE_VTOL_RESERVED2:
case MAV_TYPE_VTOL_RESERVED3:
case MAV_TYPE_VTOL_RESERVED4:
case MAV_TYPE_VTOL_RESERVED5:
case MAV_TYPE_GIMBAL:
default:
return GenericFirmwarePlugin::instance();
break;
case MAV_AUTOPILOT_ARDUPILOTMEGA:
switch (vehicleType) {
case MAV_TYPE_QUADROTOR:
case MAV_TYPE_HEXAROTOR:
case MAV_TYPE_OCTOROTOR:
case MAV_TYPE_TRICOPTER:
case MAV_TYPE_COAXIAL:
case MAV_TYPE_HELICOPTER:
if (!_arduCopterFirmwarePlugin) {
_arduCopterFirmwarePlugin = new ArduCopterFirmwarePlugin;
}
return _arduCopterFirmwarePlugin;
case MAV_TYPE_FIXED_WING:
if (!_arduPlaneFirmwarePlugin) {
_arduPlaneFirmwarePlugin = new ArduPlaneFirmwarePlugin;
}
case MAV_AUTOPILOT_PX4:
return PX4FirmwarePlugin::instance();
return _arduPlaneFirmwarePlugin;
case MAV_TYPE_GROUND_ROVER:
case MAV_TYPE_SURFACE_BOAT:
case MAV_TYPE_SUBMARINE:
if (!_arduRoverFirmwarePlugin) {
_arduRoverFirmwarePlugin = new ArduRoverFirmwarePlugin;
}
return _arduRoverFirmwarePlugin;
default:
return GenericFirmwarePlugin::instance();
break;
}
case MAV_AUTOPILOT_PX4:
if (!_px4FirmwarePlugin) {
_px4FirmwarePlugin = new PX4FirmwarePlugin;
}
return _px4FirmwarePlugin;
default:
break;
}
if (!_genericFirmwarePlugin) {
_genericFirmwarePlugin = new GenericFirmwarePlugin;
}
return _genericFirmwarePlugin;
}
......@@ -34,6 +34,11 @@
#include "QGCToolbox.h"
class QGCApplication;
class ArduCopterFirmwarePlugin;
class ArduPlaneFirmwarePlugin;
class ArduRoverFirmwarePlugin;
class PX4FirmwarePlugin;
class GenericFirmwarePlugin;
/// FirmwarePluginManager is a singleton which is used to return the correct FirmwarePlugin for a MAV_AUTOPILOT type.
......@@ -42,13 +47,21 @@ class FirmwarePluginManager : public QGCTool
Q_OBJECT
public:
FirmwarePluginManager(QGCApplication* app) : QGCTool(app) { }
FirmwarePluginManager(QGCApplication* app);
~FirmwarePluginManager();
/// Returns appropriate plugin for autopilot type.
/// @param autopilotType Type of autopilot to return plugin for.
/// @param vehicleType Vehicle type of autopilot to return plugin for.
/// @return Singleton FirmwarePlugin instance for the specified MAV_AUTOPILOT.
FirmwarePlugin* firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType);
private:
ArduCopterFirmwarePlugin* _arduCopterFirmwarePlugin;
ArduPlaneFirmwarePlugin* _arduPlaneFirmwarePlugin;
ArduRoverFirmwarePlugin* _arduRoverFirmwarePlugin;
GenericFirmwarePlugin* _genericFirmwarePlugin;
PX4FirmwarePlugin* _px4FirmwarePlugin;
};
#endif
......@@ -29,13 +29,6 @@
#include <QDebug>
IMPLEMENT_QGC_SINGLETON(GenericFirmwarePlugin, FirmwarePlugin)
GenericFirmwarePlugin::GenericFirmwarePlugin(void)
{
}
QList<VehicleComponent*> GenericFirmwarePlugin::componentsForVehicle(AutoPilotPlugin* vehicle)
{
Q_UNUSED(vehicle);
......
......@@ -32,8 +32,6 @@
class GenericFirmwarePlugin : public FirmwarePlugin
{
Q_OBJECT
DECLARE_QGC_SINGLETON(GenericFirmwarePlugin, FirmwarePlugin)
public:
// Overrides from FirmwarePlugin
......@@ -49,9 +47,6 @@ public:
virtual bool sendHomePositionToVehicle(void);
virtual void addMetaDataToFact(Fact* fact);
virtual QString getDefaultComponentIdParam(void) const { return QString(); }
private:
GenericFirmwarePlugin(void);
};
#endif
......@@ -29,8 +29,6 @@
#include <QDebug>
IMPLEMENT_QGC_SINGLETON(PX4FirmwarePlugin, FirmwarePlugin)
enum PX4_CUSTOM_MAIN_MODE {
PX4_CUSTOM_MAIN_MODE_MANUAL = 1,
PX4_CUSTOM_MAIN_MODE_ALTCTL,
......@@ -88,11 +86,6 @@ static const struct Modes2Name rgModes2Name[] = {
};
PX4FirmwarePlugin::PX4FirmwarePlugin(void)
{
}
QList<VehicleComponent*> PX4FirmwarePlugin::componentsForVehicle(AutoPilotPlugin* vehicle)
{
Q_UNUSED(vehicle);
......
......@@ -34,11 +34,8 @@ class PX4FirmwarePlugin : public FirmwarePlugin
{
Q_OBJECT
DECLARE_QGC_SINGLETON(PX4FirmwarePlugin, FirmwarePlugin)
public:
// Overrides from FirmwarePlugin
virtual bool isCapable(FirmwareCapabilities capabilities);
virtual QList<VehicleComponent*> componentsForVehicle(AutoPilotPlugin* vehicle);
virtual QStringList flightModes(void);
......@@ -52,9 +49,6 @@ public:
virtual QString getDefaultComponentIdParam(void) const { return QString("SYS_AUTOSTART"); }
private:
/// All access to singleton is through AutoPilotPluginManager::instance
PX4FirmwarePlugin(void);
PX4ParameterMetaData _parameterMetaData;
};
......
......@@ -49,7 +49,6 @@
#include "QGCMessageBox.h"
#include "MainWindow.h"
#include "UDPLink.h"
#include "QGCSingleton.h"
#include "LinkManager.h"
#include "HomePositionManager.h"
#include "UASMessageHandler.h"
......@@ -322,7 +321,11 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
QGCApplication::~QGCApplication()
{
_destroySingletons();
MainWindow* mainWindow = MainWindow::instance();
if (mainWindow) {
delete mainWindow;
}
shutdownVideoStreaming();
delete _toolbox;
}
......@@ -433,8 +436,6 @@ bool QGCApplication::_initForNormalAppBoot(void)
{
QSettings settings;
_createSingletons();
#ifdef __mobile__
_styleIsDark = false;
#else
......@@ -573,37 +574,6 @@ QGCApplication* qgcApp(void)
return QGCApplication::_app;
}
/// @brief We create all the non-ui based singletons here instead of allowing them to be created randomly
/// by calls to instance. The reason being that depending on boot sequence the singleton may end
/// up being creating on something other than the main thread.
void QGCApplication::_createSingletons(void)
{
// No dependencies
FirmwarePlugin* firmwarePlugin = GenericFirmwarePlugin::_createSingleton();
Q_UNUSED(firmwarePlugin);
Q_ASSERT(firmwarePlugin);
// No dependencies
firmwarePlugin = PX4FirmwarePlugin::_createSingleton();
firmwarePlugin = ArduCopterFirmwarePlugin::_createSingleton();
firmwarePlugin = ArduPlaneFirmwarePlugin::_createSingleton();
firmwarePlugin = ArduRoverFirmwarePlugin::_createSingleton();
}
void QGCApplication::_destroySingletons(void)
{
MainWindow* mainWindow = MainWindow::instance();
if (mainWindow) {
delete mainWindow;
}
GenericFirmwarePlugin::_deleteSingleton();
PX4FirmwarePlugin::_deleteSingleton();
ArduCopterFirmwarePlugin::_deleteSingleton();
ArduPlaneFirmwarePlugin::_deleteSingleton();
ArduRoverFirmwarePlugin::_deleteSingleton();
}
void QGCApplication::informationMessageBoxOnMainThread(const QString& title, const QString& msg)
{
QGCMessageBox::information(title, msg);
......
......@@ -168,8 +168,6 @@ private slots:
void _missingParamsDisplay(void);
private:
void _createSingletons(void);
void _destroySingletons(void);
void _loadCurrentStyle(void);
static const char* _settingsVersionKey; ///< Settings key which hold settings version
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 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/>.
======================================================================*/
/// @file
/// @brief Base class for global singletons
///
/// @author Don Gagne <don@thegagnes.com>
#include "QGCSingleton.h"
#include "QGCApplication.h"
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 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/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef QGCSINGLETON_H
#define QGCSINGLETON_H
#include <QObject>
#include <QMutex>
/// @def DECLARE_QGC_SINGLETON
/// Include this macro in your Derived Class definition
/// @param className Derived Class name
/// @param interfaceName If your class is accessed through an interface specify that, if not specify Derived class name.
#define DECLARE_QGC_SINGLETON(className, interfaceName) \
public: \
static interfaceName* instance(bool nullOk = false); \
static void setMockInstance(interfaceName* mock); \
static interfaceName* _createSingleton(void); \
static void _deleteSingleton(void); \
private: \
static interfaceName* _instance; \
static interfaceName* _mockInstance; \
static interfaceName* _realInstance; \
/// @def IMPLEMENT_QGC_SINGLETON
/// Include this macro in your Derived Class implementation
/// @param className Derived Class name
/// @param interfaceName If your class is accessed through an interface specify that, if not specify Derived class name.
#define IMPLEMENT_QGC_SINGLETON(className, interfaceName) \
interfaceName* className::_instance = NULL; \
interfaceName* className::_mockInstance = NULL; \
interfaceName* className::_realInstance = NULL; \
\
interfaceName* className::_createSingleton(void) \
{ \
Q_ASSERT(_instance == NULL); \
_instance = new className; \
return _instance; \
} \
\
void className::_deleteSingleton(void) \
{ \
if (className::_instance) { \
className* instance = qobject_cast<className*>(className::_instance); \
Q_ASSERT_X(instance != NULL, "QGCSingleton", "If you hit this assert you may have forgotten to clear a Mock instance"); \
className::_instance = NULL; \
delete instance; \
} \
} \
\
interfaceName* className::instance(bool nullOk) \
{ \
if (!nullOk) { \
Q_ASSERT_X(_instance, "QGCSingleton", "Request for singleton that is NULL. If you hit this, then you have likely run into a startup or shutdown sequence bug (possibly intermittent)."); \
} \
return _instance; \
} \
\
void className::setMockInstance(interfaceName* mock) \
{ \
if (mock) { \
Q_ASSERT(_instance); \
Q_ASSERT(!_realInstance); \
\
_realInstance = _instance; \
_instance = dynamic_cast<interfaceName*>(mock); \
Q_ASSERT(_instance); \
_mockInstance = mock; \
} else { \
Q_ASSERT(_instance); \
Q_ASSERT(_realInstance); \
\
_instance = _realInstance; \
_realInstance = NULL; \
_mockInstance = NULL; \
} \
}
class QGCApplication;
class UnitTest;
/// This is the base class for all app global singletons
///
/// All global singletons are created/destroyed at boot time by QGCApplication::_createSingletons and destroyed by QGC::Application::_destroySingletons.
/// This is done in order to make sure they are all created on the main thread. As such no other code other than Unit Test
/// code has access to the constructor/destructor. QGCSingleton supports replacing singletons with a mock implementation.
/// In this case your object must derive from an interface which in turn derives from QGCSingleton. Youu can then use
/// the setMock method to add and remove you mock implementation. See HomePositionManager example usage. In order to provide the
/// appropriate methods to make all this work you need to use the DECLARE_QGC_SINGLETON and IMPLEMENT_QGC_SINGLETON
/// macros as follows:
/// @code{.unparsed}
/// // Header file
///
/// class MySingleton : public QGCSingleton {
/// Q_OBJECT
///
/// DECLARE_QGC_SINGLETON(MySingleton, MySingleton)
///
/// ...
///
/// private:
/// // Constructor/Desctructor private since all access is through the singleton methods
/// MySingleton(QObject* parent == NULL);
/// ~MySingleton();
///
/// ...
/// }
///
/// // Code file
///
/// IMPLEMENT_QGC_SINGLETON(MySingleton, MySingleton)
///
/// MySingleton::MySingleton(QObject* parent) :
/// QGCSigleton(parent)
/// {
/// }
///
/// // Other class methods...
///
/// @endcode
/// The example above does not use an inteface so the second parameter to the macro is the class name as well.
class QGCSingleton : public QObject
{
Q_OBJECT
};
#endif
......@@ -124,10 +124,6 @@ void UnitTest::init(void)
_expectMissedFileDialog = false;
_expectMissedMessageBox = false;
// Each test gets a clean global state
qgcApp()->_destroySingletons();
qgcApp()->_createSingletons();
MAVLinkProtocol::deleteTempLogFiles();
}
......@@ -152,8 +148,6 @@ void UnitTest::cleanup(void)
QEXPECT_FAIL("", "Expecting failure due internal testing", Continue);
}
QCOMPARE(_missedFileDialogCount, 0);
qgcApp()->_destroySingletons();
}
void UnitTest::setExpectedMessageBox(QMessageBox::StandardButton response)
......
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