File indexing completed on 2024-11-24 04:44:12
0001 /* 0002 * SPDX-FileCopyrightText: 2012 Christian Mollekopf <mollekopf@kolabsys.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-3.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "kolab_export.h" 0010 0011 #include <QDebug> 0012 #include <QIODevice> 0013 #include <QList> 0014 #include <QString> 0015 0016 namespace Kolab 0017 { 0018 class DebugStream; 0019 /** 0020 * Kolab Error Handler 0021 * 0022 * Errors are reported during an operation, but the operation might still succeed. 0023 * The error handler therefore contains all errors which occurred during a single operation, 0024 * and must be cleared at the start of a new operation. 0025 * 0026 * A user of the kolabobject classes should check ErrorHandler::error() after every operation. 0027 * 0028 * all non-const functions are not for the user of this class and only exist for internal usage. 0029 * 0030 * TODO: Hide everything which is not meant for the user from the interface. 0031 * FIXME: Use Threadlocal storage to make this threadsafe. 0032 */ 0033 class KOLAB_EXPORT ErrorHandler 0034 { 0035 public: 0036 enum Severity { 0037 Debug, 0038 Warning, // Warning, error could be corrected, object can be used without dataloss. This warning is also used if dataloss is acceptable because a 0039 // feature is explicitly not supported. 0040 Error, // Potentially corrupt object, writing the object back could result in dataloss. (Object could still be used to display the data readonly). 0041 Critical // Critical error, produced object cannot be used and should be thrown away (writing back will result in dataloss). 0042 }; 0043 0044 struct Err { 0045 Err(Severity s, const QString &m, const QString &l) 0046 : severity(s) 0047 , message(m) 0048 , location(l) 0049 { 0050 } 0051 0052 Severity severity; 0053 QString message; 0054 QString location; 0055 }; 0056 0057 static ErrorHandler &instance() 0058 { 0059 static ErrorHandler inst; 0060 return inst; 0061 } 0062 0063 void addError(Severity s, const QString &message, const QString &location); 0064 const QList<Err> &getErrors() const; 0065 Severity error() const; 0066 QString errorMessage() const; 0067 void clear(); 0068 0069 /** 0070 * Check for errors during the libkolabxml reading/writing process and copy them into this error handler. 0071 */ 0072 static void handleLibkolabxmlErrors(); 0073 0074 static void clearErrors() 0075 { 0076 ErrorHandler::instance().clear(); 0077 } 0078 0079 static bool errorOccured() 0080 { 0081 if (ErrorHandler::instance().error() >= Error) { 0082 return true; 0083 } 0084 return false; 0085 } 0086 0087 /** 0088 * Returns a debug stream to which logs errors 0089 */ 0090 static QDebug debugStream(Severity, int line, const char *file); 0091 0092 private: 0093 ErrorHandler(); 0094 ErrorHandler(const ErrorHandler &) = delete; 0095 ErrorHandler &operator=(const ErrorHandler &) = delete; 0096 0097 Severity m_worstError; 0098 QString m_worstErrorMessage; 0099 QList<Err> m_errorQueue; 0100 QScopedPointer<DebugStream> m_debugStream; 0101 }; 0102 0103 void logMessage(const QString &, const QString &, int, ErrorHandler::Severity s); 0104 0105 #define LOG(message) logMessage(message, __FILE__, __LINE__, ErrorHandler::Debug); 0106 #define WARNING(message) logMessage(message, __FILE__, __LINE__, ErrorHandler::Warning); 0107 #define ERROR(message) logMessage(message, __FILE__, __LINE__, ErrorHandler::Error); 0108 #define CRITICAL(message) logMessage(message, QStringLiteral(__FILE__), __LINE__, ErrorHandler::Critical); 0109 0110 class DebugStream : public QIODevice 0111 { 0112 Q_OBJECT 0113 public: 0114 QString m_location; 0115 ErrorHandler::Severity m_severity; 0116 DebugStream(); 0117 ~DebugStream() override; 0118 bool isSequential() const override 0119 { 0120 return true; 0121 } 0122 0123 qint64 readData(char *, qint64) override 0124 { 0125 return 0; /* eof */ 0126 } 0127 0128 qint64 readLineData(char *, qint64) override 0129 { 0130 return 0; /* eof */ 0131 } 0132 0133 qint64 writeData(const char *data, qint64 len) override; 0134 0135 private: 0136 Q_DISABLE_COPY(DebugStream) 0137 }; 0138 0139 #define Debug() Kolab::ErrorHandler::debugStream(Kolab::ErrorHandler::Debug, __LINE__, __FILE__) 0140 #define Warning() Kolab::ErrorHandler::debugStream(Kolab::ErrorHandler::Warning, __LINE__, __FILE__) 0141 #define Error() Kolab::ErrorHandler::debugStream(Kolab::ErrorHandler::Error, __LINE__, __FILE__) 0142 #define Critical() Kolab::ErrorHandler::debugStream(Kolab::ErrorHandler::Critical, __LINE__, __FILE__) 0143 } 0144 0145 QDebug operator<<(QDebug dbg, const std::string &s);