mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 20:15:35 +08:00
refs #316 Added CLogHandler which allows to subscribe to log messages.
This commit is contained in:
124
src/blackmisc/loghandler.cpp
Normal file
124
src/blackmisc/loghandler.cpp
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/* Copyright (C) 2014
|
||||||
|
* Swift Project Community / Contributors
|
||||||
|
*
|
||||||
|
* This file is part of Swift Project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||||
|
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
|
||||||
|
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||||
|
* contained in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "loghandler.h"
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QMetaMethod>
|
||||||
|
|
||||||
|
namespace BlackMisc
|
||||||
|
{
|
||||||
|
Q_GLOBAL_STATIC(CLogHandler, g_handler)
|
||||||
|
|
||||||
|
CLogHandler *CLogHandler::instance()
|
||||||
|
{
|
||||||
|
Q_ASSERT(! g_handler.isDestroyed());
|
||||||
|
return g_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||||
|
{
|
||||||
|
CStatusMessage statusMessage(type, context, message);
|
||||||
|
QMetaObject::invokeMethod(CLogHandler::instance(), "logLocalMessage", Q_ARG(BlackMisc::CStatusMessage, statusMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLogHandler::install()
|
||||||
|
{
|
||||||
|
m_oldHandler = qInstallMessageHandler(messageHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
CLogHandler::CLogHandler()
|
||||||
|
{
|
||||||
|
// in case the first call to instance() is in a different thread
|
||||||
|
moveToThread(QCoreApplication::instance()->thread());
|
||||||
|
}
|
||||||
|
|
||||||
|
CLogHandler::~CLogHandler()
|
||||||
|
{
|
||||||
|
if (m_oldHandler)
|
||||||
|
{
|
||||||
|
qInstallMessageHandler(m_oldHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLogCategoryHandler *CLogHandler::handlerForCategory(const QString &category)
|
||||||
|
{
|
||||||
|
if (! m_categoryHandlers.contains(category))
|
||||||
|
{
|
||||||
|
m_categoryHandlers[category] = new CLogCategoryHandler(this, m_enableFallThrough);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_categoryHandlers[category];
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<CLogCategoryHandler *> CLogHandler::handlersForCategory(const QString &category) const
|
||||||
|
{
|
||||||
|
QList<CLogCategoryHandler *> m_handlers;
|
||||||
|
for (auto i = m_categoryHandlers.begin(); i != m_categoryHandlers.end(); ++i)
|
||||||
|
{
|
||||||
|
if (category.startsWith(i.key()))
|
||||||
|
{
|
||||||
|
m_handlers.push_back(i.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLogHandler::enableConsoleOutput(bool enable)
|
||||||
|
{
|
||||||
|
m_enableFallThrough = enable;
|
||||||
|
for (auto *handler : m_categoryHandlers.values())
|
||||||
|
{
|
||||||
|
handler->enableConsoleOutput(enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CLogHandler::isFallThroughEnabled(const QList<CLogCategoryHandler *> &handlers) const
|
||||||
|
{
|
||||||
|
for (auto *handler : handlers)
|
||||||
|
{
|
||||||
|
if (handler->m_enableFallThrough != m_enableFallThrough)
|
||||||
|
{
|
||||||
|
return handler->m_enableFallThrough;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_enableFallThrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLogHandler::logLocalMessage(const CStatusMessage &statusMessage)
|
||||||
|
{
|
||||||
|
logMessage(statusMessage);
|
||||||
|
emit localMessageLogged(statusMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLogHandler::logRemoteMessage(const CStatusMessage &statusMessage)
|
||||||
|
{
|
||||||
|
logMessage(statusMessage);
|
||||||
|
emit remoteMessageLogged(statusMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLogHandler::logMessage(const CStatusMessage &statusMessage)
|
||||||
|
{
|
||||||
|
auto handlers = handlersForCategory(statusMessage.getCategory());
|
||||||
|
|
||||||
|
if (isFallThroughEnabled(handlers))
|
||||||
|
{
|
||||||
|
QtMsgType type;
|
||||||
|
QString category;
|
||||||
|
QString message;
|
||||||
|
statusMessage.toQtLogTriple(&type, &category, &message);
|
||||||
|
m_oldHandler(type, QMessageLogContext(nullptr, 0, nullptr, qPrintable(category)), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto *handler : handlers)
|
||||||
|
{
|
||||||
|
emit handler->messageLogged(statusMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
101
src/blackmisc/loghandler.h
Normal file
101
src/blackmisc/loghandler.h
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/* Copyright (C) 2014
|
||||||
|
* Swift Project Community / Contributors
|
||||||
|
*
|
||||||
|
* This file is part of Swift Project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||||
|
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
|
||||||
|
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||||
|
* contained in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BLACKMISC_LOGHANDLER_H
|
||||||
|
#define BLACKMISC_LOGHANDLER_H
|
||||||
|
|
||||||
|
//! \file
|
||||||
|
|
||||||
|
#include "statusmessage.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
namespace BlackMisc
|
||||||
|
{
|
||||||
|
class CLogCategoryHandler;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Class for subscribing to log messages.
|
||||||
|
*/
|
||||||
|
class CLogHandler : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! \private Constructor.
|
||||||
|
CLogHandler();
|
||||||
|
|
||||||
|
//! \private Destructor.
|
||||||
|
~CLogHandler();
|
||||||
|
|
||||||
|
//! Return pointer to the CLogHandler singleton.
|
||||||
|
//! \warning This can not be called from within a plugin, because the returned instance will be wrong.
|
||||||
|
static CLogHandler *instance();
|
||||||
|
|
||||||
|
//! Tell the CLogHandler to install itself with qInstallMessageHandler.
|
||||||
|
void install();
|
||||||
|
|
||||||
|
//! Return a category handler for subscribing to all messages whose category string starts with the given prefix.
|
||||||
|
CLogCategoryHandler *handlerForCategory(const QString &prefix);
|
||||||
|
|
||||||
|
//! Enable or disable the default Qt handler.
|
||||||
|
void enableConsoleOutput(bool enable);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
//! Emitted when a message is logged in this process.
|
||||||
|
void localMessageLogged(const BlackMisc::CStatusMessage &message);
|
||||||
|
|
||||||
|
//! Emitted when a log message is relayed from a different process.
|
||||||
|
void remoteMessageLogged(const BlackMisc::CStatusMessage &message);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
//! Called by our QtMessageHandler to log a message.
|
||||||
|
void logLocalMessage(const BlackMisc::CStatusMessage &message);
|
||||||
|
|
||||||
|
//! Called by the context to relay a message.
|
||||||
|
void logRemoteMessage(const BlackMisc::CStatusMessage &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void logMessage(const BlackMisc::CStatusMessage &message);
|
||||||
|
QtMessageHandler m_oldHandler = nullptr;
|
||||||
|
bool m_enableFallThrough = true;
|
||||||
|
bool isFallThroughEnabled(const QList<CLogCategoryHandler *> &handlers) const;
|
||||||
|
QMap<QString, CLogCategoryHandler *> m_categoryHandlers;
|
||||||
|
QList<CLogCategoryHandler *> handlersForCategory(const QString &category) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A class for subscribing to log messages in particular categories.
|
||||||
|
* \sa CLogHandler::handlerForCategory
|
||||||
|
*/
|
||||||
|
class CLogCategoryHandler : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* Enable or disable the default Qt handler for messages in relevant categories.
|
||||||
|
* This can override the setting of the parent CLogHandler.
|
||||||
|
*/
|
||||||
|
void enableConsoleOutput(bool enable) { m_enableFallThrough = enable; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/*!
|
||||||
|
* Emitted when a message is logged in a relevant category.
|
||||||
|
*/
|
||||||
|
void messageLogged(const CStatusMessage &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class CLogHandler;
|
||||||
|
CLogCategoryHandler(QObject *parent, bool enableFallThrough) : QObject(parent), m_enableFallThrough(enableFallThrough) {}
|
||||||
|
bool m_enableFallThrough;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user