I have spent hours trying to understand why my logger class does not work.
The idea is to hook existing qDebug, qWarning and qFatal to one of my slots and also extend the macro list with new ones (qInfo in this example)
I tried to follow the following guidelines:
Using a Singleton Class across a Qt Application and its Plugins
#pragma once
#include <QtGui>
#include <QMutex>
//! Creates a fake call, to have a cleaner design.
extern void qInfo(const char* fmt);
#define QtTraceMsg QtMsgType(6)
#define QtInfoMsg QtMsgType(7)
class MsgHandler: public QObject
{
Q_OBJECT
signals:
void newMsg(QtMsgType type, const QString &msg);
public:
static MsgHandler *instance();
static void Handler(QtMsgType type, const char *msg);
private:
MsgHandler() { qRegisterMetaType<QtMsgType>("QtMsgType"); } // important
static MsgHandler* _instance;
};
and cpp:
#include "MsgHandler.h"
MsgHandler* MsgHandler::_instance = NULL;
MsgHandler * MsgHandler::instance()
{
static QMutex mutex;
if (_instance == NULL)
{
mutex.lock();
if (_instance == NULL)
_instance = new MsgHandler;
mutex.unlock();
}
return _instance;
}
void MsgHandler::Handler(QtMsgType type, const char *msg)
{
QString s = msg;
emit instance()->newMsg(type, s);
}
///////////////////////////////////////////////////////////////////////////////
void qInfo(const char *msg)
{
MsgHandler::instance()->Handler(QtInfoMsg, msg);
}
then in the main I register my handler
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Handle error messages
qInstallMsgHandler(MsgHandler::Handler);
}
Everything works perfectly in the main thread. But from a plugin that runs its own thread it fail:
void MyPlugin::run()
{
qWarning("Test debug"); //works fine
MsgHandler::instance()->Handler(QtInfoMsg, "info 2"); //creates a new instance!
qInfo("test info"); //also creates a new instance!
}
The solution is to pass a pointer to the MsgHandler to each plugin.