swift
loghandler.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2014 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_LOGHANDLER_H
7 #define SWIFT_MISC_LOGHANDLER_H
8 
9 #include <atomic>
10 #include <utility>
11 
12 #include <QHash>
13 #include <QList>
14 #include <QMetaMethod>
15 #include <QMetaObject>
16 #include <QObject>
17 #include <QPointer>
18 #include <QThread>
19 #include <QTimer>
20 #include <QtGlobal>
21 #include <QtMessageHandler>
22 
23 #include "misc/logcategory.h"
24 #include "misc/logpattern.h"
25 #include "misc/statusmessage.h"
26 #include "misc/swiftmiscexport.h"
27 #include "misc/tokenbucket.h"
28 
29 namespace swift::misc
30 {
31  class CLogPatternHandler;
32 
36  class SWIFT_MISC_EXPORT CLogHandler : public QObject
37  {
38  Q_OBJECT
39 
40  public:
42  CLogHandler();
43 
45  ~CLogHandler() override;
46 
49  static CLogHandler *instance();
50 
52  void install(bool skipIfAlreadyInstalled = false);
53 
57 
61 
65  {
66  return handlerForPattern(CLogPattern::exactMatch(CLogCategories::validation())
67  .withSeverityAtOrAbove(CStatusMessage::SeverityWarning));
68  }
69 
71  QList<CLogPattern> getAllSubscriptions() const;
72 
73  signals:
76 
79 
82 
85 
86  public slots:
89 
92 
94  void enableConsoleOutput(bool enable);
95 
96  private:
97  friend class CLogPatternHandler;
98  void logMessage(const swift::misc::CStatusMessage &message);
99  QtMessageHandler m_oldHandler = nullptr;
100  bool m_enableFallThrough = true;
101  bool isFallThroughEnabled(const QList<CLogPatternHandler *> &handlers) const;
102  using PatternPair = std::pair<CLogPattern, CLogPatternHandler *>;
103  QList<PatternPair> m_patternHandlers;
104  QList<CLogPatternHandler *> handlersForMessage(const CStatusMessage &message) const;
105  void removePatternHandler(CLogPatternHandler *);
107  };
108 
113  class SWIFT_MISC_EXPORT CLogPatternHandler : public QObject
114  {
115  Q_OBJECT
116 
117  public slots:
125  void enableConsoleOutput(bool enable)
126  {
127  Q_ASSERT(thread() == QThread::currentThread());
128  m_inheritFallThrough = false;
129  m_enableFallThrough = enable;
130  m_subscriptionNeedsUpdate = true;
131  }
132 
141  {
142  Q_ASSERT(thread() == QThread::currentThread());
143  m_inheritFallThrough = true;
144  m_subscriptionNeedsUpdate = true;
145  }
146 
147  signals:
161 
162  public:
166  template <typename T, typename F>
167  QMetaObject::Connection subscribe(T *receiver, F slot)
168  {
169  return connect(this, &CLogPatternHandler::messageLogged, receiver, slot);
170  }
171 
175  template <typename F>
176  QMetaObject::Connection subscribe(F slot)
177  {
178  return connect(this, &CLogPatternHandler::messageLogged, slot);
179  }
180 
181  protected:
183  void connectNotify(const QMetaMethod &signal) override
184  {
185  if (signal == QMetaMethod::fromSignal(&CLogPatternHandler::messageLogged))
186  {
187  m_subscriptionNeedsUpdate = true;
188  }
189  }
190 
192  void disconnectNotify(const QMetaMethod &signal) override
193  {
194  if (signal == QMetaMethod::fromSignal(&CLogPatternHandler::messageLogged))
195  {
196  m_subscriptionNeedsUpdate = true;
197  }
198  }
199 
200  private:
201  friend class CLogHandler;
202  CLogPatternHandler(CLogHandler *parent, const CLogPattern &pattern);
203  CLogHandler *m_parent = nullptr;
204  CLogPattern m_pattern;
205  bool m_inheritFallThrough = true;
206  bool m_enableFallThrough = true;
207  bool m_isSubscribed = false;
208  std::atomic<bool> m_subscriptionNeedsUpdate { false };
209  QTimer m_subscriptionUpdateTimer;
210  void updateSubscription();
211  };
212 
219  class SWIFT_MISC_EXPORT CLogSubscriber : public QObject
220  {
221  Q_OBJECT
222 
223  public:
225  CLogSubscriber(QObject *parent = nullptr) : QObject(parent) {}
226 
228  template <typename T, typename F>
229  CLogSubscriber(T *parent, F slot) : QObject(parent)
230  {
231  QObject::connect(this, &CLogSubscriber::ps_messageLogged, parent, slot);
232  }
233 
236  void changeSubscription(const CLogPattern &pattern);
237 
240  void unsubscribe();
241 
244  void enableConsoleOutput(bool enable);
245 
249 
250  signals:
252  void ps_messageLogged(const swift::misc::CStatusMessage &message);
253 
254  private slots:
255  void ps_logMessage(const swift::misc::CStatusMessage &message) { emit ps_messageLogged(message); }
256 
257  private:
258  QPointer<CLogPatternHandler> m_handler;
259  bool m_inheritFallThrough = true;
260  bool m_enableFallThrough = true;
261  };
262 } // namespace swift::misc
263 
264 #endif // SWIFT_MISC_LOGHANDLER_H
static const QString & validation()
Validation.
Definition: logcategories.h:38
A log category is an arbitrary string tag which can be attached to log messages.
Definition: logcategory.h:28
Class for subscribing to log messages.
Definition: loghandler.h:37
void localMessageLogged(const swift::misc::CStatusMessage &message)
Emitted when a message is logged in this process.
void enableConsoleOutput(bool enable)
Enable or disable the default Qt handler.
void subscriptionAdded(const swift::misc::CLogPattern &pattern)
Emitted when an object subscribes to a pattern of log messages.
QList< CLogPattern > getAllSubscriptions() const
Returns all log patterns for which there are currently subscribed log pattern handlers.
static CLogHandler * instance()
Return pointer to the CLogHandler singleton.
CLogPatternHandler * handlerForCategory(const CLogCategory &category)
Return a pattern handler for subscribing to all messages which contain the given category.
CLogPatternHandler * handlerForPattern(const CLogPattern &pattern)
Return a pattern handler for subscribing to all messages which match the given pattern.
void logLocalMessage(const swift::misc::CStatusMessage &message)
Called by our QtMessageHandler to log a message.
void logRemoteMessage(const swift::misc::CStatusMessage &message)
Called by the context to relay a message.
void remoteMessageLogged(const swift::misc::CStatusMessage &message)
Emitted when a log message is relayed from a different process.
void install(bool skipIfAlreadyInstalled=false)
Tell the CLogHandler to install itself with qInstallMessageHandler.
CLogPatternHandler * handlerForValidation()
Return a pattern handler for subscribing to all validation warnings and errors.
Definition: loghandler.h:64
void subscriptionRemoved(const swift::misc::CLogPattern &pattern)
Emitted when an object unsubscribes from a pattern of log messages.
A class for subscribing to log messages which match particular patterns.
Definition: loghandler.h:114
void connectNotify(const QMetaMethod &signal)
Definition: loghandler.h:183
void disconnectNotify(const QMetaMethod &signal)
Definition: loghandler.h:192
QMetaObject::Connection subscribe(T *receiver, F slot)
Convenience method to connect the messageLogged signal to a slot in the given receiver object.
Definition: loghandler.h:167
void enableConsoleOutput(bool enable)
Enable or disable the default Qt handler for messages which match the relevant pattern.
Definition: loghandler.h:125
QMetaObject::Connection subscribe(F slot)
Convenience method to connect the messageLogged signal to a functor.
Definition: loghandler.h:176
void inheritConsoleOutput()
The policy of whether to enable or disable the default Qt handler for messages which match the releva...
Definition: loghandler.h:140
void messageLogged(const swift::misc::CStatusMessage &message)
Emitted when a message is logged which matches the relevant pattern.
Value class for matching log messages based on their categories.
Definition: logpattern.h:49
static CLogPattern exactMatch(const CLogCategory &category)
Returns a CLogPattern which will match any message with the given category.
Definition: logpattern.cpp:101
A helper class for subscribing to log messages matching a particular pattern, with the ability to cha...
Definition: loghandler.h:220
void enableConsoleOutput(bool enable)
Enable or disable the default Qt handler for messages which match the relevant pattern.
void inheritConsoleOutput()
The policy of whether to enable or disable the default Qt handler for messages which match the releva...
void changeSubscription(const CLogPattern &pattern)
Change the pattern which you want to subscribe to.
void unsubscribe()
Unsubscribe from all messages.
CLogSubscriber(QObject *parent=nullptr)
Default constructor, for when you're not interested in messages and just want to control the console ...
Definition: loghandler.h:225
CLogSubscriber(T *parent, F slot)
Construct a subscriber which forwards messages to the given slot of parent.
Definition: loghandler.h:229
Streamable status message, e.g.
constexpr static auto SeverityWarning
Status severities.
Free functions in swift::misc.
#define SWIFT_MISC_EXPORT
Export a class or function from the library.