Commit 7ffa27f8 authored by Don Gagne's avatar Don Gagne

New Singleton Manager

parent efcde338
...@@ -29,25 +29,7 @@ ...@@ -29,25 +29,7 @@
#include "Generic/GenericAutoPilotPlugin.h" #include "Generic/GenericAutoPilotPlugin.h"
#include "QGCApplication.h" #include "QGCApplication.h"
AutoPilotPluginManager* AutoPilotPluginManager::_instance = NULL; IMPLEMENT_QGC_SINGLETON(AutoPilotPluginManager, AutoPilotPluginManager)
AutoPilotPluginManager* AutoPilotPluginManager::instance(void)
{
if (_instance == NULL) {
_instance = new AutoPilotPluginManager(qgcApp());
Q_CHECK_PTR(_instance);
}
Q_ASSERT(_instance);
return _instance;
}
void AutoPilotPluginManager::deleteInstance(void)
{
_instance = NULL;
delete this;
}
AutoPilotPluginManager::AutoPilotPluginManager(QObject* parent) : AutoPilotPluginManager::AutoPilotPluginManager(QObject* parent) :
QGCSingleton(parent) QGCSingleton(parent)
......
...@@ -41,13 +41,10 @@ ...@@ -41,13 +41,10 @@
class AutoPilotPluginManager : public QGCSingleton class AutoPilotPluginManager : public QGCSingleton
{ {
Q_OBJECT Q_OBJECT
DECLARE_QGC_SINGLETON(AutoPilotPluginManager, AutoPilotPluginManager)
public: public:
/// @brief Returns the AutoPilotPluginManager singleton
static AutoPilotPluginManager* instance(void);
virtual void deleteInstance(void);
/// @brief Returns the singleton AutoPilot instance for the specified auto pilot type. /// @brief Returns the singleton AutoPilot instance for the specified auto pilot type.
/// @param autopilotType Specified using the MAV_AUTOPILOT_* values. /// @param autopilotType Specified using the MAV_AUTOPILOT_* values.
AutoPilotPlugin* getInstanceForAutoPilotPlugin(int autopilotType); AutoPilotPlugin* getInstanceForAutoPilotPlugin(int autopilotType);
...@@ -56,8 +53,6 @@ private: ...@@ -56,8 +53,6 @@ private:
/// All access to singleton is through AutoPilotPluginManager::instance /// All access to singleton is through AutoPilotPluginManager::instance
AutoPilotPluginManager(QObject* parent = NULL); AutoPilotPluginManager(QObject* parent = NULL);
static AutoPilotPluginManager* _instance;
QMap<int, AutoPilotPlugin*> _pluginMap; QMap<int, AutoPilotPlugin*> _pluginMap;
}; };
......
...@@ -54,7 +54,7 @@ void FlightModeConfigTest::init(void) ...@@ -54,7 +54,7 @@ void FlightModeConfigTest::init(void)
_mockUASManager = new MockUASManager(); _mockUASManager = new MockUASManager();
Q_ASSERT(_mockUASManager); Q_ASSERT(_mockUASManager);
UASManager::setMockUASManager(_mockUASManager); UASManager::setMockInstance(_mockUASManager);
_mockUAS = new MockUAS(); _mockUAS = new MockUAS();
Q_CHECK_PTR(_mockUAS); Q_CHECK_PTR(_mockUAS);
...@@ -126,21 +126,21 @@ void FlightModeConfigTest::init(void) ...@@ -126,21 +126,21 @@ void FlightModeConfigTest::init(void)
void FlightModeConfigTest::cleanup(void) void FlightModeConfigTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_configWidget); Q_ASSERT(_configWidget);
delete _configWidget; delete _configWidget;
Q_ASSERT(_mockUAS); Q_ASSERT(_mockUAS);
delete _mockUAS; delete _mockUAS;
UASManager::setMockUASManager(NULL); UASManager::setMockInstance(NULL);
Q_ASSERT(_mockUASManager); Q_ASSERT(_mockUASManager);
delete _mockUASManager; delete _mockUASManager;
_mapChannelCombo2Param.clear(); _mapChannelCombo2Param.clear();
_mapChannelCombo2ButtonGroup.clear(); _mapChannelCombo2ButtonGroup.clear();
UnitTest::cleanup();
} }
/// @brief Returns channel mapping for the specified parameters /// @brief Returns channel mapping for the specified parameters
......
...@@ -26,37 +26,16 @@ ...@@ -26,37 +26,16 @@
#include "FactSystem.h" #include "FactSystem.h"
#include "UASManager.h" #include "UASManager.h"
#include "QGCApplication.h"
#include <QtQml> #include <QtQml>
FactSystem* FactSystem::_instance = NULL; IMPLEMENT_QGC_SINGLETON(FactSystem, FactSystem)
QMutex FactSystem::_singletonLock;
const char* FactSystem::_factSystemQmlUri = "QGroundControl.FactSystem";
FactSystem* FactSystem::instance(void)
{
if(_instance == 0) {
_singletonLock.lock();
if (_instance == 0) {
_instance = new FactSystem(qgcApp());
Q_CHECK_PTR(_instance);
}
_singletonLock.unlock();
}
Q_ASSERT(_instance);
return _instance;
}
void FactSystem::deleteInstance(void) const char* FactSystem::_factSystemQmlUri = "QGroundControl.FactSystem";
{
_instance = NULL;
delete this;
}
FactSystem::FactSystem(QObject* parent, bool registerSingleton) : FactSystem::FactSystem(QObject* parent) :
QGCSingleton(parent, registerSingleton) QGCSingleton(parent)
{ {
qmlRegisterType<Fact>(_factSystemQmlUri, 1, 0, "Fact"); qmlRegisterType<Fact>(_factSystemQmlUri, 1, 0, "Fact");
qmlRegisterType<FactValidator>(_factSystemQmlUri, 1, 0, "FactValidator"); qmlRegisterType<FactValidator>(_factSystemQmlUri, 1, 0, "FactValidator");
......
...@@ -33,8 +33,6 @@ ...@@ -33,8 +33,6 @@
#include "QGCSingleton.h" #include "QGCSingleton.h"
#include "FactValidator.h" #include "FactValidator.h"
#include <QMutex>
/// FactSystem is a singleton which provides access to the Facts in the system /// FactSystem is a singleton which provides access to the Facts in the system
/// ///
/// The components of the FactSystem are a Fact which holds an individual value. FactMetaData holds /// The components of the FactSystem are a Fact which holds an individual value. FactMetaData holds
...@@ -47,22 +45,14 @@ class FactSystem : public QGCSingleton ...@@ -47,22 +45,14 @@ class FactSystem : public QGCSingleton
{ {
Q_OBJECT Q_OBJECT
public: DECLARE_QGC_SINGLETON(FactSystem, FactSystem)
/// Returns the FactSystem singleton
static FactSystem* instance(void);
/// Override from QGCSingleton
virtual void deleteInstance(void);
~FactSystem();
private: private:
/// All access to FactSystem is through FactSystem::instance, so constructor is private /// All access to FactSystem is through FactSystem::instance, so constructor is private
FactSystem(QObject* parent = NULL, bool registerSingleton = true); FactSystem(QObject* parent = NULL);
static QMutex _singletonLock; ///< Mutex to make calls to instance thread-safe ~FactSystem();
static FactSystem* _instance; ///< FactSystem singleton
static const char* _factSystemQmlUri; ///< URI for FactSystem QML imports static const char* _factSystemQmlUri; ///< URI for FactSystem QML imports
}; };
......
...@@ -175,7 +175,7 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) : ...@@ -175,7 +175,7 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) :
QGCApplication::~QGCApplication() QGCApplication::~QGCApplication()
{ {
destroySingletonsForUnitTest(); _destroySingletons();
} }
void QGCApplication::_initCommon(void) void QGCApplication::_initCommon(void)
...@@ -424,43 +424,33 @@ QGCApplication* qgcApp(void) ...@@ -424,43 +424,33 @@ QGCApplication* qgcApp(void)
/// up being creating on something other than the main thread. /// up being creating on something other than the main thread.
void QGCApplication::_createSingletons(void) void QGCApplication::_createSingletons(void)
{ {
// The order here is important since the singletons reference each other
LinkManager* linkManager = LinkManager::instance(); LinkManager* linkManager = LinkManager::_createSingleton();
Q_UNUSED(linkManager); Q_UNUSED(linkManager);
Q_ASSERT(linkManager); Q_ASSERT(linkManager);
UASManagerInterface* uasManager = UASManager::instance(); // Needs LinkManager
UASManagerInterface* uasManager = UASManager::_createSingleton();
Q_UNUSED(uasManager); Q_UNUSED(uasManager);
Q_ASSERT(uasManager); Q_ASSERT(uasManager);
AutoPilotPluginManager* pluginManager = AutoPilotPluginManager::instance(); // Need UASManager
AutoPilotPluginManager* pluginManager = AutoPilotPluginManager::_createSingleton();
Q_UNUSED(pluginManager); Q_UNUSED(pluginManager);
Q_ASSERT(pluginManager); Q_ASSERT(pluginManager);
// Must be after UASManager since FactSystem connects to UASManager // Needs UASManager
FactSystem* factSystem = FactSystem::instance(); FactSystem* factSystem = FactSystem::_createSingleton();
Q_UNUSED(factSystem); Q_UNUSED(factSystem);
Q_ASSERT(factSystem); Q_ASSERT(factSystem);
} }
void QGCApplication::destroySingletonsForUnitTest(void) void QGCApplication::_destroySingletons(void)
{ {
foreach(QGCSingleton* singleton, _singletons) { // Take down singletons in reverse order of creation
Q_ASSERT(singleton);
singleton->deleteInstance();
}
if (MainWindow::instance()) {
delete MainWindow::instance();
}
_singletons.clear();
}
void QGCApplication::registerSingleton(QGCSingleton* singleton) FactSystem::_deleteSingleton();
{ AutoPilotPluginManager::_deleteSingleton();
Q_ASSERT(singleton); UASManager::_deleteSingleton();
Q_ASSERT(!_singletons.contains(singleton)); LinkManager::_deleteSingleton();
_singletons.append(singleton);
} }
...@@ -84,16 +84,6 @@ public: ...@@ -84,16 +84,6 @@ public:
/// @brief Sets the flag to log all mavlink connections /// @brief Sets the flag to log all mavlink connections
void setPromptFlightDataSave(bool promptForSave); void setPromptFlightDataSave(bool promptForSave);
/// @brief All global singletons must be registered such that QGCApplication::destorySingletonsForUnitTest
/// can work correctly.
void registerSingleton(QGCSingleton* singleton);
/// @brief Creates non-ui based singletons for unit testing
void createSingletonsForUnitTest(void) { _createSingletons(); }
/// @brief Destroys all singletons. Used by unit test code to reset global state.
void destroySingletonsForUnitTest(void);
/// @brief Returns truee if unit test are being run /// @brief Returns truee if unit test are being run
bool runningUnitTests(void) { return _runningUnitTests; } bool runningUnitTests(void) { return _runningUnitTests; }
...@@ -114,6 +104,7 @@ public: ...@@ -114,6 +104,7 @@ public:
private: private:
void _createSingletons(void); void _createSingletons(void);
void _destroySingletons(void);
static const char* _settingsVersionKey; ///< Settings key which hold settings version static const char* _settingsVersionKey; ///< Settings key which hold settings version
static const char* _deleteAllSettingsKey; ///< If this settings key is set on boot, all settings will be deleted static const char* _deleteAllSettingsKey; ///< If this settings key is set on boot, all settings will be deleted
...@@ -124,9 +115,10 @@ private: ...@@ -124,9 +115,10 @@ private:
static const char* _savedFileMavlinkLogDirectoryName; ///< Name of mavlink log subdirectory static const char* _savedFileMavlinkLogDirectoryName; ///< Name of mavlink log subdirectory
static const char* _savedFileParameterDirectoryName; ///< Name of parameter subdirectory static const char* _savedFileParameterDirectoryName; ///< Name of parameter subdirectory
QList<QGCSingleton*> _singletons; ///< List of registered global singletons
bool _runningUnitTests; ///< true: running unit tests, false: normal app bool _runningUnitTests; ///< true: running unit tests, false: normal app
/// Unit Test have access to creating and destroying singletons
friend class UnitTest;
}; };
/// @brief Returns the QGCApplication object singleton. /// @brief Returns the QGCApplication object singleton.
......
...@@ -29,10 +29,8 @@ ...@@ -29,10 +29,8 @@
#include "QGCSingleton.h" #include "QGCSingleton.h"
#include "QGCApplication.h" #include "QGCApplication.h"
QGCSingleton::QGCSingleton(QObject* parent, bool registerSingleton) : QGCSingleton::QGCSingleton(QObject* parent) :
QObject(parent) QObject(parent)
{ {
if (registerSingleton) {
qgcApp()->registerSingleton(this);
}
} }
...@@ -22,30 +22,137 @@ ...@@ -22,30 +22,137 @@
======================================================================*/ ======================================================================*/
/// @file /// @file
/// @brief Base class for global singletons
///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
#ifndef QGCSINGLETON_H #ifndef QGCSINGLETON_H
#define QGCSINGLETON_H #define QGCSINGLETON_H
#include <QObject> #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.
/// For example DECLARE_QGC_SINGLETON(UASManager, UASManagerInterface)
#define DECLARE_QGC_SINGLETON(className, interfaceName) \
public: \
static interfaceName* instance(void); \
static void setMockInstance(interfaceName* mock); \
private: \
static interfaceName* _createSingleton(void); \
static void _deleteSingleton(void); \
static interfaceName* _instance; \
static interfaceName* _mockInstance; \
static interfaceName* _realInstance; \
friend class QGCApplication; \
friend class UnitTest; \
/// @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.
/// For example DECLARE_QGC_SINGLETON(UASManager, UASManagerInterface)
#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(qgcApp()); \
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(void) \
{ \
Q_ASSERT_X(_instance, "QGCSingleton", "If you hit this, then you have run into a startup or shutdown sequence bug."); \
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;
#include "QGCApplication.h" /// 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 UASManager 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 use an inteface so the second parameter to the macro is the class name as well.
class QGCSingleton : public QObject class QGCSingleton : public QObject
{ {
Q_OBJECT Q_OBJECT
public: protected:
/// @brief Contructor will register singleton to QGCApplication /// Constructor is private since all creation is done through _createInstance
/// @param parent Parent object /// @param parent Parent object
/// @param registerSingleton true: register with QGCApplication, false: do not register (only used for Mock implementations) QGCSingleton(QObject* parent = NULL);
QGCSingleton(QObject* parent = NULL, bool registerSingleton = true);
/// @brief Implementation should delete the singleton such that next call to instance
/// will create a new singleton.
virtual void deleteInstance(void) = 0;
}; };
#endif #endif
...@@ -38,41 +38,18 @@ This file is part of the QGROUNDCONTROL project ...@@ -38,41 +38,18 @@ This file is part of the QGROUNDCONTROL project
#include "QGCMessageBox.h" #include "QGCMessageBox.h"
#include "QGCApplication.h" #include "QGCApplication.h"
LinkManager* LinkManager::_instance = NULL; IMPLEMENT_QGC_SINGLETON(LinkManager, LinkManager)
LinkManager* LinkManager::instance(void)
{
if(_instance == 0) {
new LinkManager(qgcApp());
Q_CHECK_PTR(_instance);
}
Q_ASSERT(_instance);
return _instance;
}
void LinkManager::deleteInstance(void)
{
_instance = NULL;
delete this;
}
/** /**
* @brief Private singleton constructor * @brief Private singleton constructor
* *
* This class implements the singleton design pattern and has therefore only a private constructor. * This class implements the singleton design pattern and has therefore only a private constructor.
**/ **/
LinkManager::LinkManager(QObject* parent, bool registerSingleton) : LinkManager::LinkManager(QObject* parent) :
QGCSingleton(parent, registerSingleton), QGCSingleton(parent),
_connectionsSuspended(false), _connectionsSuspended(false),
_mavlink(NULL) _mavlink(NULL)
{ {
if (registerSingleton) {
Q_ASSERT(_instance == NULL);
_instance = this;
}
_mavlink = new MAVLinkProtocol(this); _mavlink = new MAVLinkProtocol(this);
Q_CHECK_PTR(_mavlink); Q_CHECK_PTR(_mavlink);
} }
......
...@@ -49,14 +49,13 @@ class LinkManagerTest; ...@@ -49,14 +49,13 @@ class LinkManagerTest;
class LinkManager : public QGCSingleton class LinkManager : public QGCSingleton
{ {
Q_OBJECT Q_OBJECT
public:
/// @brief Returns the LinkManager singleton
static LinkManager* instance(void);
virtual void deleteInstance(void); DECLARE_QGC_SINGLETON(LinkManager, LinkManager)
~LinkManager(); /// Unit Test has access to private constructor/destructor
friend class LinkManagerTest;
public:
/// Returns list of all links /// Returns list of all links
const QList<LinkInterface*> getLinks(); const QList<LinkInterface*> getLinks();
...@@ -99,19 +98,15 @@ signals: ...@@ -99,19 +98,15 @@ signals:
private: private:
/// All access to LinkManager is through LinkManager::instance /// All access to LinkManager is through LinkManager::instance
LinkManager(QObject* parent = NULL, bool registerSingleton = true); LinkManager(QObject* parent = NULL);
/// LinkManager unit test is allowed to new LinkManager objects
friend class LinkManagerTest;
~LinkManager();
bool _connectionsSuspendedMsg(void); bool _connectionsSuspendedMsg(void);
static LinkManager* _instance; /// LinkManager singleton
QList<LinkInterface*> _links; ///< List of available links QList<LinkInterface*> _links; ///< List of available links
QMutex _linkListMutex; ///< Mutex for thread safe access to _links list QMutex _linkListMutex; ///< Mutex for thread safe access to _links list
bool _connectionsSuspended; ///< true: all new connections should not be allowed bool _connectionsSuspended; ///< true: all new connections should not be allowed
QString _connectionsSuspendedReason; ///< User visible reason for suspension QString _connectionsSuspendedReason; ///< User visible reason for suspension
......
...@@ -45,7 +45,7 @@ void LinkManagerTest::init(void) ...@@ -45,7 +45,7 @@ void LinkManagerTest::init(void)
Q_ASSERT(_linkMgr == NULL); Q_ASSERT(_linkMgr == NULL);
Q_ASSERT(_multiSpy == NULL); Q_ASSERT(_multiSpy == NULL);
_linkMgr = new LinkManager(NULL /* no parent */, false /* don't register singleton */); _linkMgr = new LinkManager(NULL /* no parent */);
Q_CHECK_PTR(_linkMgr); Q_CHECK_PTR(_linkMgr);
_rgSignals[newLinkSignalIndex] = SIGNAL(newLink(LinkInterface*)); _rgSignals[newLinkSignalIndex] = SIGNAL(newLink(LinkInterface*));
...@@ -57,8 +57,6 @@ void LinkManagerTest::init(void) ...@@ -57,8 +57,6 @@ void LinkManagerTest::init(void)
void LinkManagerTest::cleanup(void) void LinkManagerTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_linkMgr); Q_ASSERT(_linkMgr);
Q_ASSERT(_multiSpy); Q_ASSERT(_multiSpy);
...@@ -67,18 +65,11 @@ void LinkManagerTest::cleanup(void) ...@@ -67,18 +65,11 @@ void LinkManagerTest::cleanup(void)
_linkMgr = NULL; _linkMgr = NULL;
_multiSpy = NULL; _multiSpy = NULL;
}
void LinkManagerTest::_instance_test(void)
{
LinkManager *linkManager = new LinkManager(NULL /* no parent */, false /* don't register singleton */);
// If the flag to not register singleton is not working this will cause QGCApplication to crash on UnitTest::cleanup();
// desctrucion since it will try to de-reference a deleted singleton.
delete linkManager;
} }
void LinkManagerTest::_add_test(void) void LinkManagerTest::_add_test(void)
{ {
Q_ASSERT(_linkMgr); Q_ASSERT(_linkMgr);
......
...@@ -44,7 +44,6 @@ private slots: ...@@ -44,7 +44,6 @@ private slots:
void init(void); void init(void);
void cleanup(void); void cleanup(void);
void _instance_test(void);
void _add_test(void); void _add_test(void);
void _delete_test(void); void _delete_test(void);
void _addSignals_test(void); void _addSignals_test(void);
......
...@@ -59,12 +59,12 @@ void MavlinkLogTest::init(void) ...@@ -59,12 +59,12 @@ void MavlinkLogTest::init(void)
void MavlinkLogTest::cleanup(void) void MavlinkLogTest::cleanup(void)
{ {
UnitTest::cleanup();
// Make sure no left over logs in temp directory // Make sure no left over logs in temp directory
QDir tmpDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); QDir tmpDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
QStringList logFiles(tmpDir.entryList(QStringList(QString("*.%1").arg(_logFileExtension)), QDir::Files)); QStringList logFiles(tmpDir.entryList(QStringList(QString("*.%1").arg(_logFileExtension)), QDir::Files));
QCOMPARE(logFiles.count(), 0); QCOMPARE(logFiles.count(), 0);
UnitTest::cleanup();
} }
void MavlinkLogTest::_createTempLogFile(bool zeroLength) void MavlinkLogTest::_createTempLogFile(bool zeroLength)
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "MockUASManager.h" #include "MockUASManager.h"
MockUASManager::MockUASManager(void) : MockUASManager::MockUASManager(void) :
UASManagerInterface(NULL, false /* do not register singleton with QGCApplication */), UASManagerInterface(NULL),
_mockUAS(NULL) _mockUAS(NULL)
{ {
......
...@@ -156,7 +156,7 @@ void PX4RCCalibrationTest::init(void) ...@@ -156,7 +156,7 @@ void PX4RCCalibrationTest::init(void)
_mockUASManager = new MockUASManager(); _mockUASManager = new MockUASManager();
Q_ASSERT(_mockUASManager); Q_ASSERT(_mockUASManager);
UASManager::setMockUASManager(_mockUASManager); UASManager::setMockInstance(_mockUASManager);
_mockUAS = new MockUAS(); _mockUAS = new MockUAS();
Q_CHECK_PTR(_mockUAS); Q_CHECK_PTR(_mockUAS);
...@@ -201,19 +201,18 @@ void PX4RCCalibrationTest::init(void) ...@@ -201,19 +201,18 @@ void PX4RCCalibrationTest::init(void)
void PX4RCCalibrationTest::cleanup(void) void PX4RCCalibrationTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_calWidget); Q_ASSERT(_calWidget);
delete _calWidget; delete _calWidget;
Q_ASSERT(_mockUAS); Q_ASSERT(_mockUAS);
delete _mockUAS; delete _mockUAS;
UASManager::setMockUASManager(NULL); UASManager::setMockInstance(NULL);
Q_ASSERT(_mockUASManager); Q_ASSERT(_mockUASManager);
delete _mockUASManager; delete _mockUASManager;
UnitTest::cleanup();
} }
/// @brief Test for correct behavior in determining minimum numbers of channels for flight. /// @brief Test for correct behavior in determining minimum numbers of channels for flight.
......
...@@ -88,8 +88,6 @@ void QGCUASFileManagerUnitTest::init(void) ...@@ -88,8 +88,6 @@ void QGCUASFileManagerUnitTest::init(void)
// Called after every test case // Called after every test case
void QGCUASFileManagerUnitTest::cleanup(void) void QGCUASFileManagerUnitTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_multiSpy); Q_ASSERT(_multiSpy);
Q_ASSERT(_fileManager); Q_ASSERT(_fileManager);
...@@ -98,6 +96,8 @@ void QGCUASFileManagerUnitTest::cleanup(void) ...@@ -98,6 +96,8 @@ void QGCUASFileManagerUnitTest::cleanup(void)
_fileManager = NULL; _fileManager = NULL;
_multiSpy = NULL; _multiSpy = NULL;
UnitTest::cleanup();
} }
/// @brief Connected to QGCUASFileManager listEntry signal in order to catch list entries /// @brief Connected to QGCUASFileManager listEntry signal in order to catch list entries
......
...@@ -68,8 +68,6 @@ void TCPLinkUnitTest::init(void) ...@@ -68,8 +68,6 @@ void TCPLinkUnitTest::init(void)
// Called after every test // Called after every test
void TCPLinkUnitTest::cleanup(void) void TCPLinkUnitTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_multiSpy); Q_ASSERT(_multiSpy);
Q_ASSERT(_link); Q_ASSERT(_link);
...@@ -78,6 +76,8 @@ void TCPLinkUnitTest::cleanup(void) ...@@ -78,6 +76,8 @@ void TCPLinkUnitTest::cleanup(void)
_multiSpy = NULL; _multiSpy = NULL;
_link = NULL; _link = NULL;
UnitTest::cleanup();
} }
void TCPLinkUnitTest::_properties_test(void) void TCPLinkUnitTest::_properties_test(void)
......
...@@ -20,13 +20,13 @@ void UASUnitTest::init() ...@@ -20,13 +20,13 @@ void UASUnitTest::init()
//this function is called after every test //this function is called after every test
void UASUnitTest::cleanup() void UASUnitTest::cleanup()
{ {
UnitTest::cleanup();
delete _uas; delete _uas;
_uas = NULL; _uas = NULL;
delete _mavlink; delete _mavlink;
_mavlink = NULL; _mavlink = NULL;
UnitTest::cleanup();
} }
void UASUnitTest::getUASID_test() void UASUnitTest::getUASID_test()
......
...@@ -114,8 +114,8 @@ void UnitTest::init(void) ...@@ -114,8 +114,8 @@ void UnitTest::init(void)
_expectMissedMessageBox = false; _expectMissedMessageBox = false;
// Each test gets a clean global state // Each test gets a clean global state
qgcApp()->destroySingletonsForUnitTest(); qgcApp()->_destroySingletons();
qgcApp()->createSingletonsForUnitTest(); qgcApp()->_createSingletons();
MAVLinkProtocol::deleteTempLogFiles(); MAVLinkProtocol::deleteTempLogFiles();
} }
...@@ -136,7 +136,7 @@ void UnitTest::cleanup(void) ...@@ -136,7 +136,7 @@ void UnitTest::cleanup(void)
} }
QCOMPARE(_missedFileDialogCount, 0); QCOMPARE(_missedFileDialogCount, 0);
qgcApp()->destroySingletonsForUnitTest(); qgcApp()->_destroySingletons();
} }
void UnitTest::setExpectedMessageBox(QMessageBox::StandardButton response) void UnitTest::setExpectedMessageBox(QMessageBox::StandardButton response)
......
...@@ -24,35 +24,29 @@ ...@@ -24,35 +24,29 @@
#define MEAN_EARTH_DIAMETER 12756274.0 #define MEAN_EARTH_DIAMETER 12756274.0
#define UMR 0.017453292519943295769236907684886 #define UMR 0.017453292519943295769236907684886
UASManager* UASManager::_instance = NULL; IMPLEMENT_QGC_SINGLETON(UASManager, UASManagerInterface)
UASManagerInterface* UASManager::_mockUASManager = NULL;
UASManager::UASManager(QObject* parent) :
void UASManager::setMockUASManager(UASManagerInterface* mockUASManager) UASManagerInterface(parent),
activeUAS(NULL),
offlineUASWaypointManager(NULL),
homeLat(47.3769),
homeLon(8.549444),
homeAlt(470.0),
homeFrame(MAV_FRAME_GLOBAL)
{ {
_mockUASManager = mockUASManager; loadSettings();
setLocalNEDSafetyBorders(1, -1, 0, -1, 1, -1);
} }
UASManagerInterface* UASManager::instance() UASManager::~UASManager()
{ {
if (_mockUASManager) { storeSettings();
return _mockUASManager; // Delete all systems
} foreach (UASInterface* mav, systems) {
// deleteLater so it ends up on correct thread
if(_instance == NULL) { mav->deleteLater();
_instance = new UASManager(qgcApp());
Q_CHECK_PTR(_instance);
} }
Q_ASSERT(_instance);
return _instance;
}
void UASManager::deleteInstance(void)
{
_instance = NULL;
delete this;
} }
void UASManager::storeSettings() void UASManager::storeSettings()
...@@ -256,34 +250,6 @@ void UASManager::uavChangedHomePosition(int uav, double lat, double lon, double ...@@ -256,34 +250,6 @@ void UASManager::uavChangedHomePosition(int uav, double lat, double lon, double
} }
} }
/**
* @brief Private singleton constructor
*
* This class implements the singleton design pattern and has therefore only a private constructor.
**/
UASManager::UASManager(QObject* parent) :
UASManagerInterface(parent),
activeUAS(NULL),
offlineUASWaypointManager(NULL),
homeLat(47.3769),
homeLon(8.549444),
homeAlt(470.0),
homeFrame(MAV_FRAME_GLOBAL)
{
loadSettings();
setLocalNEDSafetyBorders(1, -1, 0, -1, 1, -1);
}
UASManager::~UASManager()
{
storeSettings();
// Delete all systems
foreach (UASInterface* mav, systems) {
// deleteLater so it ends up on correct thread
mav->deleteLater();
}
}
void UASManager::addUAS(UASInterface* uas) void UASManager::addUAS(UASInterface* uas)
{ {
// WARNING: The active uas is set here // WARNING: The active uas is set here
......
...@@ -38,7 +38,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -38,7 +38,7 @@ This file is part of the QGROUNDCONTROL project
#include <UASInterface.h> #include <UASInterface.h>
#include "../../libs/eigen/Eigen/Eigen" #include "../../libs/eigen/Eigen/Eigen"
#include "QGCGeo.h" #include "QGCGeo.h"
#include "QGCApplication.h" #include "QGCSingleton.h"
/** /**
* @brief Central manager for all connected aerial vehicles * @brief Central manager for all connected aerial vehicles
...@@ -49,20 +49,10 @@ This file is part of the QGROUNDCONTROL project ...@@ -49,20 +49,10 @@ This file is part of the QGROUNDCONTROL project
class UASManager : public UASManagerInterface class UASManager : public UASManagerInterface
{ {
Q_OBJECT Q_OBJECT
public:
/// @brief Returns the UASManager singleton
static UASManagerInterface* instance(void);
virtual void deleteInstance(void);
~UASManager();
/** DECLARE_QGC_SINGLETON(UASManager, UASManagerInterface)
* @brief Sets a mock UASManager to be returned when a call is made to instance()
**/
static void setMockUASManager(UASManagerInterface* mockUASManager);
public:
/** /**
* @brief Get the currently selected UAS * @brief Get the currently selected UAS
* *
...@@ -273,9 +263,7 @@ private: ...@@ -273,9 +263,7 @@ private:
/// @brief All access to UASManager singleton is through UASManager::instance /// @brief All access to UASManager singleton is through UASManager::instance
UASManager(QObject* parent = NULL); UASManager(QObject* parent = NULL);
static UASManager* _instance; ~UASManager();
static UASManagerInterface* _mockUASManager;
public: public:
/* Need to align struct pointer to prevent a memory assertion: /* Need to align struct pointer to prevent a memory assertion:
......
...@@ -57,11 +57,6 @@ class UASManagerInterface : public QGCSingleton ...@@ -57,11 +57,6 @@ class UASManagerInterface : public QGCSingleton
Q_OBJECT Q_OBJECT
public: public:
/// @brief Contructor will register singleton to QGCApplication
/// @param parent Parent object
/// @param registerSingleton true: register with QGCApplication, false: do not register (only used for Mock implementations)
UASManagerInterface(QObject* parent = NULL, bool registerSingleton = true) : QGCSingleton(parent, registerSingleton) { }
virtual UASInterface* getActiveUAS() = 0; virtual UASInterface* getActiveUAS() = 0;
virtual UASWaypointManager *getActiveUASWaypointManager() = 0; virtual UASWaypointManager *getActiveUASWaypointManager() = 0;
virtual UASInterface* silentGetActiveUAS() = 0; virtual UASInterface* silentGetActiveUAS() = 0;
...@@ -112,6 +107,11 @@ signals: ...@@ -112,6 +107,11 @@ signals:
void activeUASStatusChanged(int systemId, bool active); void activeUASStatusChanged(int systemId, bool active);
/** @brief Current home position changed */ /** @brief Current home position changed */
void homePositionChanged(double lat, double lon, double alt); void homePositionChanged(double lat, double lon, double alt);
protected:
// FIXME: Do we need this here?
UASManagerInterface(QObject* parent = NULL) :
QGCSingleton(parent) { }
}; };
#endif // _UASMANAGERINTERFACE_H_ #endif // _UASMANAGERINTERFACE_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