logerror.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /******************************************************************************
  2. *
  3. * package: Log4Qt
  4. * file: logerror.h
  5. * created: September 2007
  6. * author: Martin Heinrich
  7. *
  8. *
  9. * Copyright 2007 Martin Heinrich
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ******************************************************************************/
  24. #ifndef LOG4QT_LOGERROR_H
  25. #define LOG4QT_LOGERROR_H
  26. /******************************************************************************
  27. * Dependencies
  28. ******************************************************************************/
  29. #include <QtCore/QString>
  30. #include <QtCore/QVariant>
  31. /******************************************************************************
  32. * Declarations
  33. ******************************************************************************/
  34. namespace Log4Qt
  35. {
  36. /*!
  37. * Creates an LogError object with the error message \a message, the error
  38. * code \a code and the context \a context. The symbol of the error is
  39. * set to \a code as string value.
  40. *
  41. * The following example logs an error, if a character is not a digit.
  42. *
  43. * \code
  44. * if (!c.isDigit())
  45. * {
  46. * Error e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."),
  47. * LAYOUT_EXPECTED_DIGIT_ERROR,
  48. * "Log4Qt::PatternFormatter");
  49. * e << QString(c);
  50. * logger()->error(e);
  51. * }
  52. * \endcode
  53. */
  54. #define LOG4QT_ERROR(message, code, context) \
  55. LogError(message, code, #code, context)
  56. /*!
  57. * Creates an LogError object with the error message \a message and the
  58. * error code \a code. The symbol of the error is set to \a code as string
  59. * value. The context is set to the class name of the current object. The
  60. * current objects class must be derived from QObject.
  61. *
  62. * The following example handles an error while opening a file.
  63. *
  64. * \code
  65. * if (!mpFile->open(mode))
  66. * {
  67. * LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"),
  68. * APPENDER_OPENING_FILE_ERROR);
  69. * e << mFileName << name();
  70. * e.addCausingError(LogError(mpFile->errorString(), mpFile->error()));
  71. * logger()->error(e);
  72. * return;
  73. * }
  74. * \endcode
  75. */
  76. #define LOG4QT_QCLASS_ERROR(message, code) \
  77. LogError(message, code, #code, this->metaObject()->className())
  78. /*!
  79. * \brief The class LogError represents an error.
  80. *
  81. * The class error allows storing error information in a structured way.
  82. * The error message is stored separately from the information that may be
  83. * substituted into the message string. This way it is possible to access
  84. * all information after the error has been raised. It also allows to
  85. * translate the error at a later point in time or to get a translated and
  86. * a not translated error text (e.g. translated for the UI and not
  87. * translated for a log).
  88. *
  89. * The message is accessed using message() and setMessage(). Arguments for
  90. * the message can be added using addArg() or operator<<(). The arguments
  91. * can be retrieved using args(). The message with substituted arguments
  92. * is returned by messageWithArgs().
  93. *
  94. * An error code can be set as integer value code() and/or a symbolic value
  95. * symbol().
  96. *
  97. * To allow the translation of the message the error stores the translation
  98. * context (context(), setContext()). The translated message can be accessed
  99. * using translatedMessage() or using translatedMessageWithArgs(), if it
  100. * should contain the arguments.
  101. *
  102. * An error can have one or more related errors that caused it. An error is
  103. * related using addCausingError(). All causing errors can be retrieved using
  104. * causingErrors().
  105. *
  106. * A per thread error can be maintained using lastError() and setLastError().
  107. *
  108. * There are two macros avaiable to simplify the error creation. The macro
  109. * \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" is used with classes not derived
  110. * from QObject. The macro \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR"
  111. * is used with classes derived from QObject.
  112. */
  113. class LogError
  114. {
  115. public:
  116. /*!
  117. * The enum Encoding defines the 8-bit encoding of a character string
  118. * arguments to \ref LogError::LogError(const char *, int, const char *,
  119. * const char *, Encoding) "LogError::LogError()".
  120. *
  121. * \sa \ref LogError::LogError(const char *, int, const char *, const char *, Encoding) "LogError::LogError()"
  122. */
  123. enum Encoding
  124. {
  125. /*! LATIN-1 */
  126. LATIN1,
  127. /*!
  128. * The encoding specified by QTextCodec::codecForTr()
  129. * (Latin-1 if none has been set).
  130. */
  131. CODECFORTR,
  132. /*! UTF-8 */
  133. UNICODEUTF8
  134. };
  135. Q_ENUMS(Encoding)
  136. /*!
  137. * Creates an empty error. The error code is set to 0 and all other
  138. * members are set to be empty.
  139. *
  140. * \sa isEmpty()
  141. */
  142. LogError();
  143. /*!
  144. * Creates an error with the Message \a rMessage and the error code
  145. * \a code. The symbol for the error code is set to \a rSymbol and the
  146. * context to \a rContext.
  147. *
  148. * \a rContext must be string that can be converted to Latin-1. The
  149. * Latin-1 representation of the string is used with
  150. * QApplication::translate(), if a translation for \a rMessage is
  151. * requested.
  152. *
  153. * \sa translatedMessage(), translatedMessageWithArgs()
  154. */
  155. LogError(const QString &rMessage,
  156. int code = 0,
  157. const QString &rSymbol = QString(),
  158. const QString &rContext = QString());
  159. /*!
  160. * Creates an error with the Message \a pMessage and the error code
  161. * \a code. The symbol for the error code is set to \a pSymbol and the
  162. * context to \a pContext.
  163. *
  164. * \a encoding specifies the encoding of \a pMessage. \a pSymbol and
  165. * \a pContext are expected to be Latin-1.
  166. *
  167. * \note To support the macros \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR"
  168. * and \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR"
  169. * the function tests, if \a pSymbol is the string representation of
  170. * \a code. If it is, the symbol is set to be empty. Otherwise symbol
  171. * is set to \a pSymbol.
  172. *
  173. * \sa translatedMessage(), translatedMessageWithArgs()
  174. */
  175. LogError(const char *pMessage,
  176. int code = 0,
  177. const char *pSymbol = 0,
  178. const char *pContext = 0,
  179. Encoding encoding = LATIN1);
  180. // LogError(const LogError &rOther); // Use compiler default
  181. // virtual ~LogError(); // Use compiler default
  182. // LogError &operator=(const LogError &rOther); // Use compiler default
  183. /*!
  184. * Returns the error code.
  185. *
  186. * \sa setCode()
  187. */
  188. int code() const;
  189. /*!
  190. * Returns the context for the error.
  191. *
  192. * \sa setContext()
  193. */
  194. QString context() const;
  195. /*!
  196. * Returns the error message.
  197. *
  198. * \sa setMessage()
  199. */
  200. QString message() const;
  201. /*!
  202. * Returns the symbol for the error code.
  203. *
  204. * \sa setSymbol()
  205. */
  206. QString symbol() const;
  207. /*!
  208. * Returns the translated error message.
  209. *
  210. * The translated message is created by calling
  211. * QCoreApplication::translate() using context().toLatin1() as
  212. * context and message.toUtf8() as message.
  213. *
  214. * \sa translatedMessageWithArgs()
  215. */
  216. QString translatedMessage() const;
  217. /*!
  218. * Sets the error code to \a code.
  219. *
  220. * \sa code()
  221. */
  222. void setCode(int code);
  223. /*!
  224. * Sets the context to \a rClassName.
  225. *
  226. * \a rContext must be string that can be converted to Latin-1. The
  227. * Latin-1 representation of the string is used with
  228. * QApplication::translate(), if a translation for \a rMessage is
  229. * requestd.
  230. *
  231. * \sa context(), translatedMessage(), translatedMessageWithArgs()
  232. */
  233. void setContext(const QString &rClassName);
  234. /*!
  235. * Sets the error message to \a rMessage
  236. *
  237. * \sa message()
  238. */
  239. void setMessage(const QString &rMessage);
  240. /*!
  241. * Sets the symbol for the error code to \a rSymbol.
  242. *
  243. * \sa symbol()
  244. */
  245. void setSymbol(const QString &rSymbol);
  246. /*!
  247. * Returns the last error set for the current thread using
  248. * setLastError().
  249. *
  250. * \note: This function is thread-safe.
  251. *
  252. * \sa setLastError()
  253. */
  254. static LogError lastError();
  255. /*!
  256. * Sets the last error for the current thread to \a rLogError.
  257. *
  258. * \note: This function is thread-safe.
  259. *
  260. * \sa lastError()
  261. */
  262. static void setLastError(const LogError &rLogError);
  263. /*!
  264. * Appends \a rArg to the list of arguments and returns a reference to
  265. * this error.
  266. *
  267. * \sa operator<<(), args(), clearArgs()
  268. */
  269. LogError &addArg(const QVariant &rArg);
  270. /*!
  271. * This is an overloaded member function, provided for convenience.
  272. */
  273. LogError &addArg(int arg);
  274. /*!
  275. * This is an overloaded member function, provided for convenience.
  276. */
  277. LogError &addArg(const QString &rArg);
  278. /*!
  279. * Appends \a rLogError to the list of causing errors and returns a
  280. * reference to this error.
  281. *
  282. * \sa causingErrors(), clearCausingErrors()
  283. */
  284. LogError &addCausingError(const LogError &rLogError);
  285. /*!
  286. * Returns the list of arguments that have been added to this error.
  287. *
  288. * \sa addArg(), operator<<(), clearArgs()
  289. */
  290. QList<QVariant> args() const;
  291. /*!
  292. * Returns the list of causing errors that have been added to this error.
  293. *
  294. * \sa addArg(), operator<<(), clearArgs()
  295. */
  296. QList<LogError> causingErrors() const;
  297. /*!
  298. * Clears the list of arguments that have been added to this error.
  299. *
  300. * \sa addArg(), operator<<(), args()
  301. */
  302. void clearArgs();
  303. /*!
  304. * Clears the list of causing errors that have been added to this error.
  305. *
  306. * \sa addCausingError(), causingErrors()
  307. */
  308. void clearCausingErrors();
  309. /*!
  310. * Returns true, if the error code is 0 and the message is empty.
  311. * Otherwise it returns false.
  312. *
  313. * \sa code(), message()
  314. */
  315. bool isEmpty() const;
  316. /*!
  317. * Returns the message with arguments. The arguments are incoorporated
  318. * into the messag using QString::arg().
  319. *
  320. * \sa QString::arg(), translatedMessageWithArgs()
  321. */
  322. QString messageWithArgs() const;
  323. /*!
  324. * Returns the translated message with arguments. The arguments are
  325. * incoorporated into the messag using QString::arg().
  326. *
  327. * \sa QString::arg(), messageWithArgs(), translatedMessage()
  328. */
  329. QString translatedMessageWithArgs() const;
  330. /*!
  331. * Appends \a rArg to the list of arguments and returns a reference to
  332. * this error.
  333. *
  334. * \sa addArg()
  335. */
  336. LogError &operator<<(const QVariant &rArg);
  337. /*!
  338. * This is an overloaded member function, provided for convenience.
  339. */
  340. LogError &operator<<(int arg);
  341. /*!
  342. * This is an overloaded member function, provided for convenience.
  343. */
  344. LogError &operator<<(const QString &rArg);
  345. /*!
  346. * Returns a string representation of the error.
  347. *
  348. * The string has the following format:
  349. *
  350. * <tt>
  351. * message (context::symbol, code): causing_error, causing_error
  352. * </tt>
  353. *
  354. * If members are empty they are omitted:
  355. * - Omit context, if empty
  356. * - Omit symbol, if empty
  357. * - Omit double colon with context and symbol, if both are empty
  358. * - Omit code, if 0
  359. * - Omit bracket with context/symbol and code, if all are empty
  360. * - Omit colon with causing errors, if no causing errors exist
  361. */
  362. QString toString() const;
  363. private:
  364. QString insertArgs(const QString &rMessage) const;
  365. QString cleanMessage(const QString &rMessage);
  366. private:
  367. int mCode;
  368. QString mContext;
  369. QString mMessage;
  370. QString mSymbol;
  371. QList<QVariant> mArgs;
  372. QList<LogError> mCausingErrors;
  373. #ifndef QT_NO_DATASTREAM
  374. // Needs to be friend to stream objects
  375. friend QDataStream &operator<<(QDataStream &rStream,
  376. const LogError &rLogError);
  377. friend QDataStream &operator>>(QDataStream &rStream,
  378. LogError &rLogError);
  379. #endif // QT_NO_DATASTREAM
  380. };
  381. /**************************************************************************
  382. * Operators, Helper
  383. **************************************************************************/
  384. #ifndef QT_NO_DATASTREAM
  385. /*!
  386. * \relates LogError
  387. *
  388. * Writes the given error \a rLogError to the given stream \a rStream,
  389. * and returns a reference to the stream.
  390. */
  391. QDataStream &operator<<(QDataStream &rStream,
  392. const LogError &rLogError);
  393. /*!
  394. * \relates LogError
  395. *
  396. * Reads an error from the given stream \a rStream into the given
  397. * error \a rLogError, and returns a reference to the stream.
  398. */
  399. QDataStream &operator>>(QDataStream &rStream,
  400. LogError &rLogError);
  401. #endif // QT_NO_DATASTREAM
  402. #ifndef QT_NO_DEBUG_STREAM
  403. /*!
  404. * \relates LogError
  405. *
  406. * Writes all object member variables to the given debug stream \a debug and
  407. * returns the stream.
  408. *
  409. * <tt>
  410. * %LogError(code:7 context:"Log4Qt::FileAppender"
  411. * message:"Unable to open file '%1' for appender '%2'"
  412. * symbol:"APPENDER_OPENING_FILE_ERROR"
  413. * args:(QVariant(QString, "G:\logs\client.log") , QVariant(QString, "Client FileAppender") )
  414. * translatedMessage: "Unable to open file '%1' for appender '%2'" )
  415. * </tt>
  416. *
  417. * \sa QDebug
  418. */
  419. QDebug operator<<(QDebug debug,
  420. const LogError &rLogError);
  421. #endif // QT_NO_DEBUG_STREAM
  422. /**************************************************************************
  423. * Inline
  424. **************************************************************************/
  425. inline int LogError::code() const
  426. { return mCode; }
  427. inline QString LogError::context() const
  428. { return mContext; }
  429. inline QString LogError::message() const
  430. { return mMessage; }
  431. inline QString LogError::symbol() const
  432. { return mSymbol; }
  433. inline void LogError::setCode(int code)
  434. { mCode = code; }
  435. inline void LogError::setContext(const QString &rContext)
  436. { mContext = rContext; }
  437. inline void LogError::setMessage(const QString &rMessage)
  438. { mMessage = cleanMessage(rMessage); }
  439. inline void LogError::setSymbol(const QString &rSymbol)
  440. { mSymbol = rSymbol; }
  441. inline LogError &LogError::addArg(const QVariant &rArg)
  442. { mArgs << rArg; return *this; }
  443. inline LogError &LogError::addArg(int arg)
  444. { mArgs << QVariant(arg); return *this; }
  445. inline LogError &LogError::addArg(const QString &rArg)
  446. { mArgs << QVariant(rArg); return *this; }
  447. inline LogError &LogError::addCausingError(const LogError &rLogError)
  448. { mCausingErrors << rLogError; return *this; }
  449. inline QList<QVariant> LogError::args() const
  450. { return mArgs; }
  451. inline void LogError::clearArgs()
  452. { mArgs.clear(); }
  453. inline void LogError::clearCausingErrors()
  454. { mCausingErrors.clear(); }
  455. inline QList<LogError> LogError::causingErrors() const
  456. { return mCausingErrors; }
  457. inline bool LogError::isEmpty() const
  458. { return mCode || !mMessage.isEmpty(); }
  459. inline QString LogError::messageWithArgs() const
  460. { return insertArgs(message()); }
  461. inline QString LogError::translatedMessageWithArgs() const
  462. { return insertArgs(translatedMessage()); }
  463. inline LogError &LogError::operator<<(const QVariant &rArg)
  464. { return addArg(rArg); }
  465. inline LogError &LogError::operator<<(int arg)
  466. { return addArg(arg); }
  467. inline LogError &LogError::operator<<(const QString &rArg)
  468. { return addArg(rArg); }
  469. } // namespace Log4Qt
  470. Q_DECLARE_METATYPE(Log4Qt::LogError)
  471. Q_DECLARE_TYPEINFO(Log4Qt::LogError, Q_MOVABLE_TYPE);
  472. #endif // LOG4QT_ERROR_H