ctkErrorLogModel.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QApplication>
  16. #include <QDateTime>
  17. #include <QDebug>
  18. #include <QFile>
  19. #include <QMainWindow>
  20. #include <QMetaEnum>
  21. #include <QMetaType>
  22. #include <QMutexLocker>
  23. #include <QPointer>
  24. #include <QStandardItem>
  25. #include <QStatusBar>
  26. // CTK includes
  27. #include "ctkErrorLogModel.h"
  28. #include <ctkPimpl.h>
  29. #include <unistd.h>
  30. // STD includes
  31. #include <cstdio> // For _fileno or fileno
  32. #ifdef _MSC_VER
  33. # include <io.h> // For _write()
  34. #else
  35. # include <unistd.h>
  36. #endif
  37. // --------------------------------------------------------------------------
  38. // ctkErrorLogLevel methods
  39. // --------------------------------------------------------------------------
  40. ctkErrorLogLevel::ctkErrorLogLevel()
  41. {
  42. qRegisterMetaType<ctkErrorLogLevel::LogLevel>("ctkErrorLogLevel::LogLevel");
  43. }
  44. // --------------------------------------------------------------------------
  45. QString ctkErrorLogLevel::operator()(ctkErrorLogLevel::LogLevel logLevel)
  46. {
  47. return this->logLevelAsString(logLevel);
  48. }
  49. // --------------------------------------------------------------------------
  50. QString ctkErrorLogLevel::logLevelAsString(ctkErrorLogLevel::LogLevel logLevel)const
  51. {
  52. QMetaEnum logLevelEnum = this->metaObject()->enumerator(0);
  53. Q_ASSERT(QString("LogLevel").compare(logLevelEnum.name()) == 0);
  54. return QLatin1String(logLevelEnum.valueToKey(logLevel));
  55. }
  56. // --------------------------------------------------------------------------
  57. // ctkErrorLogTerminalOutputPrivate
  58. // --------------------------------------------------------------------------
  59. class ctkErrorLogTerminalOutputPrivate
  60. {
  61. public:
  62. ctkErrorLogTerminalOutputPrivate();
  63. ~ctkErrorLogTerminalOutputPrivate();
  64. bool Enabled;
  65. mutable QMutex EnableMutex;
  66. int FD;
  67. mutable QMutex OutputMutex;
  68. };
  69. // --------------------------------------------------------------------------
  70. ctkErrorLogTerminalOutputPrivate::ctkErrorLogTerminalOutputPrivate()
  71. : Enabled(false)
  72. {
  73. #ifdef Q_OS_WIN32
  74. this->FD = _fileno(stdout);
  75. #else
  76. this->FD = fileno(stdout);
  77. #endif
  78. }
  79. // --------------------------------------------------------------------------
  80. ctkErrorLogTerminalOutputPrivate::~ctkErrorLogTerminalOutputPrivate()
  81. {
  82. }
  83. // --------------------------------------------------------------------------
  84. // ctkErrorLogTerminalOutput methods
  85. // --------------------------------------------------------------------------
  86. ctkErrorLogTerminalOutput::ctkErrorLogTerminalOutput()
  87. : d_ptr(new ctkErrorLogTerminalOutputPrivate)
  88. {
  89. }
  90. // --------------------------------------------------------------------------
  91. ctkErrorLogTerminalOutput::~ctkErrorLogTerminalOutput()
  92. {
  93. }
  94. // --------------------------------------------------------------------------
  95. bool ctkErrorLogTerminalOutput::enabled()const
  96. {
  97. Q_D(const ctkErrorLogTerminalOutput);
  98. QMutexLocker locker(&d->EnableMutex);
  99. return d->Enabled;
  100. }
  101. // --------------------------------------------------------------------------
  102. void ctkErrorLogTerminalOutput::setEnabled(bool value)
  103. {
  104. Q_D(ctkErrorLogTerminalOutput);
  105. QMutexLocker locker(&d->EnableMutex);
  106. d->Enabled = value;
  107. }
  108. // --------------------------------------------------------------------------
  109. int ctkErrorLogTerminalOutput::fileDescriptor()const
  110. {
  111. Q_D(const ctkErrorLogTerminalOutput);
  112. QMutexLocker locker(&d->OutputMutex);
  113. return d->FD;
  114. }
  115. // --------------------------------------------------------------------------
  116. void ctkErrorLogTerminalOutput::setFileDescriptor(int fd)
  117. {
  118. Q_D(ctkErrorLogTerminalOutput);
  119. QMutexLocker locker(&d->OutputMutex);
  120. d->FD = fd;
  121. }
  122. // --------------------------------------------------------------------------
  123. void ctkErrorLogTerminalOutput::output(const QString& text)
  124. {
  125. Q_D(ctkErrorLogTerminalOutput);
  126. {
  127. QMutexLocker locker(&d->EnableMutex);
  128. if (!d->Enabled)
  129. {
  130. return;
  131. }
  132. }
  133. {
  134. QMutexLocker locker(&d->OutputMutex);
  135. QString textWithNewLine = text + "\n";
  136. #ifdef _MSC_VER
  137. int res = _write(d->FD, qPrintable(textWithNewLine), textWithNewLine.size());
  138. #else
  139. ssize_t res = write(d->FD, qPrintable(textWithNewLine), textWithNewLine.size());
  140. #endif
  141. if (res == -1)
  142. {
  143. return;
  144. }
  145. }
  146. }
  147. // --------------------------------------------------------------------------
  148. // ctkErrorLogModelPrivate
  149. // --------------------------------------------------------------------------
  150. class ctkErrorLogModelPrivate
  151. {
  152. Q_DECLARE_PUBLIC(ctkErrorLogModel);
  153. protected:
  154. ctkErrorLogModel* const q_ptr;
  155. public:
  156. ctkErrorLogModelPrivate(ctkErrorLogModel& object);
  157. ~ctkErrorLogModelPrivate();
  158. void init();
  159. /// Convenient method that could be used for debugging purposes.
  160. void appendToFile(const QString& fileName, const QString& text);
  161. void setMessageHandlerConnection(ctkErrorLogAbstractMessageHandler * msgHandler, bool asynchronous);
  162. QStandardItemModel StandardItemModel;
  163. QHash<QString, ctkErrorLogAbstractMessageHandler*> RegisteredHandlers;
  164. ctkErrorLogLevel::LogLevels CurrentLogLevelFilter;
  165. bool LogEntryGrouping;
  166. bool AsynchronousLogging;
  167. bool AddingEntry;
  168. ctkErrorLogLevel ErrorLogLevel;
  169. ctkErrorLogTerminalOutput StdErrTerminalOutput;
  170. ctkErrorLogTerminalOutput StdOutTerminalOutput;
  171. QMutex AppendToFileMutex;
  172. };
  173. // --------------------------------------------------------------------------
  174. // ctkErrorLogModelPrivate methods
  175. // --------------------------------------------------------------------------
  176. ctkErrorLogModelPrivate::ctkErrorLogModelPrivate(ctkErrorLogModel& object)
  177. : q_ptr(&object)
  178. {
  179. this->LogEntryGrouping = false;
  180. this->AsynchronousLogging = true;
  181. this->AddingEntry = false;
  182. }
  183. // --------------------------------------------------------------------------
  184. ctkErrorLogModelPrivate::~ctkErrorLogModelPrivate()
  185. {
  186. foreach(const QString& handlerName, this->RegisteredHandlers.keys())
  187. {
  188. ctkErrorLogAbstractMessageHandler * msgHandler =
  189. this->RegisteredHandlers.value(handlerName);
  190. Q_ASSERT(msgHandler);
  191. msgHandler->setEnabled(false);
  192. delete msgHandler;
  193. }
  194. }
  195. // --------------------------------------------------------------------------
  196. void ctkErrorLogModelPrivate::init()
  197. {
  198. Q_Q(ctkErrorLogModel);
  199. q->setDynamicSortFilter(true);
  200. //
  201. // WARNING - Using a QSortFilterProxyModel slows down the insertion of rows by a factor 10
  202. //
  203. q->setSourceModel(&this->StandardItemModel);
  204. q->setFilterKeyColumn(ctkErrorLogModel::LogLevelColumn);
  205. }
  206. // --------------------------------------------------------------------------
  207. void ctkErrorLogModelPrivate::appendToFile(const QString& fileName, const QString& text)
  208. {
  209. QMutexLocker locker(&this->AppendToFileMutex);
  210. QFile f(fileName);
  211. f.open(QFile::Append);
  212. QTextStream s(&f);
  213. s << QDateTime::currentDateTime().toString() << " - " << text << "\n";
  214. f.close();
  215. }
  216. // --------------------------------------------------------------------------
  217. void ctkErrorLogModelPrivate::setMessageHandlerConnection(
  218. ctkErrorLogAbstractMessageHandler * msgHandler, bool asynchronous)
  219. {
  220. Q_Q(ctkErrorLogModel);
  221. msgHandler->disconnect();
  222. QObject::connect(msgHandler,
  223. SIGNAL(messageHandled(QDateTime,QString,ctkErrorLogLevel::LogLevel,QString,QString)),
  224. q, SLOT(addEntry(QDateTime,QString,ctkErrorLogLevel::LogLevel,QString,QString)),
  225. asynchronous ? Qt::QueuedConnection : Qt::BlockingQueuedConnection);
  226. }
  227. // --------------------------------------------------------------------------
  228. // ctkErrorLogModel methods
  229. //------------------------------------------------------------------------------
  230. ctkErrorLogModel::ctkErrorLogModel(QObject * parentObject)
  231. : Superclass(parentObject)
  232. , d_ptr(new ctkErrorLogModelPrivate(*this))
  233. {
  234. Q_D(ctkErrorLogModel);
  235. d->init();
  236. }
  237. //------------------------------------------------------------------------------
  238. ctkErrorLogModel::~ctkErrorLogModel()
  239. {
  240. }
  241. //------------------------------------------------------------------------------
  242. bool ctkErrorLogModel::registerMsgHandler(ctkErrorLogAbstractMessageHandler * msgHandler)
  243. {
  244. Q_D(ctkErrorLogModel);
  245. if (!msgHandler)
  246. {
  247. return false;
  248. }
  249. if (d->RegisteredHandlers.keys().contains(msgHandler->handlerName()))
  250. {
  251. return false;
  252. }
  253. d->setMessageHandlerConnection(msgHandler, d->AsynchronousLogging);
  254. msgHandler->setTerminalOutput(Self::StandardError, &d->StdErrTerminalOutput);
  255. msgHandler->setTerminalOutput(Self::StandardOutput, &d->StdOutTerminalOutput);
  256. d->RegisteredHandlers.insert(msgHandler->handlerName(), msgHandler);
  257. return true;
  258. }
  259. //------------------------------------------------------------------------------
  260. QStringList ctkErrorLogModel::msgHandlerNames()const
  261. {
  262. Q_D(const ctkErrorLogModel);
  263. return d->RegisteredHandlers.keys();
  264. }
  265. //------------------------------------------------------------------------------
  266. bool ctkErrorLogModel::msgHandlerEnabled(const QString& handlerName) const
  267. {
  268. Q_D(const ctkErrorLogModel);
  269. if (!d->RegisteredHandlers.keys().contains(handlerName))
  270. {
  271. return false;
  272. }
  273. return d->RegisteredHandlers.value(handlerName)->enabled();
  274. }
  275. //------------------------------------------------------------------------------
  276. void ctkErrorLogModel::setMsgHandlerEnabled(const QString& handlerName, bool enabled)
  277. {
  278. Q_D(ctkErrorLogModel);
  279. if (!d->RegisteredHandlers.keys().contains(handlerName))
  280. {
  281. // qCritical() << "Failed to enable/disable message handler " << handlerName
  282. // << "- Handler not registered !";
  283. return;
  284. }
  285. d->RegisteredHandlers.value(handlerName)->setEnabled(enabled);
  286. }
  287. //------------------------------------------------------------------------------
  288. QStringList ctkErrorLogModel::msgHandlerEnabled() const
  289. {
  290. Q_D(const ctkErrorLogModel);
  291. QStringList msgHandlers;
  292. foreach(const QString& handlerName, d->RegisteredHandlers.keys())
  293. {
  294. if (d->RegisteredHandlers.value(handlerName)->enabled())
  295. {
  296. msgHandlers << handlerName;
  297. }
  298. }
  299. return msgHandlers;
  300. }
  301. //------------------------------------------------------------------------------
  302. void ctkErrorLogModel::setMsgHandlerEnabled(const QStringList& handlerNames)
  303. {
  304. foreach(const QString& handlerName, handlerNames)
  305. {
  306. this->setMsgHandlerEnabled(handlerName, true);
  307. }
  308. }
  309. //------------------------------------------------------------------------------
  310. void ctkErrorLogModel::enableAllMsgHandler()
  311. {
  312. this->setAllMsgHandlerEnabled(true);
  313. }
  314. //------------------------------------------------------------------------------
  315. void ctkErrorLogModel::disableAllMsgHandler()
  316. {
  317. this->setAllMsgHandlerEnabled(false);
  318. }
  319. //------------------------------------------------------------------------------
  320. void ctkErrorLogModel::setAllMsgHandlerEnabled(bool enabled)
  321. {
  322. Q_D(ctkErrorLogModel);
  323. foreach(const QString& msgHandlerName, d->RegisteredHandlers.keys())
  324. {
  325. this->setMsgHandlerEnabled(msgHandlerName, enabled);
  326. }
  327. }
  328. //------------------------------------------------------------------------------
  329. ctkErrorLogModel::TerminalOutputs ctkErrorLogModel::terminalOutputs()const
  330. {
  331. Q_D(const ctkErrorLogModel);
  332. ctkErrorLogModel::TerminalOutputs currentTerminalOutputs;
  333. currentTerminalOutputs |= d->StdErrTerminalOutput.enabled() ? Self::StandardError : Self::None;
  334. currentTerminalOutputs |= d->StdOutTerminalOutput.enabled() ? Self::StandardOutput : Self::None;
  335. return currentTerminalOutputs;
  336. }
  337. //------------------------------------------------------------------------------
  338. void ctkErrorLogModel::setTerminalOutputs(
  339. const ctkErrorLogModel::TerminalOutputs& terminalOutput)
  340. {
  341. Q_D(ctkErrorLogModel);
  342. d->StdErrTerminalOutput.setEnabled(terminalOutput & ctkErrorLogModel::StandardOutput);
  343. d->StdOutTerminalOutput.setEnabled(terminalOutput & ctkErrorLogModel::StandardError);
  344. }
  345. //------------------------------------------------------------------------------
  346. void ctkErrorLogModel::addEntry(const QDateTime& currentDateTime, const QString& threadId,
  347. ctkErrorLogLevel::LogLevel logLevel,
  348. const QString& origin, const QString& text)
  349. {
  350. Q_D(ctkErrorLogModel);
  351. // d->appendToFile("/tmp/ctkErrorLogModel-appendToFile.txt",
  352. // QString("addEntry: %1").arg(QThread::currentThreadId()));
  353. if (d->AddingEntry)
  354. {
  355. // QString str;
  356. // QTextStream s(&str);
  357. // s << "----------------------------------\n";
  358. // s << "text=>" << text << "\n";
  359. // s << "\tlogLevel:" << qPrintable(d->ErrorLogLevel(logLevel)) << "\n";
  360. // s << "\torigin:" << qPrintable(origin) << "\n";
  361. // d->appendToFile("/tmp/ctkErrorLogModel-AddingEntry-true.txt", str);
  362. return;
  363. }
  364. d->AddingEntry = true;
  365. QString timeFormat("dd.MM.yyyy hh:mm:ss");
  366. bool groupEntry = false;
  367. if (d->LogEntryGrouping)
  368. {
  369. // Retrieve threadId associated with last row
  370. QModelIndex lastRowThreadIdIndex =
  371. d->StandardItemModel.index(d->StandardItemModel.rowCount() - 1, ctkErrorLogModel::ThreadIdColumn);
  372. bool threadIdMatched = threadId == lastRowThreadIdIndex.data().toString();
  373. // Retrieve logLevel associated with last row
  374. QModelIndex lastRowLogLevelIndex =
  375. d->StandardItemModel.index(d->StandardItemModel.rowCount() - 1, ctkErrorLogModel::LogLevelColumn);
  376. bool logLevelMatched = d->ErrorLogLevel(logLevel) == lastRowLogLevelIndex.data().toString();
  377. // Retrieve origin associated with last row
  378. QModelIndex lastRowOriginIndex =
  379. d->StandardItemModel.index(d->StandardItemModel.rowCount() - 1, ctkErrorLogModel::OriginColumn);
  380. bool originMatched = origin == lastRowOriginIndex.data().toString();
  381. // Retrieve time associated with last row
  382. QModelIndex lastRowTimeIndex =
  383. d->StandardItemModel.index(d->StandardItemModel.rowCount() - 1, ctkErrorLogModel::TimeColumn);
  384. QDateTime lastRowDateTime = QDateTime::fromString(lastRowTimeIndex.data().toString(), timeFormat);
  385. int groupingIntervalInMsecs = 1000;
  386. bool withinGroupingInterval = lastRowDateTime.time().msecsTo(currentDateTime.time()) <= groupingIntervalInMsecs;
  387. groupEntry = threadIdMatched && logLevelMatched && originMatched && withinGroupingInterval;
  388. }
  389. if (!groupEntry)
  390. {
  391. QList<QStandardItem*> itemList;
  392. // Time item
  393. QStandardItem * timeItem = new QStandardItem(currentDateTime.toString(timeFormat));
  394. timeItem->setEditable(false);
  395. itemList << timeItem;
  396. // ThreadId item
  397. QStandardItem * threadIdItem = new QStandardItem(threadId);
  398. threadIdItem->setEditable(false);
  399. itemList << threadIdItem;
  400. // LogLevel item
  401. QStandardItem * logLevelItem = new QStandardItem(d->ErrorLogLevel(logLevel));
  402. logLevelItem->setEditable(false);
  403. itemList << logLevelItem;
  404. // Origin item
  405. QStandardItem * originItem = new QStandardItem(origin);
  406. originItem->setEditable(false);
  407. itemList << originItem;
  408. // Description item
  409. QStandardItem * descriptionItem = new QStandardItem();
  410. QString descriptionText(text);
  411. descriptionItem->setData(descriptionText.left(160).append((descriptionText.size() > 160) ? "..." : ""), Qt::DisplayRole);
  412. descriptionItem->setData(descriptionText, ctkErrorLogModel::DescriptionTextRole);
  413. descriptionItem->setEditable(false);
  414. itemList << descriptionItem;
  415. d->StandardItemModel.invisibleRootItem()->appendRow(itemList);
  416. }
  417. else
  418. {
  419. // Retrieve description associated with last row
  420. QModelIndex lastRowDescriptionIndex =
  421. d->StandardItemModel.index(d->StandardItemModel.rowCount() - 1, ctkErrorLogModel::DescriptionColumn);
  422. QStringList updatedDescription;
  423. updatedDescription << lastRowDescriptionIndex.data(ctkErrorLogModel::DescriptionTextRole).toString();
  424. updatedDescription << text;
  425. d->StandardItemModel.setData(lastRowDescriptionIndex, updatedDescription.join("\n"),
  426. ctkErrorLogModel::DescriptionTextRole);
  427. // Append '...' to displayText if needed
  428. QString displayText = lastRowDescriptionIndex.data().toString();
  429. if (!displayText.endsWith("..."))
  430. {
  431. d->StandardItemModel.setData(lastRowDescriptionIndex, displayText.append("..."), Qt::DisplayRole);
  432. }
  433. }
  434. d->AddingEntry = false;
  435. }
  436. //------------------------------------------------------------------------------
  437. void ctkErrorLogModel::clear()
  438. {
  439. Q_D(ctkErrorLogModel);
  440. d->StandardItemModel.invisibleRootItem()->removeRows(0, d->StandardItemModel.rowCount());
  441. }
  442. //------------------------------------------------------------------------------
  443. void ctkErrorLogModel::filterEntry(const ctkErrorLogLevel::LogLevels& logLevel,
  444. bool disableFilter)
  445. {
  446. Q_D(ctkErrorLogModel);
  447. QStringList patterns;
  448. if (!this->filterRegExp().pattern().isEmpty())
  449. {
  450. patterns << this->filterRegExp().pattern().split("|");
  451. }
  452. patterns.removeAll(d->ErrorLogLevel(ctkErrorLogLevel::None));
  453. // foreach(QString s, patterns)
  454. // {
  455. // std::cout << "pattern:" << qPrintable(s) << std::endl;
  456. // }
  457. QMetaEnum logLevelEnum = d->ErrorLogLevel.metaObject()->enumerator(0);
  458. Q_ASSERT(QString("LogLevel").compare(logLevelEnum.name()) == 0);
  459. // Loop over enum values and append associated name to 'patterns' if
  460. // it has been specified within 'logLevel'
  461. for (int i = 1; i < logLevelEnum.keyCount(); ++i)
  462. {
  463. int aLogLevel = logLevelEnum.value(i);
  464. if (logLevel & aLogLevel)
  465. {
  466. QString logLevelAsString = d->ErrorLogLevel(static_cast<ctkErrorLogLevel::LogLevel>(aLogLevel));
  467. if (!disableFilter)
  468. {
  469. patterns << logLevelAsString;
  470. d->CurrentLogLevelFilter |= static_cast<ctkErrorLogLevel::LogLevels>(aLogLevel);
  471. }
  472. else
  473. {
  474. patterns.removeAll(logLevelAsString);
  475. d->CurrentLogLevelFilter ^= static_cast<ctkErrorLogLevel::LogLevels>(aLogLevel);
  476. }
  477. }
  478. }
  479. if (patterns.isEmpty())
  480. {
  481. // If there are no patterns, let's filter with the None level so that
  482. // all entries are filtered out.
  483. patterns << d->ErrorLogLevel(ctkErrorLogLevel::None);
  484. }
  485. bool filterChanged = true;
  486. QStringList currentPatterns = this->filterRegExp().pattern().split("|");
  487. if (currentPatterns.count() == patterns.count())
  488. {
  489. foreach(const QString& p, patterns)
  490. {
  491. currentPatterns.removeAll(p);
  492. }
  493. filterChanged = currentPatterns.count() > 0;
  494. }
  495. this->setFilterRegExp(patterns.join("|"));
  496. if (filterChanged)
  497. {
  498. emit this->logLevelFilterChanged();
  499. }
  500. }
  501. //------------------------------------------------------------------------------
  502. ctkErrorLogLevel::LogLevels ctkErrorLogModel::logLevelFilter()const
  503. {
  504. Q_D(const ctkErrorLogModel);
  505. QMetaEnum logLevelEnum = d->ErrorLogLevel.metaObject()->enumerator(0);
  506. Q_ASSERT(QString("LogLevel").compare(logLevelEnum.name()) == 0);
  507. ctkErrorLogLevel::LogLevels filter = ctkErrorLogLevel::Unknown;
  508. foreach(const QString& filterAsString, this->filterRegExp().pattern().split("|"))
  509. {
  510. filter |= static_cast<ctkErrorLogLevel::LogLevels>(logLevelEnum.keyToValue(filterAsString.toLatin1()));
  511. }
  512. return filter;
  513. }
  514. //------------------------------------------------------------------------------
  515. bool ctkErrorLogModel::logEntryGrouping()const
  516. {
  517. Q_D(const ctkErrorLogModel);
  518. return d->LogEntryGrouping;
  519. }
  520. //------------------------------------------------------------------------------
  521. void ctkErrorLogModel::setLogEntryGrouping(bool value)
  522. {
  523. Q_D(ctkErrorLogModel);
  524. d->LogEntryGrouping = value;
  525. }
  526. //------------------------------------------------------------------------------
  527. bool ctkErrorLogModel::asynchronousLogging()const
  528. {
  529. Q_D(const ctkErrorLogModel);
  530. return d->AsynchronousLogging;
  531. }
  532. //------------------------------------------------------------------------------
  533. void ctkErrorLogModel::setAsynchronousLogging(bool value)
  534. {
  535. Q_D(ctkErrorLogModel);
  536. if (d->AsynchronousLogging == value)
  537. {
  538. return;
  539. }
  540. foreach(const QString& handlerName, d->RegisteredHandlers.keys())
  541. {
  542. d->setMessageHandlerConnection(
  543. d->RegisteredHandlers.value(handlerName), value);
  544. }
  545. d->AsynchronousLogging = value;
  546. }
  547. // --------------------------------------------------------------------------
  548. // ctkErrorLogAbstractMessageHandlerPrivate
  549. // --------------------------------------------------------------------------
  550. class ctkErrorLogAbstractMessageHandlerPrivate
  551. {
  552. public:
  553. ctkErrorLogAbstractMessageHandlerPrivate();
  554. ~ctkErrorLogAbstractMessageHandlerPrivate();
  555. bool Enabled;
  556. QString HandlerPrettyName;
  557. // Use "int" instead of "ctkErrorLogModel::TerminalOutput" to avoid compilation warning ...
  558. // qhash.h:879: warning: passing ‘ctkErrorLogModel::TerminalOutput’ chooses ‘int’ over ‘uint’ [-Wsign-promo]
  559. QHash<int, ctkErrorLogTerminalOutput*> TerminalOutputs;
  560. };
  561. // --------------------------------------------------------------------------
  562. ctkErrorLogAbstractMessageHandlerPrivate::
  563. ctkErrorLogAbstractMessageHandlerPrivate()
  564. : Enabled(false)
  565. {
  566. }
  567. // --------------------------------------------------------------------------
  568. ctkErrorLogAbstractMessageHandlerPrivate::~ctkErrorLogAbstractMessageHandlerPrivate()
  569. {
  570. }
  571. // --------------------------------------------------------------------------
  572. // ctkErrorLogAbstractMessageHandlerPrivate methods
  573. // --------------------------------------------------------------------------
  574. ctkErrorLogAbstractMessageHandler::ctkErrorLogAbstractMessageHandler()
  575. : Superclass(), d_ptr(new ctkErrorLogAbstractMessageHandlerPrivate)
  576. {
  577. }
  578. // --------------------------------------------------------------------------
  579. ctkErrorLogAbstractMessageHandler::~ctkErrorLogAbstractMessageHandler()
  580. {
  581. }
  582. // --------------------------------------------------------------------------
  583. QString ctkErrorLogAbstractMessageHandler::handlerPrettyName()const
  584. {
  585. Q_D(const ctkErrorLogAbstractMessageHandler);
  586. if (d->HandlerPrettyName.isEmpty())
  587. {
  588. return this->handlerName();
  589. }
  590. else
  591. {
  592. return d->HandlerPrettyName;
  593. }
  594. }
  595. // --------------------------------------------------------------------------
  596. void ctkErrorLogAbstractMessageHandler::setHandlerPrettyName(const QString& newHandlerPrettyName)
  597. {
  598. Q_D(ctkErrorLogAbstractMessageHandler);
  599. d->HandlerPrettyName = newHandlerPrettyName;
  600. }
  601. // --------------------------------------------------------------------------
  602. bool ctkErrorLogAbstractMessageHandler::enabled()const
  603. {
  604. Q_D(const ctkErrorLogAbstractMessageHandler);
  605. return d->Enabled;
  606. }
  607. // --------------------------------------------------------------------------
  608. void ctkErrorLogAbstractMessageHandler::setEnabled(bool value)
  609. {
  610. Q_D(ctkErrorLogAbstractMessageHandler);
  611. if (value == d->Enabled)
  612. {
  613. return;
  614. }
  615. this->setEnabledInternal(value);
  616. d->Enabled = value;
  617. }
  618. // --------------------------------------------------------------------------
  619. void ctkErrorLogAbstractMessageHandler::handleMessage(const QString& threadId,
  620. ctkErrorLogLevel::LogLevel logLevel,
  621. const QString& origin, const QString& text)
  622. {
  623. Q_D(ctkErrorLogAbstractMessageHandler);
  624. if (logLevel <= ctkErrorLogLevel::Info)
  625. {
  626. if(d->TerminalOutputs.contains(ctkErrorLogModel::StandardOutput))
  627. {
  628. d->TerminalOutputs.value(ctkErrorLogModel::StandardOutput)->output(text);
  629. }
  630. }
  631. else
  632. {
  633. if(d->TerminalOutputs.contains(ctkErrorLogModel::StandardError))
  634. {
  635. d->TerminalOutputs.value(ctkErrorLogModel::StandardError)->output(text);
  636. }
  637. }
  638. emit this->messageHandled(QDateTime::currentDateTime(), threadId, logLevel, origin, text);
  639. }
  640. // --------------------------------------------------------------------------
  641. ctkErrorLogTerminalOutput* ctkErrorLogAbstractMessageHandler::terminalOutput(
  642. ctkErrorLogModel::TerminalOutput terminalOutputType)const
  643. {
  644. Q_D(const ctkErrorLogAbstractMessageHandler);
  645. if(d->TerminalOutputs.contains(terminalOutputType))
  646. {
  647. return d->TerminalOutputs.value(terminalOutputType);
  648. }
  649. return 0;
  650. }
  651. // --------------------------------------------------------------------------
  652. void ctkErrorLogAbstractMessageHandler::setTerminalOutput(
  653. ctkErrorLogModel::TerminalOutput terminalOutputType, ctkErrorLogTerminalOutput* terminalOutput)
  654. {
  655. Q_D(ctkErrorLogAbstractMessageHandler);
  656. d->TerminalOutputs.insert(terminalOutputType, terminalOutput);
  657. }