#31 Squashed merge of commits relating to the plugin system and IContext redesign, from the 'interconnect' branch.

This commit is contained in:
Mathew Sutcliffe
2013-04-17 01:26:54 +01:00
parent 4e812975b4
commit 9916419678
57 changed files with 1517 additions and 1092 deletions

View File

@@ -3,247 +3,224 @@
//! License, v. 2.0. If a copy of the MPL was not distributed with this
//! file, You can obtain one at http://mozilla.org/MPL/2.0/
#ifndef CONTEXT_H
#define CONTEXT_H
#ifndef BLACKMISC_CONTEXT_H
#define BLACKMISC_CONTEXT_H
#include <QObject>
#include <QMap>
namespace BlackMisc
{
class CLog;
class CDebug;
//! IContext Interface.
/*!
This interface abstracts any application and library context. Use it to
add singleton classes and for application and library wide logging.
*/
class IContext
{
public:
//! Reference to IConext.
/*!
This static function returns a reference to the singleton object.
Use always this method to retrieve the context, since you cannot
instantiate your own one. Before it can be used you have to create
either a CApplicationContext or a CLibraryContext in the very
beginning of the executable/libary.
*/
static IContext &getInstance();
//! Returns true if the context is initialized and ready.
/*!
\return Returns true if context is initialized, otherwise false.
*/
static bool isInitialised();
//! Destructor.
/*!
Destroys the context.
*/
virtual ~IContext();
//! Pure virtual method returns the pointer to singletone object by its name.
/*!
\param singletonName a reference to the singletones name.
\return Returns a pointer to the singleton object.
*/
virtual void *singletonPointer(const QString &singletonName) = 0;
//! Pure virtual method sets the singletone pointer, given by its name.
/*!
\param singletonName a reference to the singletones name.
\param object a pointer to the singletone object.
*/
virtual void setSingletonPointer(const QString &singletonName, void *object) = 0;
//! Deallocates the object and removes the singletone pointer from the context map.
/*!
\param singletonName a reference to the singletones name.
\param object a pointer to the singletone object.
*/
virtual void releaseSingletonPointer(const QString &singletonName, void *object) = 0;
//! Pure virtual method returns the pointer to debug object
/*!
\return Pointer to CDebug object
*/
virtual CDebug *getDebug() = 0;
//! Pure virtual function to set the global error log object
/*!
\param Pointer to CDebug object
*/
virtual void setDebug(CDebug *debug) = 0;
protected:
//! Method to register the context.
/*! This method should be called by the derived class. It sets the
context variable to the calling object.*/
/*!
\param Pointer to CLog object
*/
void registerContext();
//! Pointer to the global context.
/*!
This variable holds a pointer to the application context.
*/
static IContext *m_context;
//! Pointer to the global Debug object.
/*!
This member variable contains all logging types, not only debug.
*/
CDebug *m_debug;
};
//! CApplicationContext.
/*!
This class implements the IContext interface for applications.
*/
class CApplicationContext : public IContext
{
public:
CApplicationContext();
//! This method returns the pointer to singletone object by its name.
/*!
\param singletonName a reference to the singletones name.
\return Returns a pointer to the singleton object.
*/
virtual void *singletonPointer(const QString &singletonName);
//! Sets the singletone pointer, given by its name.
/*!
\param singletonName a reference to the singletones name.
\param object a pointer to the singletone object.
*/
virtual void setSingletonPointer(const QString &singletonName, void *object);
//! Deallocates the object and removes the singletone pointer from the context map.
/*!
\param singletonName a reference to the singletones name.
\param object a pointer to the singletone object.
*/
virtual void releaseSingletonPointer(const QString &singletonName, void *ptr);
//! Pure virtual method returns the pointer to debug object
/*!
Keeps track of all singleton and pseudo-singleton objects.
*/
class IContext
{
public:
/*!
\return Pointer to CDebug object
Returns a reference to the static global context singleton.
\return
\warning Do not use this from within a plugin.
*/
virtual CDebug *getDebug();
static IContext &getInstance();
//! Pure virtual function to set the global error log object
/*!
\param Pointer to CDebug object
Destructor.
*/
virtual void setDebug(CDebug *debug);
virtual ~IContext();
private:
//! Typedef for the singleton map
typedef QMap<QString, void*> TSingletonMap;
//! Map of all registered objects inside the application.
/*!
This map holds associates all registered singleton objects to their names.
*/
TSingletonMap m_singletonObjects;
};
//! CApplicationContext.
/*!
This class implements the IContext interface for libraries.
*/
class CLibraryContext : public IContext
{
public:
CLibraryContext (IContext &application);
//! This method returns the pointer to singletone object by its name.
/*!
\param singletonName a reference to the singletones name.
\return Returns a pointer to the singleton object.
*/
virtual void *singletonPointer(const QString &singletonName);
//! Sets the singletone pointer, given by its name.
/*!
\param singletonName a reference to the singletones name.
\param object a pointer to the singletone object.
*/
virtual void setSingletonPointer(const QString &singletonName, void *ptr);
//! Deallocates the object and removes the singletone pointer from the context map.
/*!
\param singletonName a reference to the singletones name.
\param object a pointer to the singletone object.
*/
virtual void releaseSingletonPointer(const QString &singletonName, void *ptr);
//! Pure virtual method returns the pointer to debug object
/*!
\return Pointer to CDebug object
Returns the pointer to a singleton object by its name.
You usually use the template overload of this method instead.
\param singletonName
\return
\throw std::logic_error The requested singleton is not present.
*/
virtual CDebug *getDebug();
virtual QObject *singleton(const QString &singletonName) = 0;
//! Pure virtual function to set the global error log object
/*!
\param Pointer to CDebug object
Returns true if a singleton object with the give name is present.
You usually use the template overload of this method instead.
\param singletonName
\return
*/
virtual void setDebug(CDebug *debug);
private:
//! Pointer the application context.
/*!
Libraries do not have their own context, because they are using
the one from the linked application.
*/
IContext *m_applicationContext;
};
virtual bool hasSingleton(const QString &singletonName) const = 0;
/*!
Sets a singleton pointer, given by its name.
You usually use the template overload of this method instead.
\param singletonName
\param object
*/
virtual void setSingleton(const QString &singletonName, QObject *object) = 0;
/*!
Removes the singleton pointer, given by its name.
You usually use the template overload of this method instead.
\param singletonName
\param object
*/
virtual void releaseSingleton(const QString &singletonName) = 0;
/*!
Return the singleton pointer with the type T.
\tparam T An interface defined with the BLACK_INTERFACE macro.
\return
\throw std::logic_error The requested singleton is not present.
*/
template <class T>
T *singleton()
{
QObject *qobj = singleton(T::blackInterfaceId());
T *t = qobject_cast<T *>(qobj);
Q_ASSERT_X(t, "IContext", "qobject_cast failed");
return t;
}
/*!
Return true if the requested singleton in present in the context.
\tparam T An interface defined with the BLACK_INTERFACE macro.
\return
*/
template <class T>
bool hasSingleton() const
{
return hasSingleton(T::blackInterfaceId());
}
/*!
Set the singleton pointer with the type T.
\tparam T An interface defined with the BLACK_INTERFACE macro.
\param object
*/
template <class T>
void setSingleton(T *object)
{
setSingleton(T::blackInterfaceId(), object);
}
/*!
Remove the singleton pointer with the type T.
\tparam T An interface defined with the BLACK_INTERFACE macro.
*/
template <class T>
void releaseSingleton()
{
releaseSingleton(T::blackInterfaceId());
}
/*!
Set the global name of the application.
\param appName
*/
virtual void setApplicationName(const QString &appName) = 0;
/*!
Set the application name to the default.
*/
virtual void setDefaultApplicationName() = 0;
/*!
Return the global name of the application.
\return
*/
virtual const QString &getApplicationName() const = 0;
/*!
Return the CDebug singleton.
\return
\deprecated Use getSingletonPointer<CDebug>() instead.
\throw std::logic_error The requested singleton is not present.
*/
virtual CDebug *getDebug() = 0;
/*!
Set the CDebug singleton.
\param debug
\deprecated Use setSingletonPointer<CDebug>() instead.
*/
virtual void setDebug(CDebug *debug) = 0;
};
/*!
This macros helps to create the body of a singletone class,
which registers itself with the application context.
*/
#define SINGLETON_CLASS_DECLARATION(className) \
private:\
/* Singletone class constructor */ \
className (const className &) {}\
/* the local static pointer to the singleton instance */ \
static className *m_instance; \
public:\
static className &getInstance() \
Enable an interface to be manipulated with the template methods of IContext.
Put this macro in the public section of the interface definition.
\param FQNAME The fully qualified name of the interface (e.g. BlackMisc::IWhatever).
*/
#define BLACK_INTERFACE(FQNAME) static const char *blackInterfaceId() { return #FQNAME ; }
/*!
Default implementation of the IContext interface.
*/
class CApplicationContext : public IContext
{
public:
/*!
Constructor
*/
CApplicationContext();
virtual QObject *singleton(const QString &singletonName);
virtual bool hasSingleton(const QString &singletonName) const;
virtual void setSingleton(const QString &singletonName, QObject *object);
virtual void releaseSingleton(const QString &singletonName);
virtual CDebug *getDebug();
virtual void setDebug(CDebug *debug);
virtual void setApplicationName(const QString &applicationName) { m_appName = applicationName; }
virtual void setDefaultApplicationName();
virtual const QString &getApplicationName() const { return m_appName; }
private:
typedef QMap<QString, QObject *> TSingletonMap;
TSingletonMap m_singletons;
QString m_appName;
};
/*!
This macros helps to create the body of a singletone class,
which registers itself with the application context.
\warning Singletons defined with this macro will not be accessible in plugins.
\deprecated Preferred way is, during application initialization,
construct singletons and register them manually,
and when you want to access them, do it through the IContext.
*/
#define SINGLETON_CLASS_DECLARATION(className) \
private:\
/* Forbid copying */ \
className (const className &); \
className &operator= (const className &); \
/* the local static pointer to the singleton instance */ \
static className *m_instance; \
public:\
static className &getInstance() \
{ \
if (m_instance == NULL) \
{ \
/* Get the singleton object from the context, if there is one */ \
if (BlackMisc::IContext::getInstance().hasSingleton(#className)) \
{ \
if (m_instance == NULL) \
{ \
/* We need a valid context.*/ \
bAssertstr(BlackMisc::IContext::isInitialised(), QString("You are trying to access a singleton without having initialized a context. The simplest correction is to add 'BlackMisc::CApplicationContext myApplicationContext;' at the very beginning of your application.")); \
\
/* Get the singleton object from the context, if there is one */ \
void *object = BlackMisc::IContext::getInstance().singletonPointer(#className); \
if (object == NULL) \
{ \
/* We have no allocated object yet, so do it now. */ \
m_instance = new className; \
BlackMisc::IContext::getInstance().setSingletonPointer(#className, m_instance); \
} \
else \
{ \
/* Always use the c++ methods instead of casting the C way. */ \
m_instance = reinterpret_cast<className*>(object); \
} \
} \
return *m_instance; \
m_instance = reinterpret_cast<className*>(BlackMisc::IContext::getInstance().singleton(#className)); \
} \
private:
/* Put your class constructor directly after this makro and make sure it is private! */
#define SINGLETON_CLASS_IMPLEMENTATION(className) className *className::m_instance = NULL;
else \
{ \
/* We have no allocated object yet, so do it now. */ \
m_instance = new className; \
BlackMisc::IContext::getInstance().setSingleton(#className, m_instance); \
} \
} \
return *m_instance; \
} \
private:
/* Put your class constructor directly after this makro and make sure it is private! */
#define SINGLETON_CLASS_IMPLEMENTATION(className) className *className::m_instance = NULL;
} // namespace BlackMisc
#endif CONTEXT_H
#endif //BLACKMISC_CONTEXT_H