Updating IContext to our current style and making it less reliant on macros.

Updating code that uses IContext to a more conformant pattern of usage.
This commit is contained in:
Mathew Sutcliffe
2013-10-05 18:12:16 +01:00
parent 01af31d4da
commit e607121cc4
26 changed files with 235 additions and 200 deletions

View File

@@ -8,8 +8,8 @@
#include <iostream>
#include <QStringList>
Client::Client()
: m_net(BlackMisc::IContext::getInstance().singleton<BlackCore::INetwork>())
Client::Client(BlackMisc::IContext &ctx)
: m_net(&ctx.getObject<BlackCore::INetwork>())
{
using namespace BlackCore;
connect(m_net, &INetwork::atcPositionUpdate, this, &Client::atcPositionUpdate);

View File

@@ -6,18 +6,19 @@
#ifndef __BLACKSAMPLE_CLI_CLIENT_H__
#define __BLACKSAMPLE_CLI_CLIENT_H__
#include "blackcore/network.h"
#include "blackmisc/context.h"
#include <QObject>
#include <QTextStream>
#include <QMap>
#include <functional>
#include "blackcore/network.h"
class Client : public QObject
{
Q_OBJECT
public:
Client();
Client(BlackMisc::IContext &);
signals:
void quit();

View File

@@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "blackcore/network_vatlib.h"
#include "blackmisc/context.h"
#include "client.h"
#include "reader.h"
#include <QCoreApplication>
@@ -12,11 +13,15 @@
int main(int argc, char *argv[])
{
QCoreApplication app (argc, argv);
BlackMisc::CApplicationContext myApplicationContext;
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::IContext::getInstance().setSingleton<BlackCore::INetwork>(new BlackCore::NetworkVatlib());
Client client;
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
BlackCore::NetworkVatlib net;
ctx.setObject<BlackCore::INetwork>(net);
Client client(ctx);
LineReader reader;
QObject::connect(&reader, SIGNAL(command(const QString&)), &client, SLOT(command(const QString&)));
QObject::connect(&client, SIGNAL(quit()), &reader, SLOT(terminate()));

View File

@@ -7,10 +7,12 @@ using namespace BlackMisc;
int main(int argc, char *argv[])
{
BlackMisc::CApplicationContext myApplicationContext;
QCoreApplication a(argc, argv);
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
Client client;

View File

@@ -7,10 +7,12 @@ using namespace BlackMisc;
int main(int argc, char *argv[])
{
BlackMisc::CApplicationContext myApplicationContext;
QCoreApplication a(argc, argv);
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
Server server;

View File

@@ -10,9 +10,11 @@ using namespace BlackMisc;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
BlackMisc::CApplicationContext myApplicationContext;
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
CConfigManager::getInstance().setConfigPath(QString("config"));
if (!CConfigManager::getInstance().readConfig())

View File

@@ -22,7 +22,11 @@ using namespace BlackMisc::Aviation;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
QElapsedTimer timer;

View File

@@ -7,9 +7,11 @@
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
BlackMisc::CApplicationContext myApplicationContext;
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
bAppInfo << "This is a Info log message";
bAppWarning << "This is a bWarning log message";

View File

@@ -9,9 +9,11 @@
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
BlackMisc::CApplicationContext myApplicationContext;
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
{
const QString pluginPath = "../../build/bin";

View File

@@ -9,6 +9,7 @@
#include "blackmisc/debug.h"
#include "blackmisc/message.h"
#include "blackmisc/gui_messages.h"
#include "blackmisc/context.h"
using namespace BlackMisc;

View File

@@ -11,7 +11,11 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
BlackBox w;
w.show();

View File

@@ -6,9 +6,9 @@
#include "atclistmgr.h"
#include "network.h"
BlackCore::CAtcListManager::CAtcListManager()
BlackCore::CAtcListManager::CAtcListManager(BlackMisc::IContext &ctx)
{
INetwork *net = BlackMisc::IContext::getInstance().singleton<INetwork>();
INetwork *net = &ctx.getObject<INetwork>();
connect(net, &INetwork::atcPositionUpdate, this, &CAtcListManager::update, Qt::QueuedConnection);
connect(net, &INetwork::atcDisconnected, this, &CAtcListManager::remove, Qt::QueuedConnection);

View File

@@ -25,8 +25,6 @@ namespace BlackCore
Q_PROPERTY(BlackMisc::CAtcList list READ getList NOTIFY listChanged)
public:
BLACK_INTERFACE(BlackCore::IAtcListManager)
/*!
* Virtual destructor.
*/
@@ -49,7 +47,7 @@ namespace BlackCore
/*!
* Concrete ATC list manager. Implementation of IAtcListManager.
*
* Has a dependency on INetwork. An INetwork must be available through the IContext singleton.
* Has a dependency on INetwork. An INetwork must be available through the IContext.
*/
class CAtcListManager : public IAtcListManager
{
@@ -58,8 +56,9 @@ namespace BlackCore
public:
/*!
* Constructor.
* \param context
*/
CAtcListManager();
CAtcListManager(BlackMisc::IContext &context);
virtual const BlackMisc::CAtcList& getList() const { return m_list; }

View File

@@ -34,8 +34,6 @@ namespace BlackCore
Q_OBJECT
public:
BLACK_INTERFACE(BlackCore::INetwork)
virtual ~INetwork() {}
enum

View File

@@ -14,7 +14,7 @@
#include "blackcore/simulator.h"
#include "blackmisc/debug.h"
#include "blackmisc/context.h"
#include <QtGlobal>
#include <QLibrary>

View File

@@ -118,14 +118,14 @@ void BlackD::createTrayIcon()
void BlackD::createLogging()
{
BlackMisc::IContext::getInstance().getDebug()->create();
BlackMisc::IContext::getInstance().getDebug().create();
m_displayer = new CQtDisplayer(ui->logginView);
BlackMisc::IContext::getInstance().getDebug()->getDebugLog()->attachDisplay(m_displayer);
BlackMisc::IContext::getInstance().getDebug()->getInfoLog()->attachDisplay(m_displayer);
BlackMisc::IContext::getInstance().getDebug()->getWarningLog()->attachDisplay(m_displayer);
BlackMisc::IContext::getInstance().getDebug()->getErrorLog()->attachDisplay(m_displayer);
BlackMisc::IContext::getInstance().getDebug().getDebugLog()->attachDisplay(m_displayer);
BlackMisc::IContext::getInstance().getDebug().getInfoLog()->attachDisplay(m_displayer);
BlackMisc::IContext::getInstance().getDebug().getWarningLog()->attachDisplay(m_displayer);
BlackMisc::IContext::getInstance().getDebug().getErrorLog()->attachDisplay(m_displayer);
}
void BlackD::createComServer()

View File

@@ -18,7 +18,10 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
BlackMisc::CApplicationContext myBlackApp;
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::CApplicationContext ctx;
BlackMisc::IContext::setInstance(ctx);
BlackMisc::CDebug debug;
ctx.setObject(debug);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
QMessageBox::critical(0, QObject::tr("Systray"),

View File

@@ -5,6 +5,7 @@
#include "blackmisc/com_handler.h"
#include "blackmisc/debug.h"
#include "blackmisc/context.h"
#include <QTcpSocket>
#include <QDataStream>

View File

@@ -5,6 +5,7 @@
#include "blackmisc/config.h"
#include "blackmisc/debug.h"
#include "blackmisc/context.h"
#include <QFile>
#include <QStringList>

View File

@@ -6,7 +6,6 @@
#include "blackmisc/debug.h"
#include "blackmisc/context.h"
#include <QFileInfo>
#include <stdexcept>
#ifdef Q_OS_WIN
#include <Windows.h>
@@ -15,10 +14,21 @@
namespace BlackMisc
{
IContext &IContext::getInstance()
IContext *&instancePointer()
{
static CApplicationContext context;
return context;
static IContext *ptr = &context;
return ptr;
}
void IContext::setInstance(IContext &context)
{
instancePointer() = &context;
}
IContext &IContext::getInstance()
{
return *instancePointer();
}
IContext::~IContext()
@@ -29,44 +39,20 @@ namespace BlackMisc
{
}
QObject *CApplicationContext::singleton(const QString &singletonName)
const QObject *CApplicationContext::getQObjectNothrow(const QString &name) const
{
TSingletonMap::const_iterator it = m_singletons.find(singletonName);
if (it != m_singletons.end())
{
return it.value();
}
throw std::logic_error("Requested singleton not present");
auto it = m_map.find(name);
return it == m_map.end() ? nullptr : it.value();
}
bool CApplicationContext::hasSingleton(const QString &singletonName) const
void CApplicationContext::setQObject(QString name, QObject &object)
{
TSingletonMap::const_iterator it = m_singletons.find(singletonName);
if (it != m_singletons.end())
{
return true;
}
return false;
m_map.insert(name, &object);
}
void CApplicationContext::setSingleton(const QString &singletonName, QObject *object)
void CApplicationContext::removeQObject(const QString &name)
{
m_singletons.insert(singletonName, object);
}
void CApplicationContext::releaseSingleton(const QString &singletonName)
{
m_singletons.remove(singletonName);
}
CDebug *CApplicationContext::getDebug()
{
return IContext::singleton<CDebug>();
}
void CApplicationContext::setDebug(CDebug *debug)
{
IContext::setSingleton(debug);
m_map.remove(name);
}
void CApplicationContext::setDefaultApplicationName()

View File

@@ -6,178 +6,202 @@
#ifndef BLACKMISC_CONTEXT_H
#define BLACKMISC_CONTEXT_H
#include "blackmisc/debug.h"
#include <QMetaType>
#include <QObject>
#include <QMap>
#include <stdexcept>
namespace BlackMisc
{
class CDebug;
/*!
Keeps track of all singleton and pseudo-singleton objects.
*/
* Provides centralized modular access to long-lived interface objects.
*/
class IContext
{
public:
/*!
Returns a reference to the static global context singleton.
\return
\warning Do not use this from within a plugin.
*/
* Returns a reference to a static global context singleton.
* \return
* \warning Do not use this in code which could be called from within a plugin.
* \deprecated Provided as a crutch to ease transition from singleton-based design.
*/
static IContext &getInstance();
/*!
Destructor.
*/
* Allows for apps to set the static global context singleton.
* \deprecated Provided as a crutch to ease transition from singleton-based design.
*/
static void setInstance(IContext &);
/*!
* Destructor.
*/
virtual ~IContext();
/*!
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 QObject *singleton(const QString &singletonName) = 0;
/*!
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 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()
* Returns true if an object with the given name is present.
* You usually use the type-safe hasObject method instead.
* \param name
* \return
*/
bool hasQObject(const QString &name)
{
QObject *qobj = singleton(T::blackInterfaceId());
T *t = qobject_cast<T *>(qobj);
Q_ASSERT_X(t, "IContext", "qobject_cast failed");
return t;
return getQObjectNothrow(name);
}
/*!
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
* Set the object pointer with the type T.
* \tparam T A class derived from QObject using the Q_OBJECT macro.
* \param object
* \param name The name of the object; default is the name of its class, T.
*/
template <class T> void setObject(T &object, QString name = T::staticMetaObject.className())
{
return hasSingleton(T::blackInterfaceId());
setQObject(name, object);
}
/*!
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)
* Remove the object pointer with the type T.
* \tparam T A class derived from QObject using the Q_OBJECT macro.
* \param name The name of the object; default is the name of its class T.
*/
template <class T> void removeObject(const QString &name = T::staticMetaObject.className())
{
setSingleton(T::blackInterfaceId(), object);
removeQObject(name);
}
/*!
Remove the singleton pointer with the type T.
\tparam T An interface defined with the BLACK_INTERFACE macro.
*/
template <class T>
void releaseSingleton()
* Return an object pointer of the class T.
* \tparam T A class derived from QObject using the Q_OBJECT macro.
* \param name The name of the object; default is the name of its class, T.
* \return
* \throw std::logic_error The requested object is not present.
*/
template <class T> T &getObject(const QString &name = T::staticMetaObject.className())
{
releaseSingleton(T::blackInterfaceId());
T *obj = qobject_cast<T *>(getQObjectNothrow(name));
if (!obj) { throw std::logic_error("IContext: qobject_cast failed"); }
return *obj;
}
/*!
Set the global name of the application.
\param appName
*/
virtual void setApplicationName(const QString &appName) = 0;
* Return true if the requested object in present in the context.
* \tparam T A class derived from QObject using the Q_OBJECT macro.
* \param name The name of the object; default is the name of its class, T.
* \return
*/
template <class T> bool hasObject(const QString &name = T::staticMetaObject.className()) const
{
QObject *qobj = getQObjectNothrow(name);
return qobj && qobject_cast<T*>(qobj);
}
/*!
Set the application name to the default.
*/
* Sets an object pointer, given by its name.
* You usually use the type-safe setObject method instead.
* \param object
* \param name
*/
virtual void setQObject(QString name, QObject &object) = 0;
/*!
* Removes an object pointer, given by its name.
* You usually use the type-safe removeObject method instead.
* \param name
* \param object
*/
virtual void removeQObject(const QString &name) = 0;
/*!
* Like getQObject but returns nullptr instead of throwing an exception.
* \param name
* \return
*/
virtual const QObject *getQObjectNothrow(const QString &name) const = 0;
/*!
* Like getQObject but returns nullptr instead of throwing an exception.
* \param name
* \return
*/
QObject *getQObjectNothrow(const QString &name)
{
return const_cast<QObject *>(static_cast<const IContext*>(this)->getQObjectNothrow(name));
}
/*!
* Returns the pointer to an object by its name.
* You usually use the type-safe getObject method instead.
* \param name
* \return
* \throw std::logic_error The requested object is not present.
*/
QObject &getQObject(const QString &name)
{
QObject *qobj = getQObjectNothrow(name);
if (!qobj) { throw std::logic_error("IContext: named object not found"); }
return *qobj;
}
/*!
* Set the global name of the application.
* \param appName
*/
virtual void setApplicationName(QString appName) = 0;
/*!
* Set the application name to the default.
*/
virtual void setDefaultApplicationName() = 0;
/*!
Return the global name of the application.
\return
*/
* 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;
* Return the CDebug object.
* \return
* \throw std::logic_error The requested object is not present.
*/
CDebug &getDebug()
{
return getObject<CDebug>();
}
/*!
Set the CDebug singleton.
\param debug
\deprecated Use setSingletonPointer<CDebug>() instead.
*/
virtual void setDebug(CDebug *debug) = 0;
* Set the CDebug object.
* \param debug
*/
void setDebug(CDebug &debug)
{
setObject(debug);
}
};
/*!
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.
*/
* Default implementation of the IContext interface.
*/
class CApplicationContext : public IContext
{
public:
/*!
Constructor
*/
* 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 const QObject *getQObjectNothrow(const QString &) const;
virtual void setQObject(QString, QObject &);
virtual void removeQObject(const QString &);
virtual void setApplicationName(QString appName) { m_appName = appName; }
virtual void setDefaultApplicationName();
virtual const QString &getApplicationName() const { return m_appName; }
private:
typedef QMap<QString, QObject *> TSingletonMap;
TSingletonMap m_singletons;
QMap<QString, QObject *> m_map;
QString m_appName;
};
@@ -186,7 +210,7 @@ namespace BlackMisc
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,
construct would-be singletons and register them manually,
and when you want to access them, do it through the IContext.
*/
#define SINGLETON_CLASS_DECLARATION(className) \
@@ -202,15 +226,15 @@ public:\
if (m_instance == NULL) \
{ \
/* Get the singleton object from the context, if there is one */ \
if (BlackMisc::IContext::getInstance().hasSingleton(#className)) \
if (BlackMisc::IContext::getInstance().hasQObject(#className)) \
{ \
m_instance = reinterpret_cast<className*>(BlackMisc::IContext::getInstance().singleton(#className)); \
m_instance = static_cast<className*>(&BlackMisc::IContext::getInstance().getQObject(#className)); \
} \
else \
{ \
/* We have no allocated object yet, so do it now. */ \
m_instance = new className; \
BlackMisc::IContext::getInstance().setSingleton(#className, m_instance); \
BlackMisc::IContext::getInstance().setQObject(#className, *m_instance); \
} \
} \
return *m_instance; \

View File

@@ -1,6 +1,7 @@
#include "blackmisc/debug.h"
#include "blackmisc/log.h"
#include "blackmisc/display.h"
#include "blackmisc/context.h"
#include <QDir>
#include <QCoreApplication>

View File

@@ -6,7 +6,6 @@
#ifndef BLACKMISC_DEBUG_H
#define BLACKMISC_DEBUG_H
#include "blackmisc/context.h"
#include "blackmisc/log.h"
#include "blackmisc/display.h"
#include "blackmisc/logmessage.h"
@@ -26,8 +25,6 @@ namespace BlackMisc
Q_OBJECT
public:
BLACK_INTERFACE(BlackMisc::CDebug)
CDebug();
// internal use only
@@ -110,10 +107,10 @@ namespace BlackMisc
CLog *m_debugLog;
};
#define bInfo(CONTEXT) ( (CONTEXT).getDebug()->blackInfo(__LINE__, __FILE__, __FUNCTION__ ) )
#define bWarning(CONTEXT) ( (CONTEXT).getDebug()->blackWarning(__LINE__, __FILE__, __FUNCTION__ ) )
#define bDebug(CONTEXT) ( (CONTEXT).getDebug()->blackDebug(__LINE__, __FILE__, __FUNCTION__ ) )
#define bError(CONTEXT) ( (CONTEXT).getDebug()->blackError(__LINE__, __FILE__, __FUNCTION__ ) )
#define bInfo(CONTEXT) ( (CONTEXT).getDebug().blackInfo(__LINE__, __FILE__, __FUNCTION__ ) )
#define bWarning(CONTEXT) ( (CONTEXT).getDebug().blackWarning(__LINE__, __FILE__, __FUNCTION__ ) )
#define bDebug(CONTEXT) ( (CONTEXT).getDebug().blackDebug(__LINE__, __FILE__, __FUNCTION__ ) )
#define bError(CONTEXT) ( (CONTEXT).getDebug().blackError(__LINE__, __FILE__, __FUNCTION__ ) )
#define bAppInfo bInfo(BlackMisc::IContext::getInstance())
#define bAppWarning bWarning(BlackMisc::IContext::getInstance())

View File

@@ -7,7 +7,6 @@
#define LOGMESSAGE_H
#include "blackmisc/log.h"
#include "blackmisc/context.h"
#include <QTextStream>
namespace BlackMisc

View File

@@ -17,17 +17,17 @@ namespace BlackCoreTest
void CTestNetMediators::initTestCase()
{
BlackMisc::IContext::getInstance().setSingleton<INetwork>(&m_networkDummy);
m_context.setObject<INetwork>(m_networkDummy);
}
void CTestNetMediators::cleanupTestCase()
{
BlackMisc::IContext::getInstance().releaseSingleton<INetwork>();
m_context.removeObject<INetwork>();
}
void CTestNetMediators::atcListManagerTest()
{
CAtcListManager mgr;
CAtcListManager mgr(m_context);
AtcListConsumer cons;
QObject::connect(&mgr, &IAtcListManager::listChanged, &cons, &AtcListConsumer::listChanged);

View File

@@ -45,6 +45,7 @@ namespace BlackCoreTest
void cleanupTestCase();
private:
BlackMisc::CApplicationContext m_context;
BlackCore::NetworkDummy m_networkDummy;
};