mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-17 10:55:32 +08:00
refs #338 CLogHandler filtering messages using CLogPattern instead of the old prefix-based approach.
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "loghandler.h"
|
#include "loghandler.h"
|
||||||
|
#include "algorithm.h"
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QMetaMethod>
|
#include <QMetaMethod>
|
||||||
|
|
||||||
@@ -43,27 +44,34 @@ namespace BlackMisc
|
|||||||
qInstallMessageHandler(m_oldHandler);
|
qInstallMessageHandler(m_oldHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLogCategoryHandler *CLogHandler::handlerForCategoryPrefix(const QString &category)
|
CLogPatternHandler *CLogHandler::handlerForPattern(const CLogPattern &pattern)
|
||||||
{
|
{
|
||||||
Q_ASSERT(thread() == QThread::currentThread());
|
Q_ASSERT(thread() == QThread::currentThread());
|
||||||
|
|
||||||
if (! m_categoryPrefixHandlers.contains(category))
|
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())
|
||||||
{
|
{
|
||||||
m_categoryPrefixHandlers[category] = new CLogCategoryHandler(this, m_enableFallThrough);
|
auto *handler = new CLogPatternHandler(this, m_enableFallThrough);
|
||||||
|
topologicallySortedInsert(m_patternHandlers, PatternPair(pattern, handler), comparator);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (*it).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_categoryPrefixHandlers[category];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<CLogCategoryHandler *> CLogHandler::handlersForCategories(const CLogCategoryList &categories) const
|
QList<CLogPatternHandler *> CLogHandler::handlersForMessage(const CStatusMessage &message) const
|
||||||
{
|
{
|
||||||
QList<CLogCategoryHandler *> m_handlers;
|
QList<CLogPatternHandler *> m_handlers;
|
||||||
for (auto i = m_categoryPrefixHandlers.begin(); i != m_categoryPrefixHandlers.end(); ++i)
|
for (const auto &pair : m_patternHandlers)
|
||||||
{
|
{
|
||||||
if (categories.anyStartWith(i.key()))
|
if (pair.first.match(message))
|
||||||
{
|
{
|
||||||
m_handlers.push_back(i.value());
|
m_handlers.push_back(pair.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_handlers;
|
return m_handlers;
|
||||||
@@ -74,13 +82,13 @@ namespace BlackMisc
|
|||||||
Q_ASSERT(thread() == QThread::currentThread());
|
Q_ASSERT(thread() == QThread::currentThread());
|
||||||
|
|
||||||
m_enableFallThrough = enable;
|
m_enableFallThrough = enable;
|
||||||
for (auto *handler : m_categoryPrefixHandlers.values())
|
for (const auto &pair : m_patternHandlers)
|
||||||
{
|
{
|
||||||
handler->enableConsoleOutput(enable);
|
pair.second->enableConsoleOutput(enable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CLogHandler::isFallThroughEnabled(const QList<CLogCategoryHandler *> &handlers) const
|
bool CLogHandler::isFallThroughEnabled(const QList<CLogPatternHandler *> &handlers) const
|
||||||
{
|
{
|
||||||
for (const auto *handler : handlers)
|
for (const auto *handler : handlers)
|
||||||
{
|
{
|
||||||
@@ -108,7 +116,7 @@ namespace BlackMisc
|
|||||||
{
|
{
|
||||||
collectGarbage();
|
collectGarbage();
|
||||||
|
|
||||||
auto handlers = handlersForCategories(statusMessage.getCategories());
|
auto handlers = handlersForMessage(statusMessage);
|
||||||
|
|
||||||
if (isFallThroughEnabled(handlers))
|
if (isFallThroughEnabled(handlers))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,13 +12,14 @@
|
|||||||
|
|
||||||
//! \file
|
//! \file
|
||||||
|
|
||||||
|
#include "logpattern.h"
|
||||||
#include "statusmessage.h"
|
#include "statusmessage.h"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
namespace BlackMisc
|
namespace BlackMisc
|
||||||
{
|
{
|
||||||
class CLogCategoryHandler;
|
class CLogPatternHandler;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Class for subscribing to log messages.
|
* Class for subscribing to log messages.
|
||||||
@@ -41,9 +42,9 @@ namespace BlackMisc
|
|||||||
//! Tell the CLogHandler to install itself with qInstallMessageHandler.
|
//! Tell the CLogHandler to install itself with qInstallMessageHandler.
|
||||||
void install();
|
void install();
|
||||||
|
|
||||||
//! Return a category handler for subscribing to all messages with a category starting with the given prefix.
|
//! Return a pattern handler for subscribing to all messages which match the given pattern.
|
||||||
//! \warning This must only be called from the main thread.
|
//! \warning This must only be called from the main thread.
|
||||||
CLogCategoryHandler *handlerForCategoryPrefix(const QString &prefix);
|
CLogPatternHandler *handlerForPattern(const CLogPattern &pattern);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
//! Emitted when a message is logged in this process.
|
//! Emitted when a message is logged in this process.
|
||||||
@@ -67,34 +68,38 @@ namespace BlackMisc
|
|||||||
void collectGarbage();
|
void collectGarbage();
|
||||||
QtMessageHandler m_oldHandler = nullptr;
|
QtMessageHandler m_oldHandler = nullptr;
|
||||||
bool m_enableFallThrough = true;
|
bool m_enableFallThrough = true;
|
||||||
bool isFallThroughEnabled(const QList<CLogCategoryHandler *> &handlers) const;
|
bool isFallThroughEnabled(const QList<CLogPatternHandler *> &handlers) const;
|
||||||
QMap<QString, CLogCategoryHandler *> m_categoryPrefixHandlers;
|
using PatternPair = std::pair<CLogPattern, CLogPatternHandler *>;
|
||||||
QList<CLogCategoryHandler *> handlersForCategories(const CLogCategoryList &categories) const;
|
QList<PatternPair> m_patternHandlers;
|
||||||
|
QList<CLogPatternHandler *> handlersForMessage(const CStatusMessage &message) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* A class for subscribing to log messages in particular categories.
|
* A class for subscribing to log messages which match particular patterns.
|
||||||
* \sa CLogHandler::handlerForCategory
|
* \see CLogHandler::handlerForPattern
|
||||||
*/
|
*/
|
||||||
class CLogCategoryHandler : public QObject
|
class CLogPatternHandler : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/*!
|
/*!
|
||||||
* Enable or disable the default Qt handler for messages in relevant categories.
|
* Enable or disable the default Qt handler for messages which match the relevant pattern.
|
||||||
* This can override the setting of the parent CLogHandler.
|
*
|
||||||
|
* The setting of this property in one CLogPatternHandler can override the setting in another
|
||||||
|
* CLogPatternHandler or the base CLogHandler, if this handler's pattern is a subset of the
|
||||||
|
* other handler's pattern. Which is to say, more specific patterns can override less specific patterns.
|
||||||
*/
|
*/
|
||||||
void enableConsoleOutput(bool enable) { Q_ASSERT(thread() == QThread::currentThread()); m_enableFallThrough = enable; }
|
void enableConsoleOutput(bool enable) { Q_ASSERT(thread() == QThread::currentThread()); m_enableFallThrough = enable; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/*!
|
/*!
|
||||||
* Emitted when a message is logged in a relevant category.
|
* Emitted when a message is logged which matches the relevant pattern.
|
||||||
*
|
*
|
||||||
* When all slots are disconnected from this signal, the CLogCategoryHandler could be deleted.
|
* When all slots are disconnected from this signal, the CLogPatternHandler could be deleted.
|
||||||
*
|
*
|
||||||
* Note that if a message matches more that one category handler, then this signal will be emitted for all of them,
|
* Note that if a message matches more that one handler's pattern, then this signal will be emitted for all of
|
||||||
* so if a slot is connected to all of them then it will be called multiple times. Use the methods
|
* those handlers, so if a slot is connected to all of them then it will be called multiple times. Use the methods
|
||||||
* CStatusMessage::markAsHandledBy() and CStatusMessage::wasHandledBy() to detect this case in the slot and avoid
|
* CStatusMessage::markAsHandledBy() and CStatusMessage::wasHandledBy() to detect this case in the slot and avoid
|
||||||
* multiple handlings of the same message. Caveat: for this to work, the slot must take its argument by non-const
|
* multiple handlings of the same message. Caveat: for this to work, the slot must take its argument by non-const
|
||||||
* reference, and be connected by Qt::DirectConnection (i.e. the receiver is in the same thread as the CLogHandler).
|
* reference, and be connected by Qt::DirectConnection (i.e. the receiver is in the same thread as the CLogHandler).
|
||||||
@@ -103,7 +108,7 @@ namespace BlackMisc
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class CLogHandler;
|
friend class CLogHandler;
|
||||||
CLogCategoryHandler(QObject *parent, bool enableFallThrough) : QObject(parent), m_enableFallThrough(enableFallThrough) {}
|
CLogPatternHandler(QObject *parent, bool enableFallThrough) : QObject(parent), m_enableFallThrough(enableFallThrough) {}
|
||||||
bool m_enableFallThrough;
|
bool m_enableFallThrough;
|
||||||
|
|
||||||
bool canBeDeleted()
|
bool canBeDeleted()
|
||||||
|
|||||||
Reference in New Issue
Block a user