mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-23 23:45:35 +08:00
136 lines
4.2 KiB
C++
136 lines
4.2 KiB
C++
/* 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 "algorithm.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()
|
|
{
|
|
qInstallMessageHandler(m_oldHandler);
|
|
}
|
|
|
|
CLogPatternHandler *CLogHandler::handlerForPattern(const CLogPattern &pattern)
|
|
{
|
|
Q_ASSERT(thread() == QThread::currentThread());
|
|
|
|
auto finder = [ & ](const PatternPair &pair) { return pair.first == pattern; };
|
|
auto comparator = [](const PatternPair &a, const PatternPair &b) { return a.first.isProperSubsetOf(b.first); };
|
|
|
|
auto it = std::find_if(m_patternHandlers.begin(), m_patternHandlers.end(), finder);
|
|
if (it == m_patternHandlers.end())
|
|
{
|
|
auto *handler = new CLogPatternHandler(this);
|
|
topologicallySortedInsert(m_patternHandlers, PatternPair(pattern, handler), comparator);
|
|
return handler;
|
|
}
|
|
else
|
|
{
|
|
return (*it).second;
|
|
}
|
|
}
|
|
|
|
QList<CLogPatternHandler *> CLogHandler::handlersForMessage(const CStatusMessage &message) const
|
|
{
|
|
QList<CLogPatternHandler *> m_handlers;
|
|
for (const auto &pair : m_patternHandlers)
|
|
{
|
|
if (pair.first.match(message))
|
|
{
|
|
m_handlers.push_back(pair.second);
|
|
}
|
|
}
|
|
return m_handlers;
|
|
}
|
|
|
|
bool CLogHandler::isFallThroughEnabled(const QList<CLogPatternHandler *> &handlers) const
|
|
{
|
|
for (const auto *handler : handlers)
|
|
{
|
|
if (! handler->m_inheritFallThrough)
|
|
{
|
|
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)
|
|
{
|
|
collectGarbage();
|
|
|
|
auto handlers = handlersForMessage(statusMessage);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
void CLogHandler::collectGarbage()
|
|
{
|
|
auto newEnd = std::stable_partition(m_patternHandlers.begin(), m_patternHandlers.end(), [](const PatternPair &pair)
|
|
{
|
|
return ! pair.second->canBeDeleted();
|
|
});
|
|
std::for_each(newEnd, m_patternHandlers.end(), [](const PatternPair &pair) { pair.second->deleteLater(); });
|
|
m_patternHandlers.erase(newEnd, m_patternHandlers.end());
|
|
}
|
|
|
|
}
|