logerror.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /******************************************************************************
  2. *
  3. * package: Log4Qt
  4. * file: logerror.cpp
  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. /******************************************************************************
  25. * Dependencies
  26. *****************************************************************************/
  27. #include "log4qt/helpers/logerror.h"
  28. #include <QtCore/QBuffer>
  29. #include <QtCore/QByteArray>
  30. #include <QtCore/QDataStream>
  31. #include <QtCore/QCoreApplication>
  32. #include <QtCore/QDebug>
  33. #include <QtCore/QTextCodec>
  34. #include <QtCore/QThreadStorage>
  35. #include "log4qt/helpers/initialisationhelper.h"
  36. namespace Log4Qt
  37. {
  38. /**************************************************************************
  39. * Declarations
  40. **************************************************************************/
  41. typedef QThreadStorage<LogError *> ThreadError;
  42. /**************************************************************************
  43. * C helper functions
  44. **************************************************************************/
  45. LOG4QT_GLOBAL_STATIC(ThreadError, thread_error)
  46. /**************************************************************************
  47. * Class implementation: LogError
  48. **************************************************************************/
  49. LogError::LogError() :
  50. mCode(0),
  51. mContext(),
  52. mMessage(),
  53. mSymbol(),
  54. mArgs(),
  55. mCausingErrors()
  56. {
  57. }
  58. LogError::LogError(const QString &rMessage,
  59. int code,
  60. const QString &rSymbol,
  61. const QString &rContext) :
  62. mCode(code),
  63. mContext(rContext),
  64. mMessage(cleanMessage(rMessage)),
  65. mSymbol(rSymbol),
  66. mArgs(),
  67. mCausingErrors()
  68. {
  69. }
  70. LogError::LogError(const char *pMessage,
  71. int code,
  72. const char *pSymbol,
  73. const char *pContext,
  74. Encoding encoding) :
  75. mCode(code),
  76. mContext(QString::fromLatin1(pContext)),
  77. mMessage(),
  78. mSymbol(QString::fromLatin1(pSymbol)),
  79. mArgs(),
  80. mCausingErrors()
  81. {
  82. switch(encoding)
  83. {
  84. case LATIN1:
  85. mMessage = QString::fromLatin1(pMessage);
  86. break;
  87. case CODECFORTR:
  88. #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
  89. mMessage = QTextCodec::codecForTr()->toUnicode(pMessage);
  90. #else
  91. mMessage = QString::fromUtf8(pMessage);
  92. #endif
  93. break;
  94. case UNICODEUTF8:
  95. mMessage = QString::fromUtf8(pMessage);
  96. break;
  97. default:
  98. Q_ASSERT_X(false, "LogError::LogError", "Unkown encoding constant");
  99. mMessage = QString::fromLatin1(pMessage);
  100. }
  101. mMessage = cleanMessage(mMessage);
  102. if (mSymbol == QString::number(mCode))
  103. mSymbol.clear();
  104. }
  105. QString LogError::translatedMessage() const
  106. {
  107. #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
  108. return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0, QCoreApplication::UnicodeUTF8);
  109. #else
  110. return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0);
  111. #endif
  112. }
  113. LogError LogError::lastError()
  114. {
  115. if (!thread_error()->hasLocalData())
  116. return LogError();
  117. else
  118. return *thread_error()->localData();
  119. }
  120. void LogError::setLastError(const LogError &rLogError)
  121. {
  122. if (!thread_error()->hasLocalData())
  123. thread_error()->setLocalData(new LogError);
  124. *thread_error()->localData() = rLogError;
  125. }
  126. QString LogError::toString() const
  127. {
  128. QString result = messageWithArgs();
  129. QString context_symbol = mContext;
  130. if (!context_symbol.isEmpty() && !mSymbol.isEmpty())
  131. context_symbol.append(QLatin1String("::"));
  132. context_symbol.append(mSymbol);
  133. if (!context_symbol.isEmpty() || mCode)
  134. {
  135. result.append(QLatin1String(" ("));
  136. if (!context_symbol.isEmpty())
  137. result.append(context_symbol);
  138. if (!context_symbol.isEmpty() && mCode)
  139. result.append(QLatin1String(", "));
  140. if (mCode)
  141. result.append(QString::number(mCode));
  142. result.append(QLatin1String(")"));
  143. }
  144. if (!mCausingErrors.isEmpty())
  145. {
  146. QString causing_errors_str = QLatin1String(": ") + mCausingErrors.at(0).toString();
  147. int i = 1;
  148. while (i < mCausingErrors.count())
  149. {
  150. causing_errors_str.append(QLatin1String(", ")).append(mCausingErrors.at(i).toString());
  151. i++;
  152. }
  153. result.append(causing_errors_str);
  154. }
  155. return result;
  156. }
  157. QString LogError::insertArgs(const QString &rMessage) const
  158. {
  159. QString result;
  160. /*
  161. // Don't use a loop to be able to handle arguments that conatin strings
  162. // like %1.
  163. // Using this method only 9 arguments can be handled as the %1
  164. // in %11 gets also replaced with the first argument.
  165. switch (mArgs.count())
  166. {
  167. case 0:
  168. break;
  169. case 1:
  170. result = rMessage.arg(mArgs.at(0));
  171. break;
  172. case 2:
  173. result = rMessage.arg(mArgs.at(0), mArgs.at(1));
  174. break;
  175. case 3:
  176. result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2));
  177. break;
  178. case 4:
  179. result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3));
  180. break;
  181. case 5:
  182. result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4));
  183. break;
  184. case 6:
  185. result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5));
  186. break;
  187. case 7:
  188. result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6));
  189. break;
  190. case 8:
  191. result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7));
  192. break;
  193. default:
  194. result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7), mArgs.at(8));
  195. break;
  196. }
  197. if (mArgs.count() > 9)
  198. {
  199. int i = 9;
  200. while(i < mArgs.count())
  201. {
  202. result = result.arg(mArgs.at(i));
  203. i++;
  204. }
  205. }
  206. */
  207. result = rMessage;
  208. QVariant arg;
  209. Q_FOREACH(arg, mArgs)
  210. result = result.arg(arg.toString());
  211. return result;
  212. }
  213. QString LogError::cleanMessage(const QString &rMessage)
  214. {
  215. if (rMessage.isEmpty())
  216. return rMessage;
  217. QString result = rMessage;
  218. if (rMessage.at(rMessage.size() - 1) == QLatin1Char('.'))
  219. result = rMessage.left(rMessage.size() - 1);
  220. return result;
  221. }
  222. /**************************************************************************
  223. * Implementation: Operators, Helper
  224. **************************************************************************/
  225. #ifndef QT_NO_DATASTREAM
  226. QDataStream &operator<<(QDataStream &rStream,
  227. const LogError &rLogError)
  228. {
  229. QBuffer buffer;
  230. buffer.open(QIODevice::WriteOnly);
  231. QDataStream stream(&buffer);
  232. // version
  233. quint16 version = 0;
  234. stream << version;
  235. // version 0 data
  236. stream << rLogError.mCode
  237. << rLogError.mContext
  238. << rLogError.mMessage
  239. << rLogError.mSymbol
  240. << rLogError.mArgs
  241. << rLogError.mCausingErrors;
  242. buffer.close();
  243. rStream << buffer.buffer();
  244. return rStream;
  245. }
  246. QDataStream &operator>>(QDataStream &rStream,
  247. LogError &rLogError)
  248. {
  249. QByteArray array;
  250. rStream >> array;
  251. QBuffer buffer(&array);
  252. buffer.open(QIODevice::ReadOnly);
  253. QDataStream stream(&buffer);
  254. // version
  255. quint16 version;
  256. stream >> version;
  257. // Version 0 data
  258. QString level;
  259. QString logger;
  260. stream >> rLogError.mCode
  261. >> rLogError.mContext
  262. >> rLogError.mMessage
  263. >> rLogError.mSymbol
  264. >> rLogError.mArgs
  265. >> rLogError.mCausingErrors;
  266. buffer.close();
  267. return rStream;
  268. }
  269. #endif // QT_NO_DATASTREAM
  270. #ifndef QT_NO_DEBUG_STREAM
  271. QDebug operator<<(QDebug debug,
  272. const LogError &rLogError)
  273. {
  274. // Escape % sign
  275. QString message = rLogError.message();
  276. message.replace(QLatin1String("%"), QLatin1String("%%"));
  277. debug.nospace() << "LogError("
  278. << "code:" << rLogError.code() << " "
  279. << "context:" << rLogError.context() << " "
  280. << "message:" << message << " "
  281. << "symbol:" << rLogError.symbol() << " "
  282. << "args:" << rLogError.args()
  283. << "translatedMessage:" << rLogError.translatedMessage()
  284. << ")";
  285. return debug.maybeSpace();
  286. }
  287. #endif // QT_NO_DEBUG_STREAM
  288. } // namespace Log4Qt