|
@@ -22,9 +22,11 @@
|
|
|
#include <QApplication>
|
|
|
#include <QDateTime>
|
|
|
#include <QDebug>
|
|
|
+#include <QFile>
|
|
|
#include <QMainWindow>
|
|
|
#include <QMetaEnum>
|
|
|
#include <QMetaType>
|
|
|
+#include <QMutexLocker>
|
|
|
#include <QPointer>
|
|
|
#include <QStandardItem>
|
|
|
#include <QStatusBar>
|
|
@@ -33,68 +35,129 @@
|
|
|
#include "ctkErrorLogModel.h"
|
|
|
#include <ctkPimpl.h>
|
|
|
|
|
|
+// STD includes
|
|
|
+#include <cstdio> // For _fileno or fileno
|
|
|
+
|
|
|
// --------------------------------------------------------------------------
|
|
|
-// ctkErrorLogAbstractMessageHandler methods
|
|
|
+// ctkErrorLogLevel methods
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-ctkErrorLogAbstractMessageHandler::ctkErrorLogAbstractMessageHandler()
|
|
|
+ctkErrorLogLevel::ctkErrorLogLevel()
|
|
|
+{
|
|
|
+ qRegisterMetaType<ctkErrorLogLevel::LogLevel>("ctkErrorLogLevel::LogLevel");
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+QString ctkErrorLogLevel::operator()(ctkErrorLogLevel::LogLevel logLevel)
|
|
|
+{
|
|
|
+ return this->logLevelAsString(logLevel);
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+QString ctkErrorLogLevel::logLevelAsString(ctkErrorLogLevel::LogLevel logLevel)const
|
|
|
+{
|
|
|
+ QMetaEnum logLevelEnum = this->metaObject()->enumerator(0);
|
|
|
+ Q_ASSERT(QString("LogLevel").compare(logLevelEnum.name()) == 0);
|
|
|
+ return QLatin1String(logLevelEnum.valueToKey(logLevel));
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+// ctkErrorLogTerminalOutputPrivate
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+class ctkErrorLogTerminalOutputPrivate
|
|
|
+{
|
|
|
+public:
|
|
|
+ ctkErrorLogTerminalOutputPrivate();
|
|
|
+ ~ctkErrorLogTerminalOutputPrivate();
|
|
|
+
|
|
|
+ bool Enabled;
|
|
|
+ mutable QMutex EnableMutex;
|
|
|
+
|
|
|
+ int FD;
|
|
|
+ mutable QMutex OutputMutex;
|
|
|
+};
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+ctkErrorLogTerminalOutputPrivate::ctkErrorLogTerminalOutputPrivate()
|
|
|
: Enabled(false)
|
|
|
{
|
|
|
+#ifdef Q_OS_WIN32
|
|
|
+ this->FD = _fileno(stdout);
|
|
|
+#else
|
|
|
+ this->FD = fileno(stdout);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-ctkErrorLogAbstractMessageHandler::~ctkErrorLogAbstractMessageHandler()
|
|
|
+ctkErrorLogTerminalOutputPrivate::~ctkErrorLogTerminalOutputPrivate()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-ctkErrorLogModel* ctkErrorLogAbstractMessageHandler::errorLogModel()const
|
|
|
+// ctkErrorLogTerminalOutput methods
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+ctkErrorLogTerminalOutput::ctkErrorLogTerminalOutput()
|
|
|
+ : d_ptr(new ctkErrorLogTerminalOutputPrivate)
|
|
|
{
|
|
|
- return this->ErrorLogModel.data();
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-void ctkErrorLogAbstractMessageHandler::setErrorLogModel(ctkErrorLogModel * newErrorLogModel)
|
|
|
+ctkErrorLogTerminalOutput::~ctkErrorLogTerminalOutput()
|
|
|
{
|
|
|
- this->ErrorLogModel = QPointer<ctkErrorLogModel>(newErrorLogModel);
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-QString ctkErrorLogAbstractMessageHandler::handlerPrettyName()const
|
|
|
+bool ctkErrorLogTerminalOutput::enabled()const
|
|
|
{
|
|
|
- if (this->HandlerPrettyName.isEmpty())
|
|
|
- {
|
|
|
- return this->handlerName();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return this->HandlerPrettyName;
|
|
|
- }
|
|
|
+ Q_D(const ctkErrorLogTerminalOutput);
|
|
|
+ QMutexLocker locker(&d->EnableMutex);
|
|
|
+ return d->Enabled;
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-void ctkErrorLogAbstractMessageHandler::setHandlerPrettyName(const QString& newHandlerPrettyName)
|
|
|
+void ctkErrorLogTerminalOutput::setEnabled(bool value)
|
|
|
{
|
|
|
- this->HandlerPrettyName = newHandlerPrettyName;
|
|
|
+ Q_D(ctkErrorLogTerminalOutput);
|
|
|
+ QMutexLocker locker(&d->EnableMutex);
|
|
|
+ d->Enabled = value;
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-bool ctkErrorLogAbstractMessageHandler::enabled()const
|
|
|
+int ctkErrorLogTerminalOutput::fileDescriptor()const
|
|
|
{
|
|
|
- return this->Enabled;
|
|
|
+ Q_D(const ctkErrorLogTerminalOutput);
|
|
|
+ QMutexLocker locker(&d->OutputMutex);
|
|
|
+ return d->FD;
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-void ctkErrorLogAbstractMessageHandler::setEnabled(bool value)
|
|
|
+void ctkErrorLogTerminalOutput::setFileDescriptor(int fd)
|
|
|
{
|
|
|
- if (value == this->Enabled)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
- this->setEnabledInternal(value);
|
|
|
- this->Enabled = value;
|
|
|
+ Q_D(ctkErrorLogTerminalOutput);
|
|
|
+ QMutexLocker locker(&d->OutputMutex);
|
|
|
+ d->FD = fd;
|
|
|
}
|
|
|
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkErrorLogTerminalOutput::output(const QString& text)
|
|
|
+{
|
|
|
+ Q_D(ctkErrorLogTerminalOutput);
|
|
|
+ {
|
|
|
+ QMutexLocker locker(&d->EnableMutex);
|
|
|
+ if (!d->Enabled)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ QMutexLocker locker(&d->OutputMutex);
|
|
|
+ QString textWithNewLine = text + "\n";
|
|
|
+ write(d->FD, qPrintable(textWithNewLine), textWithNewLine.size());
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
// ctkErrorLogModelPrivate
|
|
@@ -111,18 +174,27 @@ public:
|
|
|
|
|
|
void init();
|
|
|
|
|
|
+ /// Convenient method that could be used for debugging purposes.
|
|
|
+ void appendToFile(const QString& fileName, const QString& text);
|
|
|
+
|
|
|
+ void setMessageHandlerConnection(ctkErrorLogAbstractMessageHandler * msgHandler, bool asynchronous);
|
|
|
+
|
|
|
QStandardItemModel StandardItemModel;
|
|
|
|
|
|
QHash<QString, ctkErrorLogAbstractMessageHandler*> RegisteredHandlers;
|
|
|
|
|
|
- ctkErrorLogModel::LogLevels CurrentLogLevelFilter;
|
|
|
+ ctkErrorLogLevel::LogLevels CurrentLogLevelFilter;
|
|
|
|
|
|
bool LogEntryGrouping;
|
|
|
-
|
|
|
+ bool AsynchronousLogging;
|
|
|
bool AddingEntry;
|
|
|
|
|
|
- int TerminalOutputEnabled;
|
|
|
+ ctkErrorLogLevel ErrorLogLevel;
|
|
|
+
|
|
|
+ ctkErrorLogTerminalOutput StdErrTerminalOutput;
|
|
|
+ ctkErrorLogTerminalOutput StdOutTerminalOutput;
|
|
|
|
|
|
+ QMutex AppendToFileMutex;
|
|
|
};
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
@@ -132,14 +204,14 @@ public:
|
|
|
ctkErrorLogModelPrivate::ctkErrorLogModelPrivate(ctkErrorLogModel& object)
|
|
|
: q_ptr(&object)
|
|
|
{
|
|
|
+ this->LogEntryGrouping = false;
|
|
|
+ this->AsynchronousLogging = true;
|
|
|
this->AddingEntry = false;
|
|
|
- this->TerminalOutputEnabled = false;
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
ctkErrorLogModelPrivate::~ctkErrorLogModelPrivate()
|
|
|
{
|
|
|
- this->LogEntryGrouping = false;
|
|
|
foreach(const QString& handlerName, this->RegisteredHandlers.keys())
|
|
|
{
|
|
|
ctkErrorLogAbstractMessageHandler * msgHandler =
|
|
@@ -163,6 +235,31 @@ void ctkErrorLogModelPrivate::init()
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
+void ctkErrorLogModelPrivate::appendToFile(const QString& fileName, const QString& text)
|
|
|
+{
|
|
|
+ QMutexLocker locker(&this->AppendToFileMutex);
|
|
|
+ QFile f(fileName);
|
|
|
+ f.open(QFile::Append);
|
|
|
+ QTextStream s(&f);
|
|
|
+ s << QDateTime::currentDateTime().toString() << " - " << text << "\n";
|
|
|
+ f.close();
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkErrorLogModelPrivate::setMessageHandlerConnection(
|
|
|
+ ctkErrorLogAbstractMessageHandler * msgHandler, bool asynchronous)
|
|
|
+{
|
|
|
+ Q_Q(ctkErrorLogModel);
|
|
|
+
|
|
|
+ msgHandler->disconnect();
|
|
|
+
|
|
|
+ QObject::connect(msgHandler,
|
|
|
+ SIGNAL(messageHandled(QDateTime,QString,ctkErrorLogLevel::LogLevel,QString,QString)),
|
|
|
+ q, SLOT(addEntry(QDateTime,QString,ctkErrorLogLevel::LogLevel,QString,QString)),
|
|
|
+ asynchronous ? Qt::QueuedConnection : Qt::BlockingQueuedConnection);
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
// ctkErrorLogModel methods
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
@@ -192,7 +289,12 @@ bool ctkErrorLogModel::registerMsgHandler(ctkErrorLogAbstractMessageHandler * ms
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
- msgHandler->setErrorLogModel(this);
|
|
|
+
|
|
|
+ d->setMessageHandlerConnection(msgHandler, d->AsynchronousLogging);
|
|
|
+
|
|
|
+ msgHandler->setTerminalOutput(Self::StandardError, &d->StdErrTerminalOutput);
|
|
|
+ msgHandler->setTerminalOutput(Self::StandardOutput, &d->StdOutTerminalOutput);
|
|
|
+
|
|
|
d->RegisteredHandlers.insert(msgHandler->handlerName(), msgHandler);
|
|
|
return true;
|
|
|
}
|
|
@@ -275,59 +377,64 @@ void ctkErrorLogModel::setAllMsgHandlerEnabled(bool enabled)
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
-bool ctkErrorLogModel::terminalOutputEnabled()const
|
|
|
+ctkErrorLogModel::TerminalOutputs ctkErrorLogModel::terminalOutputs()const
|
|
|
{
|
|
|
Q_D(const ctkErrorLogModel);
|
|
|
- return d->TerminalOutputEnabled;
|
|
|
+ ctkErrorLogModel::TerminalOutputs currentTerminalOutputs;
|
|
|
+ currentTerminalOutputs |= d->StdErrTerminalOutput.enabled() ? Self::StandardError : Self::None;
|
|
|
+ currentTerminalOutputs |= d->StdOutTerminalOutput.enabled() ? Self::StandardOutput : Self::None;
|
|
|
+ return currentTerminalOutputs;
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
-void ctkErrorLogModel::setTerminalOutputEnabled(bool enabled)
|
|
|
+void ctkErrorLogModel::setTerminalOutputs(
|
|
|
+ const ctkErrorLogModel::TerminalOutputs& terminalOutput)
|
|
|
{
|
|
|
Q_D(ctkErrorLogModel);
|
|
|
- d->TerminalOutputEnabled = enabled;
|
|
|
-}
|
|
|
-
|
|
|
-//------------------------------------------------------------------------------
|
|
|
-QString ctkErrorLogModel::logLevelAsString(LogLevel logLevel)const
|
|
|
-{
|
|
|
- QMetaEnum logLevelEnum = this->metaObject()->enumerator(0);
|
|
|
- Q_ASSERT(QString("LogLevel").compare(logLevelEnum.name()) == 0);
|
|
|
- return QLatin1String(logLevelEnum.valueToKey(logLevel));
|
|
|
+ d->StdErrTerminalOutput.setEnabled(terminalOutput & ctkErrorLogModel::StandardOutput);
|
|
|
+ d->StdOutTerminalOutput.setEnabled(terminalOutput & ctkErrorLogModel::StandardError);
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
-void ctkErrorLogModel::addEntry(ctkErrorLogModel::LogLevel logLevel,
|
|
|
- const QString& origin, const char* text)
|
|
|
+void ctkErrorLogModel::addEntry(const QDateTime& currentDateTime, const QString& threadId,
|
|
|
+ ctkErrorLogLevel::LogLevel logLevel,
|
|
|
+ const QString& origin, const QString& text)
|
|
|
{
|
|
|
Q_D(ctkErrorLogModel);
|
|
|
|
|
|
+// d->appendToFile("/tmp/ctkErrorLogModel-appendToFile.txt",
|
|
|
+// QString("addEntry: %1").arg(QThread::currentThreadId()));
|
|
|
+
|
|
|
if (d->AddingEntry)
|
|
|
{
|
|
|
-// QFile f("/tmp/ctkErrorLogModel-AddingEntry-true.txt");
|
|
|
-// f.open(QFile::Append);
|
|
|
-// QTextStream s(&f);
|
|
|
+// QString str;
|
|
|
+// QTextStream s(&str);
|
|
|
+// s << "----------------------------------\n";
|
|
|
// s << "text=>" << text << "\n";
|
|
|
-// s << "\tlogLevel:" << qPrintable(this->logLevelAsString(logLevel)) << "\n";
|
|
|
+// s << "\tlogLevel:" << qPrintable(d->ErrorLogLevel(logLevel)) << "\n";
|
|
|
// s << "\torigin:" << qPrintable(origin) << "\n";
|
|
|
-// s << "\ttext:" << text << "\n";
|
|
|
-// f.close();
|
|
|
+// d->appendToFile("/tmp/ctkErrorLogModel-AddingEntry-true.txt", str);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
d->AddingEntry = true;
|
|
|
|
|
|
QString timeFormat("dd.MM.yyyy hh:mm:ss");
|
|
|
- QDateTime currentDateTime = QDateTime::currentDateTime();
|
|
|
|
|
|
bool groupEntry = false;
|
|
|
if (d->LogEntryGrouping)
|
|
|
{
|
|
|
+ // Retrieve threadId associated with last row
|
|
|
+ QModelIndex lastRowThreadIdIndex =
|
|
|
+ d->StandardItemModel.index(d->StandardItemModel.rowCount() - 1, ctkErrorLogModel::ThreadIdColumn);
|
|
|
+
|
|
|
+ bool threadIdMatched = threadId == lastRowThreadIdIndex.data().toString();
|
|
|
+
|
|
|
// Retrieve logLevel associated with last row
|
|
|
QModelIndex lastRowLogLevelIndex =
|
|
|
d->StandardItemModel.index(d->StandardItemModel.rowCount() - 1, ctkErrorLogModel::LogLevelColumn);
|
|
|
|
|
|
- bool logLevelMatched = this->logLevelAsString(logLevel) == lastRowLogLevelIndex.data().toString();
|
|
|
+ bool logLevelMatched = d->ErrorLogLevel(logLevel) == lastRowLogLevelIndex.data().toString();
|
|
|
|
|
|
// Retrieve origin associated with last row
|
|
|
QModelIndex lastRowOriginIndex =
|
|
@@ -343,7 +450,7 @@ void ctkErrorLogModel::addEntry(ctkErrorLogModel::LogLevel logLevel,
|
|
|
int groupingIntervalInMsecs = 1000;
|
|
|
bool withinGroupingInterval = lastRowDateTime.time().msecsTo(currentDateTime.time()) <= groupingIntervalInMsecs;
|
|
|
|
|
|
- groupEntry = logLevelMatched && originMatched && withinGroupingInterval;
|
|
|
+ groupEntry = threadIdMatched && logLevelMatched && originMatched && withinGroupingInterval;
|
|
|
}
|
|
|
|
|
|
if (!groupEntry)
|
|
@@ -355,8 +462,13 @@ void ctkErrorLogModel::addEntry(ctkErrorLogModel::LogLevel logLevel,
|
|
|
timeItem->setEditable(false);
|
|
|
itemList << timeItem;
|
|
|
|
|
|
+ // ThreadId item
|
|
|
+ QStandardItem * threadIdItem = new QStandardItem(threadId);
|
|
|
+ threadIdItem->setEditable(false);
|
|
|
+ itemList << threadIdItem;
|
|
|
+
|
|
|
// LogLevel item
|
|
|
- QStandardItem * logLevelItem = new QStandardItem(this->logLevelAsString(logLevel));
|
|
|
+ QStandardItem * logLevelItem = new QStandardItem(d->ErrorLogLevel(logLevel));
|
|
|
logLevelItem->setEditable(false);
|
|
|
itemList << logLevelItem;
|
|
|
|
|
@@ -383,7 +495,7 @@ void ctkErrorLogModel::addEntry(ctkErrorLogModel::LogLevel logLevel,
|
|
|
|
|
|
QStringList updatedDescription;
|
|
|
updatedDescription << lastRowDescriptionIndex.data(ctkErrorLogModel::DescriptionTextRole).toString();
|
|
|
- updatedDescription << QLatin1String(text);
|
|
|
+ updatedDescription << text;
|
|
|
|
|
|
d->StandardItemModel.setData(lastRowDescriptionIndex, updatedDescription.join("\n"),
|
|
|
ctkErrorLogModel::DescriptionTextRole);
|
|
@@ -396,22 +508,6 @@ void ctkErrorLogModel::addEntry(ctkErrorLogModel::LogLevel logLevel,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (d->TerminalOutputEnabled)
|
|
|
- {
|
|
|
- QStringList savedMsgHandlerEnabled = this->msgHandlerEnabled();
|
|
|
-
|
|
|
- this->disableAllMsgHandler();
|
|
|
- if (logLevel <= ctkErrorLogModel::Info)
|
|
|
- {
|
|
|
- std::cout << text << std::endl;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- std::cerr << text << std::endl;
|
|
|
- }
|
|
|
- this->setMsgHandlerEnabled(savedMsgHandlerEnabled);
|
|
|
- }
|
|
|
-
|
|
|
d->AddingEntry = false;
|
|
|
}
|
|
|
|
|
@@ -423,7 +519,8 @@ void ctkErrorLogModel::clear()
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
-void ctkErrorLogModel::filterEntry(const LogLevels& logLevel, bool disableFilter)
|
|
|
+void ctkErrorLogModel::filterEntry(const ctkErrorLogLevel::LogLevels& logLevel,
|
|
|
+ bool disableFilter)
|
|
|
{
|
|
|
Q_D(ctkErrorLogModel);
|
|
|
|
|
@@ -432,14 +529,14 @@ void ctkErrorLogModel::filterEntry(const LogLevels& logLevel, bool disableFilter
|
|
|
{
|
|
|
patterns << this->filterRegExp().pattern().split("|");
|
|
|
}
|
|
|
- patterns.removeAll(this->logLevelAsString(Self::None));
|
|
|
+ patterns.removeAll(d->ErrorLogLevel(ctkErrorLogLevel::None));
|
|
|
|
|
|
// foreach(QString s, patterns)
|
|
|
// {
|
|
|
// std::cout << "pattern:" << qPrintable(s) << std::endl;
|
|
|
// }
|
|
|
|
|
|
- QMetaEnum logLevelEnum = this->metaObject()->enumerator(0);
|
|
|
+ QMetaEnum logLevelEnum = d->ErrorLogLevel.metaObject()->enumerator(0);
|
|
|
Q_ASSERT(QString("LogLevel").compare(logLevelEnum.name()) == 0);
|
|
|
|
|
|
// Loop over enum values and append associated name to 'patterns' if
|
|
@@ -449,16 +546,16 @@ void ctkErrorLogModel::filterEntry(const LogLevels& logLevel, bool disableFilter
|
|
|
int aLogLevel = logLevelEnum.value(i);
|
|
|
if (logLevel & aLogLevel)
|
|
|
{
|
|
|
- QString logLevelAsString = this->logLevelAsString(static_cast<Self::LogLevel>(aLogLevel));
|
|
|
+ QString logLevelAsString = d->ErrorLogLevel(static_cast<ctkErrorLogLevel::LogLevel>(aLogLevel));
|
|
|
if (!disableFilter)
|
|
|
{
|
|
|
patterns << logLevelAsString;
|
|
|
- d->CurrentLogLevelFilter |= static_cast<Self::LogLevels>(aLogLevel);
|
|
|
+ d->CurrentLogLevelFilter |= static_cast<ctkErrorLogLevel::LogLevels>(aLogLevel);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
patterns.removeAll(logLevelAsString);
|
|
|
- d->CurrentLogLevelFilter ^= static_cast<Self::LogLevels>(aLogLevel);
|
|
|
+ d->CurrentLogLevelFilter ^= static_cast<ctkErrorLogLevel::LogLevels>(aLogLevel);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -467,7 +564,7 @@ void ctkErrorLogModel::filterEntry(const LogLevels& logLevel, bool disableFilter
|
|
|
{
|
|
|
// If there are no patterns, let's filter with the None level so that
|
|
|
// all entries are filtered out.
|
|
|
- patterns << this->logLevelAsString(Self::None);
|
|
|
+ patterns << d->ErrorLogLevel(ctkErrorLogLevel::None);
|
|
|
}
|
|
|
|
|
|
bool filterChanged = true;
|
|
@@ -490,15 +587,16 @@ void ctkErrorLogModel::filterEntry(const LogLevels& logLevel, bool disableFilter
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
-ctkErrorLogModel::LogLevels ctkErrorLogModel::logLevelFilter()const
|
|
|
+ctkErrorLogLevel::LogLevels ctkErrorLogModel::logLevelFilter()const
|
|
|
{
|
|
|
- QMetaEnum logLevelEnum = this->metaObject()->enumerator(0);
|
|
|
+ Q_D(const ctkErrorLogModel);
|
|
|
+ QMetaEnum logLevelEnum = d->ErrorLogLevel.metaObject()->enumerator(0);
|
|
|
Q_ASSERT(QString("LogLevel").compare(logLevelEnum.name()) == 0);
|
|
|
|
|
|
- Self::LogLevels filter = Self::Unknown;
|
|
|
+ ctkErrorLogLevel::LogLevels filter = ctkErrorLogLevel::Unknown;
|
|
|
foreach(const QString& filterAsString, this->filterRegExp().pattern().split("|"))
|
|
|
{
|
|
|
- filter |= static_cast<Self::LogLevels>(logLevelEnum.keyToValue(filterAsString.toLatin1()));
|
|
|
+ filter |= static_cast<ctkErrorLogLevel::LogLevels>(logLevelEnum.keyToValue(filterAsString.toLatin1()));
|
|
|
}
|
|
|
return filter;
|
|
|
}
|
|
@@ -516,3 +614,155 @@ void ctkErrorLogModel::setLogEntryGrouping(bool value)
|
|
|
Q_D(ctkErrorLogModel);
|
|
|
d->LogEntryGrouping = value;
|
|
|
}
|
|
|
+
|
|
|
+//------------------------------------------------------------------------------
|
|
|
+bool ctkErrorLogModel::asynchronousLogging()const
|
|
|
+{
|
|
|
+ Q_D(const ctkErrorLogModel);
|
|
|
+ return d->AsynchronousLogging;
|
|
|
+}
|
|
|
+
|
|
|
+//------------------------------------------------------------------------------
|
|
|
+void ctkErrorLogModel::setAsynchronousLogging(bool value)
|
|
|
+{
|
|
|
+ Q_D(ctkErrorLogModel);
|
|
|
+ if (d->AsynchronousLogging == value)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach(const QString& handlerName, d->RegisteredHandlers.keys())
|
|
|
+ {
|
|
|
+ d->setMessageHandlerConnection(
|
|
|
+ d->RegisteredHandlers.value(handlerName), value);
|
|
|
+ }
|
|
|
+
|
|
|
+ d->AsynchronousLogging = value;
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+// ctkErrorLogAbstractMessageHandlerPrivate
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+class ctkErrorLogAbstractMessageHandlerPrivate
|
|
|
+{
|
|
|
+public:
|
|
|
+ ctkErrorLogAbstractMessageHandlerPrivate();
|
|
|
+ ~ctkErrorLogAbstractMessageHandlerPrivate();
|
|
|
+
|
|
|
+ bool Enabled;
|
|
|
+ QString HandlerPrettyName;
|
|
|
+
|
|
|
+ // Use "int" instead of "ctkErrorLogModel::TerminalOutput" to avoid compilation warning ...
|
|
|
+ // qhash.h:879: warning: passing ‘ctkErrorLogModel::TerminalOutput’ chooses ‘int’ over ‘uint’ [-Wsign-promo]
|
|
|
+ QHash<int, ctkErrorLogTerminalOutput*> TerminalOutputs;
|
|
|
+};
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+ctkErrorLogAbstractMessageHandlerPrivate::
|
|
|
+ctkErrorLogAbstractMessageHandlerPrivate()
|
|
|
+ : Enabled(false)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+ctkErrorLogAbstractMessageHandlerPrivate::~ctkErrorLogAbstractMessageHandlerPrivate()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+// ctkErrorLogAbstractMessageHandlerPrivate methods
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+ctkErrorLogAbstractMessageHandler::ctkErrorLogAbstractMessageHandler()
|
|
|
+ : Superclass(), d_ptr(new ctkErrorLogAbstractMessageHandlerPrivate)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+ctkErrorLogAbstractMessageHandler::~ctkErrorLogAbstractMessageHandler()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+QString ctkErrorLogAbstractMessageHandler::handlerPrettyName()const
|
|
|
+{
|
|
|
+ Q_D(const ctkErrorLogAbstractMessageHandler);
|
|
|
+ if (d->HandlerPrettyName.isEmpty())
|
|
|
+ {
|
|
|
+ return this->handlerName();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return d->HandlerPrettyName;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkErrorLogAbstractMessageHandler::setHandlerPrettyName(const QString& newHandlerPrettyName)
|
|
|
+{
|
|
|
+ Q_D(ctkErrorLogAbstractMessageHandler);
|
|
|
+ d->HandlerPrettyName = newHandlerPrettyName;
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+bool ctkErrorLogAbstractMessageHandler::enabled()const
|
|
|
+{
|
|
|
+ Q_D(const ctkErrorLogAbstractMessageHandler);
|
|
|
+ return d->Enabled;
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkErrorLogAbstractMessageHandler::setEnabled(bool value)
|
|
|
+{
|
|
|
+ Q_D(ctkErrorLogAbstractMessageHandler);
|
|
|
+ if (value == d->Enabled)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this->setEnabledInternal(value);
|
|
|
+ d->Enabled = value;
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkErrorLogAbstractMessageHandler::handleMessage(const QString& threadId,
|
|
|
+ ctkErrorLogLevel::LogLevel logLevel,
|
|
|
+ const QString& origin, const QString& text)
|
|
|
+{
|
|
|
+ Q_D(ctkErrorLogAbstractMessageHandler);
|
|
|
+ if (logLevel <= ctkErrorLogLevel::Info)
|
|
|
+ {
|
|
|
+ if(d->TerminalOutputs.contains(ctkErrorLogModel::StandardOutput))
|
|
|
+ {
|
|
|
+ d->TerminalOutputs.value(ctkErrorLogModel::StandardOutput)->output(text);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(d->TerminalOutputs.contains(ctkErrorLogModel::StandardError))
|
|
|
+ {
|
|
|
+ d->TerminalOutputs.value(ctkErrorLogModel::StandardError)->output(text);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ emit this->messageHandled(QDateTime::currentDateTime(), threadId, logLevel, origin, text);
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+ctkErrorLogTerminalOutput* ctkErrorLogAbstractMessageHandler::terminalOutput(
|
|
|
+ ctkErrorLogModel::TerminalOutput terminalOutputType)const
|
|
|
+{
|
|
|
+ Q_D(const ctkErrorLogAbstractMessageHandler);
|
|
|
+ if(d->TerminalOutputs.contains(terminalOutputType))
|
|
|
+ {
|
|
|
+ return d->TerminalOutputs.value(terminalOutputType);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkErrorLogAbstractMessageHandler::setTerminalOutput(
|
|
|
+ ctkErrorLogModel::TerminalOutput terminalOutputType, ctkErrorLogTerminalOutput* terminalOutput)
|
|
|
+{
|
|
|
+ Q_D(ctkErrorLogAbstractMessageHandler);
|
|
|
+ d->TerminalOutputs.insert(terminalOutputType, terminalOutput);
|
|
|
+}
|