summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWolfgang Beck <wolfgang.beck@nokia.com>2012-05-03 12:38:03 +1000
committerLincoln Ramsay <lincoln.ramsay@nokia.com>2012-05-11 03:06:21 +0200
commit57555714f0b9cacefd7c1e2da61ed3c612d7791c (patch)
treefb4a0463a85d55fda7457f0055a6dfdf87a14d49
parent85cc3138442ba282b869788fd4a4fd3a56d74758 (diff)
Using QLoggingCategory without QT_LOG_CATEGORY macro
Change-Id: I086107777d49f1b9f6bc2396b8276f333ecd0e85 Reviewed-by: Lincoln Ramsay <lincoln.ramsay@nokia.com>
-rw-r--r--doc/src/index.qdoc75
-rw-r--r--examples/logger/main.cpp18
-rw-r--r--src/logger/qlogger.cpp380
-rw-r--r--src/logger/qlogger.h101
-rw-r--r--src/logger/qlogger_p.h32
-rw-r--r--tests/auto/logger/logger.pro2
-rw-r--r--tests/auto/logger/tst_qlogger.cpp68
7 files changed, 494 insertions, 182 deletions
diff --git a/doc/src/index.qdoc b/doc/src/index.qdoc
index 7e9a32b..efaa7e8 100644
--- a/doc/src/index.qdoc
+++ b/doc/src/index.qdoc
@@ -54,9 +54,13 @@
Developer can create their own logging categories.
Every category can be turned on or off for logging during runtime.
+
Each category contains a subset of "debug", "warning" and "critical" subcategories.
+
In the initialization logging will be performed for all "warning" and "critical" subcategories.
+ See \l {Default settings} .
+
\section1 How to Use
@@ -70,12 +74,14 @@
#include <qlogger.h>
- Note: qDebug, qWarning and qCritical are re-defined by this header.
+ Note: The current implementation re-defines qDebug, qWarning and qCritical by this header.
+
\section2 Creating Logging Rules
\target logging_rules
As mentioned above logging rules are needed to control the behavior of the logging.
+
The logging rules containing basically the categories and a true/false value for each category:
@@ -90,13 +96,13 @@
\endtable
Of course you could write Nokia.driver.usb = true, this will enable all subcategories (debug, warning and critical).
- Vice versa with Nokia.driver.usb = false.
+ Vice versa with Nokia.driver.usb = false.
- \section3 Wildcards
+ Wildcard (*) category definitions are possible as well.
+ The order of the categories in your configuration is important. From top to bottom the category priority is low to high.
- Wildcard (*) category definitions are possible as well. The order of the categories in your configuration is important. From top to bottom the category priority is low to high.
e.g:
\table
@@ -106,11 +112,12 @@
\row \li *Nokia*=true
\endtable
- All categories containing the word Nokia will be logged.
- Willdcard "*" can only apply to the beginning or/and to the end of your configuration category entry.
+ In this example all categories containing the word Nokia will be logged.
+ Willdcard "*" can only apply to the beginning or/and to the end of your configuration category entry.
The usage of qDebug(), qWarning() and qCrititcal results in the category "default".
+
e.g.
\table
@@ -121,26 +128,47 @@
\endtable
- The logging rule file can be defined by using the environment variable \l QT_LOGGING_CONFIG.
- The application developer can set the rule file by using \l qSetLoggingRulesFile() or can
- set the rules directly using \l qSetLoggingRules().
+ \section2 Create your Category Logging Object in your Project
- If there is no configuration available, the \l {Default settings} will be used.
+ There are two different ways to create your own category object.
- \section2 QT_LOGGING_CONFIG
- The QT_LOGGING_CONFIG environment variable overrides both qSetLoggingRulesFile() and
- qSetLoggingRules() if it points to a file.
+ 1. Qt provides the \l QT_LOG_CATEGORY() macro to create your logging Categories:
- If QT_LOGGING_CONFIG is relative, QStandardPaths::writeableLocation(QStandardPaths::ConfigLocation) will be prepended.
+ \snippet logger/main.cpp 1
- \section2 Logging usage in your project
+ 2. You can create your own \l QLoggingCategory object:
- Qt provides the \l QT_LOG_CATEGORY() macro to create your logging Categories:
+ \snippet logger/main.cpp 4
- \snippet logger/main.cpp 1
- In this example a logging category NOKIA_DRIVER_USB with a category string of "Nokia.driver.usb" and NOKIA_DRIVER_EVENT with a category string of "Nokia.driver.event" is created.
+ \section2 Activate Logging Rules
+
+ There are 3 three different way to activate the logging rules:
+
+ \table
+ \header
+ \row \li 1. \li The application developer can set the rule file by using \l qSetLoggingRulesFile()
+ \snippet logger/main.cpp 2
+
+ \row \li 2. \li The application developer can set the rules directly using \l qSetLoggingRules().
+ \snippet logger/main.cpp 5
+
+ \row \li 3. \li The logging rule file can be defined by using the environment variable called \section2 QT_LOGGING_CONFIG
+
+ The QT_LOGGING_CONFIG environment variable overrides both qSetLoggingRulesFile() and
+
+ qSetLoggingRules() if it points to a file.
+
+ If QT_LOGGING_CONFIG is relative, QStandardPaths::writeableLocation(QStandardPaths::ConfigLocation) will be prepended.
+ \endtable
+
+ If there is no loggin rules available, the \l {Default settings} will be used.
+
+ In this example a logging category NOKIA_DRIVER_USB with a category string of "Nokia.driver.usb"
+
+ and NOKIA_DRIVER_EVENT with a category string of "Nokia.driver.event" is created.
+
In you configuration file you could write:
\table
@@ -151,16 +179,13 @@
\endtable
- Next you need to tell Qt where the logging rules configuration file can be found.
-
- \snippet logger/main.cpp 2
-
- In this example the configuration file "mylogging.cfg" is in the current directory.
+ In this example the configuration file "logrules.txt" is in the current directory.
For category-based logging statements, you need to use the \l qCDebug(), \l qCWarning() and \l qCCritical() macros.
\snippet logger/main.cpp 3
+
\section1 Default settings
The defaults are as follows.
@@ -177,5 +202,7 @@
In other words, only \l qCDebug() statements are hidden by default.
- \sa QLogging
+ \section1 Classes
+
+ \annotatedlist qlogging_classes
*/
diff --git a/examples/logger/main.cpp b/examples/logger/main.cpp
index 1443433..c82c02c 100644
--- a/examples/logger/main.cpp
+++ b/examples/logger/main.cpp
@@ -96,10 +96,18 @@ protected:
void LogThread::run()
{
+//![4]
+ QLoggingCategory myCategoryObject("My.Category.Object");
+//![4]
+
for (int i = 0; i < 60; i++) {
qDebug() << "loop " << i;
//![3]
+ //Category created by QT_LOG_CATEGORY
qCDebug(NOKIA_DRIVER_USB) << "USB legacy loaded";
+
+ //Category created by using QLoggingCategory directly
+ qCDebug(myCategoryObject) << "Log with my category object";
//![3]
sleep(1);
qWarning() << "loop " << i;
@@ -133,9 +141,17 @@ int main(int argc, char *argv[])
QFile::remove(LOGOUTPUTFILE);
fprintf(stdout, "%s\r\n", "Now you can open the logrules.txt file and de/activate categories");
+ if (QFile::exists("./logrules.txt")){
//![2]
- QtLogger::qSetLoggingRulesFile("./logrules.txt");
+ QtLogger::qSetLoggingRulesFile("./logrules.txt");
//![2]
+ }
+ else {
+//![5]
+ QtLogger::qSetLoggingRules(QByteArray("Nokia.driver.usb=true"));
+//![5]
+ }
+
LogThread logthread;
logthread.start();
diff --git a/src/logger/qlogger.cpp b/src/logger/qlogger.cpp
index 4307769..d2d868e 100644
--- a/src/logger/qlogger.cpp
+++ b/src/logger/qlogger.cpp
@@ -49,14 +49,70 @@
#include <QFileSystemWatcher>
#include <QThread>
#include <QCoreApplication>
+#include <QMap>
#include "qlogger_p.h"
QT_USE_NAMESPACE
QT_LOGGER_BEGIN_NAMESPACE
+// qDebug truth table
+// ---------------------------------------
+// Log enabled | Category enabled | do Log
+// ---------------------------------------
+// false | ignore | true
+// true | false | false
+// true | true | true
+
+// qWarning truth table
+// ---------------------------------------
+// Log enabled | Category enabled | do Log
+// ---------------------------------------
+// false | ignore | true
+// true | false | false
+// true | true | true
+
+// qCritical truth table
+// ---------------------------------------
+// Log enabled | Category enabled | do Log
+// ---------------------------------------
+// false | ignore | true
+// true | false | false
+// true | true | true
+
+// qCDebug truth table
+// ---------------------------------------
+// Log enabled | Category enabled | do Log
+// ---------------------------------------
+// false | ignore | false
+// true | false | false
+// true | true | true
+
+// qCWarning truth table
+// ---------------------------------------
+// Log enabled | Category enabled | do Log
+// ---------------------------------------
+// false | ignore | true
+// true | false | false
+// true | true | true
+
+// qCCritical truth table
+// ---------------------------------------
+// Log enabled | Category enabled | do Log
+// ---------------------------------------
+// false | ignore | true
+// true | false | false
+// true | true | true
+
+
Q_GLOBAL_STATIC(QLoggingPrivate, qLogging)
+
// Set to true after QLoggingPrivate has destructed
+//declare static members
static bool privateUnloaded = false;
+static QMutex _mutexUnloadedCategory;
+static QMutex _mutexPrivateCategoryObjects;
+static QMap<QString, QLoggingCategoryPrivate *> _privateCategoryObjects;
+static QLoggingCategoryDefault default_QLoggingCategory;
// Set to true if a valid config file or set of rules has been specified
static bool gEnabled = false;
@@ -82,81 +138,174 @@ static void checkEnvironment()
}
}
-namespace QLoggingCategories
+/*!
+ \class QLoggingCategory
+ \ingroup qlogging_classes
+
+ \brief The QLoggingCategory class represents a category logging object for the category logging framework.
+
+ Users can create a QLoggingCategory object and use it in conjunction with
+ qCDebug, qCWarning and qCCritical.
+*/
+
+/*!
+ Construct a QLoggingCategory object with the provided \a category name.
+ The object becomes the local identifier for the category.
+*/
+QLoggingCategory::QLoggingCategory(const char *category)
+ : d_ptr(0)
+ , _categoryName(category)
{
- QLoggingCategory default_QLoggingCategory("default");
-
- QLoggingCategory::QLoggingCategory(const char *cat)
- : _enabledDebug(false)
- , _enabledWarning(true)
- , _enabledCritical(true)
- , _registered(false)
- , _category(cat)
- {
- }
+}
- QLoggingCategory::~QLoggingCategory()
- {
- if (_registered && !privateUnloaded) {
- qLogging()->unregisterCategory(*this);
- }
- }
+/*!
+ Returns the category name.
+*/
+const char* QLoggingCategory::categoryName()
+{
+ return _categoryName;
+}
- bool QLoggingCategory::statusMessageType(const QtMsgType &type)
- {
- switch (type) {
- case QtDebugMsg: return _enabledDebug;
- case QtWarningMsg: return _enabledWarning;
- case QtCriticalMsg: return _enabledCritical;
- default:
- break;
+/*!
+ \internal Returns the QLoggingCategory object used by the qDebug, qWarning and qCritical macros.
+*/
+QLoggingCategory& QLoggingCategory::defaultCategory()
+{
+ return default_QLoggingCategory;
+}
+
+/*!
+ Destruct a QLoggingCategory object
+*/
+QLoggingCategory::~QLoggingCategory()
+{
+ if (d_ptr) {
+ QMutexLocker locker1(&_mutexPrivateCategoryObjects);
+ QMutexLocker locker(&_mutexUnloadedCategory);
+ //Don't use QExplicitlySharedDataPointer for only reference counting
+ //We have to lock the _privateCategoryObjects map anyways and therfore we lock the reference counting as well.
+ d_ptr->_references--;
+ if (d_ptr->_references == 0) {
+ if (d_ptr->_registered && !privateUnloaded) {
+ qLogging()->unregisterCategory(*this);
+ }
+ if (d_ptr->_references == 0) {
+ QString strcategory = QString::fromLatin1(d_ptr->_categoryName);
+ QMap<QString, QLoggingCategoryPrivate* >::iterator it = _privateCategoryObjects.find(strcategory);
+ if (it != _privateCategoryObjects.end())
+ _privateCategoryObjects.remove(strcategory);
+
+ delete d_ptr;
+ }
}
- return false;
}
+}
- void QLoggingCategory::setStatusMessageType(const QtMsgType &type, bool status)
- {
- switch (type) {
- case QtDebugMsg: _enabledDebug = status;
- case QtWarningMsg: _enabledWarning = status;
- case QtCriticalMsg: _enabledCritical = status;
- default:
- break;
+/*!
+ \internal Default category class to create and initialisate a default category object
+*/
+QLoggingCategoryDefault::QLoggingCategoryDefault()
+ : QLoggingCategory("default")
+{
+ //Note d_func creates private object and assign it to the d_ptr
+ d_func()->_enabledDebug = true;
+}
+
+/*!
+ Returns true if a message of type \a msgtype will be printed. Returns false otherwise.
+
+ This function may be useful to avoid doing expensive work to generate data that is only used for debug output.
+
+ \code
+ // don't run the expensive code if the string won't print
+ if (CAT.isEnabled(QtDebugMsg)) {
+ QStringList items;
+ foreach (obj, list) {
+ items << format(obj);
+ }
+ qCDebug(CAT) << items;
}
- }
+ \endcode
- bool isEnabled()
- {
- if (gEnvironment == EnvironmentNotChecked)
- checkEnvironment();
- return gEnabled;
- }
+ Note that the expansion of qCDebug() prevents arguments from being evaluated if the string won't print so it is not normally required to check isEnabled().
- bool isEnabled(QLoggingCategories::QLoggingCategory &category, QtMsgType type)
- {
- if (!isEnabled())
- return false;
- return qLogging()->isEnabled(category, type);
+ \code
+ // expensive_func is not called if the string won't print
+ qCDebug(CAT) << expensive_func();
+ \endcode
+*/
+bool QLoggingCategory::isEnabled(QtMsgType msgtype)
+{
+ //Check if the contains of the environment variable QT_LOGGING_CONFIG was checked
+ //If not checkEnvironment will modify the gEnabled static member.
+ if (gEnvironment == EnvironmentNotChecked)
+ checkEnvironment();
+
+ /* Note that default category (qDebug & co) differs from the category objects
+ regarding to their message types initialisation values
+
+ Message Type | default categor | category Object
+ =========================================================================
+ QtDebugMsg | true | false
+ QtWarningMsg | true | true
+ QtCriticalMsg | true | true
+ */
+ if (!gEnabled) {
+ //Category logging framework is disable so return the default values
+ //Note: Default category already exist so d_ptr is valid for default category
+ if (d_ptr)
+ return d_ptr->statusMessageType(msgtype);
+ //We do this because we want to avoid to create a QLoggingCategoryPrivate object
+ //and doing expensive operations if categroy logging is not active.
+ switch (msgtype) {
+ case QtDebugMsg: return false;
+ case QtWarningMsg: return true;
+ case QtCriticalMsg: return true;
+ default:
+ return false;
+ }
}
+ return qLogging()->isEnabled(*this, msgtype);
+}
- QLoggingCategory& defaultCategory()
- {
- return default_QLoggingCategory;
+/*!
+ \internal Overwrite the private object access function.
+ */
+QLoggingCategoryPrivate * QLoggingCategory::d_func()
+{
+ if (!d_ptr) {
+ QMutexLocker locker(&_mutexPrivateCategoryObjects);
+ //Another thread can call this function for the same QLoggingCategory object now
+ //Check the d_ptr after mutex lock again.
+ if (!d_ptr) {
+ QString strcategory;
+ //just for the insane case someone calls this constructor with an empty category parameter
+ if (_categoryName)
+ strcategory = QString::fromLatin1(_categoryName);
+ QMap<QString, QLoggingCategoryPrivate* >::iterator it = _privateCategoryObjects.find(strcategory);
+ if (it != _privateCategoryObjects.end())
+ d_ptr = *it;
+ else {
+ d_ptr = new QLoggingCategoryPrivate(_categoryName);
+ _privateCategoryObjects.insert(strcategory, d_ptr);
+ }
+ //Don't use QExplicitlySharedDataPointer for only reference counting
+ //We have to lock the _privateCategoryObjects map anyways and therfore we lock the reference counting as well.
+ d_ptr->_references++;
+ }
}
+ return d_ptr;
}
-/*!
- \namespace QLogging
-*/
/*!
- \relates QLogging
+ \relates QLoggingCategory
Load logging rules from \a path.
If \a path is relative, QStandardPaths::writeableLocation(QStandardPaths::ConfigLocation) will be prepended.
Note that if the QT_LOGGING_CONFIG environment variables points to a file, this function does nothing.
- \sa QT_LOGGING_CONFIG
+ \sa {Activate Logging Rules}
*/
void qSetLoggingRulesFile(const QString &path)
{
@@ -168,14 +317,14 @@ void qSetLoggingRulesFile(const QString &path)
}
/*!
- \relates QLogging
+ \relates QLoggingCategory
Set logging \a rules directly.
This is primarily intended for applications that wish to provide runtime control of their
logging rather than relying on the user providing a configuration file.
Note that if the QT_LOGGING_CONFIG environment variables points to a file, this function does nothing.
- \sa QT_LOGGING_CONFIG
+ \sa {Activate Logging Rules}
*/
void qSetLoggingRules(const QByteArray &rules)
{
@@ -186,42 +335,45 @@ void qSetLoggingRules(const QByteArray &rules)
}
/*!
- \relates QLogging
+ \relates QLoggingCategory
\macro qCDebug(cat)
- Works like qDebug() but only prints out if \a cat has been enabled.
+ Works like qDebug() but using category object \a cat.
+ Note: this does not process arguments if the string will not be printed so do not rely on side effects.
\code
qCDebug(CAT) << "my message";
\endcode
- \sa QT_LOG_CATEGORY(), {Creating Logging Rules}
+ \sa QT_LOG_CATEGORY(), {Creating Logging Rules}, QLoggingCategory
*/
/*!
- \relates QLogging
+ \relates QLoggingCategory
\macro qCWarning(cat)
- Works like qWarning() and can be disabled with \a cat.
+ Works like qWarning() but using category object \a cat.
+ Note: this does not process arguments if the string will not be printed so do not rely on side effects.
\code
qCWarning(CAT) << "my message";
\endcode
- \sa QT_LOG_CATEGORY(), {Creating Logging Rules}
+ \sa QT_LOG_CATEGORY(), {Creating Logging Rules}, QLoggingCategory
*/
/*!
- \relates QLogging
+ \relates QLoggingCategory
\macro qCCritical(cat)
- Works like qCritical() and can be disabled with \a cat.
+ Works like qCritical() but using category object \a cat.
+ Note: this does not process arguments if the string will not be printed so do not rely on side effects.
\code
qCCritical(CAT) << "my message";
\endcode
- \sa QT_LOG_CATEGORY(), {Creating Logging Rules}
+ \sa QT_LOG_CATEGORY(), {Creating Logging Rules}, QLoggingCategory
*/
/*!
- \relates QLogging
- \macro QT_LOG_CATEGORY(cat, identifier)
- Registers a logging category with local identifier \a cat and complete identifier \a identifier.
+ \relates QLoggingCategory
+ \macro QT_LOG_CATEGORY(cat, categoryname)
+ Registers a logging category with local identifier \a cat and complete identifier \a categoryname.
This macro must be used outside of a class or method.
- \sa {Logging usage in your project}
+ \sa {Create your Category Logging Object in your Project}, QLoggingCategory
*/
@@ -231,9 +383,9 @@ void qSetLoggingRules(const QByteArray &rules)
-
-
-
+/*********************************
+ *Private objects implementation
+ *********************************/
/*!
\internal For Autotest
@@ -255,7 +407,7 @@ QLoggingPrivate::QLoggingPrivate()
this->moveToThread(QCoreApplication::instance()->thread());
//add default category
- _registeredCategories.append(&QLoggingCategories::default_QLoggingCategory);
+ _registeredCategories.append(&QLoggingCategory::defaultCategory());
}
/*!
@@ -264,6 +416,7 @@ QLoggingPrivate::QLoggingPrivate()
*/
QLoggingPrivate::~QLoggingPrivate()
{
+ QMutexLocker locker(&_mutexUnloadedCategory);
privateUnloaded = true;
}
@@ -360,7 +513,7 @@ void QLoggingPrivate::fileChanged(const QString &path)
*/
void QLoggingPrivate::readSettings(QIODevice &device)
{
- QMutexLocker locker(&_mutex);
+ QMutexLocker locker(&_mutexRegisteredCategory);
{
_logConfigItemList.clear();
@@ -379,7 +532,7 @@ void QLoggingPrivate::readSettings(QIODevice &device)
}
//Now all the categories are read, so we can update all known QLoggingCategories members.
- foreach (QLoggingCategories::QLoggingCategory *category, _registeredCategories) {
+ foreach (QLoggingCategory *category, _registeredCategories) {
updateCategory(category);
}
@@ -394,18 +547,18 @@ void QLoggingPrivate::readSettings(QIODevice &device)
\internal
Updates all the registered category members against the filter.
*/
-void QLoggingPrivate::updateCategory(QLoggingCategories::QLoggingCategory *log)
+void QLoggingPrivate::updateCategory(QLoggingCategory *log)
{
//set the default back (debug disable, warning and critical enabled)
- if (log == &QLoggingCategories::default_QLoggingCategory) {
- log->_enabledDebug = true;
- log->_enabledWarning = true;
- log->_enabledCritical = true;
+ if (log == &QLoggingCategory::defaultCategory()) {
+ log->d_func()->_enabledDebug = true;
+ log->d_func()->_enabledWarning = true;
+ log->d_func()->_enabledCritical = true;
} else {
- log->_enabledDebug = false;
- log->_enabledWarning = true;
- log->_enabledCritical = true;
+ log->d_func()->_enabledDebug = false;
+ log->d_func()->_enabledWarning = true;
+ log->d_func()->_enabledCritical = true;
}
foreach (QLogConfigFilterItem item, _logConfigItemList) {
@@ -413,15 +566,15 @@ void QLoggingPrivate::updateCategory(QLoggingCategories::QLoggingCategory *log)
int filterpass = item.pass(log, QtDebugMsg);
//apply filter if filterpass is not 0
if (filterpass != 0)
- log->_enabledDebug = (filterpass > 0);
+ log->d_func()->_enabledDebug = (filterpass > 0);
//Warning
filterpass = item.pass(log, QtWarningMsg);
if (filterpass != 0)
- log->_enabledWarning = (filterpass > 0);
+ log->d_func()->_enabledWarning = (filterpass > 0);
//Critical
filterpass = item.pass(log, QtCriticalMsg);
if (filterpass != 0)
- log->_enabledCritical = (filterpass > 0);
+ log->d_func()->_enabledCritical = (filterpass > 0);
}
}
@@ -429,36 +582,67 @@ void QLoggingPrivate::updateCategory(QLoggingCategories::QLoggingCategory *log)
\internal
Function that checks if the category is enabled and registered the category member if not already registered.
*/
-bool QLoggingPrivate::isEnabled(QLoggingCategories::QLoggingCategory &category, QtMsgType type)
+bool QLoggingPrivate::isEnabled(QLoggingCategory &category, QtMsgType type)
{
- if (category._registered)
- return category.statusMessageType(type);
+ if (category.d_func()->_registered)
+ return category.d_func()->statusMessageType(type);
//category is unregistered.
//First update category (let it through the filter)
{
- QMutexLocker locker(&_mutex);
+ QMutexLocker locker(&_mutexRegisteredCategory);
//lock against _logConfigItemList between updateCategory and readSettings
updateCategory(&category);
- category._registered = true;
+ category.d_func()->_registered = true;
_registeredCategories.append(&category);
}
- return category.statusMessageType(type);
+ return category.d_func()->statusMessageType(type);
}
/*!
\internal
Unregister a category object.
*/
-void QLoggingPrivate::unregisterCategory(QLoggingCategories::QLoggingCategory &category)
+void QLoggingPrivate::unregisterCategory(QLoggingCategory &category)
{
- QMutexLocker locker(&_mutex);
+ QMutexLocker locker(&_mutexRegisteredCategory);
//lock against _logConfigItemList between updateCategory and readSettings
- category._registered = false;
+ category.d_func()->_registered = false;
_registeredCategories.removeOne(&category);
}
+/*!
+ \internal Constructor of the private QLoggingCategory object
+*/
+QLoggingCategoryPrivate::QLoggingCategoryPrivate(const char *categoryname)
+ : _enabledDebug(false)
+ , _enabledWarning(true)
+ , _enabledCritical(true)
+ , _registered(false)
+ , _categoryName(categoryname)
+ , _references(0)
+{
+}
+
+QLoggingCategoryPrivate::~QLoggingCategoryPrivate()
+{
+}
+
+/*!
+ \internal Returns true if the message type is activated otherwise false;
+*/
+bool QLoggingCategoryPrivate::statusMessageType(const QtMsgType &type)
+{
+ switch (type) {
+ case QtDebugMsg: return _enabledDebug;
+ case QtWarningMsg: return _enabledWarning;
+ case QtCriticalMsg: return _enabledCritical;
+ default:
+ break;
+ }
+ return false;
+}
#define INVALID 0x00
#define CATEGORY 0x01
@@ -507,9 +691,9 @@ void QLogConfigFilterItem::parse()
\internal
return value 1 means filter passed, 0 means filter doesn't influence this category, -1 means category doesn't pass this filter
*/
-int QLogConfigFilterItem::pass(const QLoggingCategories::QLoggingCategory *log, const QtMsgType &type)
+int QLogConfigFilterItem::pass(QLoggingCategory *log, const QtMsgType &type)
{
- QString fullCategory = QString::fromLatin1(log->_category);
+ QString fullCategory = QString::fromLatin1(log->categoryName());
switch (type) {
case QtDebugMsg:
fullCategory += QString::fromLatin1(".debug");
@@ -529,7 +713,7 @@ int QLogConfigFilterItem::pass(const QLoggingCategories::QLoggingCategory *log,
//NOKIA.com.debug = true
//or
//NOKIA.com = true
- if (_category == QString::fromLatin1(log->_category) || _category == fullCategory)
+ if (_category == QString::fromLatin1(log->categoryName()) || _category == fullCategory)
return (_active ? 1 : -1);
}
diff --git a/src/logger/qlogger.h b/src/logger/qlogger.h
index aada8c3..ba527de 100644
--- a/src/logger/qlogger.h
+++ b/src/logger/qlogger.h
@@ -49,28 +49,23 @@
QT_BEGIN_HEADER
QT_LOGGER_BEGIN_NAMESPACE
-namespace QLoggingCategories {
- class Q_LOGGER_EXPORT QLoggingCategory {
- public:
- QLoggingCategory(const char *cat);
- ~QLoggingCategory();
- bool statusMessageType(const QtMsgType &type);
- void setStatusMessageType(const QtMsgType &type, bool status);
- bool _enabledDebug;
- bool _enabledWarning;
- bool _enabledCritical;
- bool _registered;
- const char *_category;
- };
- Q_LOGGER_EXPORT QLoggingCategory& defaultCategory();
- Q_LOGGER_EXPORT bool isEnabled(QLoggingCategory &category, QtMsgType type);
- Q_LOGGER_EXPORT bool isEnabled();
-}
-
-// This is here so that QDoc has something to attach the functions
-// and macros to.
-namespace QLogging {
-}
+class QLoggingCategoryPrivate;
+class Q_LOGGER_EXPORT QLoggingCategory {
+ Q_DISABLE_COPY(QLoggingCategory)
+public:
+ explicit QLoggingCategory(const char *category);
+ ~QLoggingCategory();
+ bool isEnabled(QtMsgType msgtype);
+ const char * categoryName();
+ static QLoggingCategory& defaultCategory();
+protected:
+ QLoggingCategoryPrivate * d_func();
+private:
+ QLoggingCategoryPrivate *d_ptr;
+ const char *_categoryName;
+
+ friend class QLoggingPrivate;
+};
Q_LOGGER_EXPORT void qSetLoggingRules(const QByteArray &rules);
Q_LOGGER_EXPORT void qSetLoggingRulesFile(const QString &path);
@@ -84,41 +79,55 @@ QT_LOGGER_USE_NAMESPACE
# undef qDebug
#endif
-#define qDebug if (QLoggingCategories::isEnabled() && !QLoggingCategories::isEnabled(QLoggingCategories::defaultCategory(), QtDebugMsg)) /*NOP*/; \
- else QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug
+#define qDebug \
+ if (!QLoggingCategory::defaultCategory().isEnabled(QtDebugMsg)) \
+ /*NOP*/; \
+ else \
+ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug
#if defined(qWarning)
# undef qWarning
#endif
-#define qWarning if (QLoggingCategories::isEnabled() && !QLoggingCategories::isEnabled(QLoggingCategories::defaultCategory(), QtWarningMsg)) /*NOP*/; \
- else QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).warning
+#define qWarning \
+ if (!QLoggingCategory::defaultCategory().isEnabled(QtWarningMsg)) \
+ /*NOP*/; \
+ else \
+ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).warning
#if defined(qCritical)
# undef qCritical
#endif
-#define qCritical if (QLoggingCategories::isEnabled() && !QLoggingCategories::isEnabled(QLoggingCategories::defaultCategory(), QtCriticalMsg)) /*NOP*/;\
- else QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).critical
-
-#define QT_LOG_CATEGORY(categorytype, category) \
- namespace QtLogger { \
- namespace QLoggingCategories \
- { \
- static QLoggingCategory categorytype##_QLoggingCategory(category); \
- } \
+#define qCritical \
+ if (!QLoggingCategory::defaultCategory().isEnabled(QtCriticalMsg)) \
+ /*NOP*/; \
+ else \
+ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).critical
+
+//This marco creates the QLoggingCategory object in an empty namespace
+//to prevent linker problems if someone else uses the categorytype in an other place.
+#define QT_LOG_CATEGORY(categorytype, categoryname) \
+ namespace { \
+ static QLoggingCategory categorytype(categoryname); \
}
-#define qCDebug(category) \
- if (!QLoggingCategories::isEnabled() || !QLoggingCategories::isEnabled(QLoggingCategories::category##_QLoggingCategory, QtDebugMsg)) /*NOP*/; \
- else QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug() << QLoggingCategories::category##_QLoggingCategory._category << ": " \
-
-#define qCWarning(category) \
- if (QLoggingCategories::isEnabled() && !QLoggingCategories::isEnabled(QLoggingCategories::category##_QLoggingCategory, QtWarningMsg)) /*NOP*/; \
- else QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).warning() << QLoggingCategories::category##_QLoggingCategory._category << ": " \
-
-#define qCCritical(category) \
- if (QLoggingCategories::isEnabled() && !QLoggingCategories::isEnabled(QLoggingCategories::category##_QLoggingCategory, QtCriticalMsg)) /*NOP*/; \
- else QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).critical() << QLoggingCategories::category##_QLoggingCategory._category << ": " \
+#define qCDebug(category) \
+ if (!category.isEnabled(QtDebugMsg)) \
+ /*NOP*/; \
+ else \
+ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug() << category.categoryName() << ": "
+
+#define qCWarning(category) \
+ if (!category.isEnabled(QtWarningMsg)) \
+ /*NOP*/; \
+ else \
+ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).warning() << category.categoryName() << ": "
+
+#define qCCritical(category) \
+ if (!category.isEnabled(QtCriticalMsg)) \
+ /*NOP*/; \
+ else \
+ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).critical() << category.categoryName() << ": "
#endif // QLOGGER_H
diff --git a/src/logger/qlogger_p.h b/src/logger/qlogger_p.h
index d7d1b8e..17ffd7f 100644
--- a/src/logger/qlogger_p.h
+++ b/src/logger/qlogger_p.h
@@ -62,7 +62,7 @@ class QLogConfigFilterItem
{
public:
QLogConfigFilterItem(const QString &category, bool active);
- int pass(const QLoggingCategories::QLoggingCategory *log, const QtMsgType &type);
+ int pass(QLoggingCategory *log, const QtMsgType &type);
void parse();
int _type;
QString _category;
@@ -79,13 +79,13 @@ public:
static QString resolveConfigFile(const QString &path);
void setLoggingRulesFile(const QString &path);
void setLoggingRules(const QByteArray &configcontent);
- bool isEnabled(QLoggingCategories::QLoggingCategory &category, QtMsgType type);
- void unregisterCategory(QLoggingCategories::QLoggingCategory &category);
+ bool isEnabled(QLoggingCategory &category, QtMsgType type);
+ void unregisterCategory(QLoggingCategory &category);
Q_INVOKABLE void createFileWatcher();
void readSettings(QIODevice &device);
- void updateCategory(QLoggingCategories::QLoggingCategory *log);
+ void updateCategory(QLoggingCategory *log);
#ifdef QT_BUILD_INTERNAL
Q_SIGNALS:
@@ -97,12 +97,32 @@ public slots:
public:
QFileSystemWatcher *_configFileWatcher;
- QList<QLoggingCategories::QLoggingCategory *> _registeredCategories;
+ QList<QLoggingCategory *> _registeredCategories;
QString _configFile;
- QMutex _mutex;
+ QMutex _mutexRegisteredCategory;
QList<QLogConfigFilterItem> _logConfigItemList;
};
+class QLoggingCategoryPrivate
+{
+public:
+ QLoggingCategoryPrivate(const char *category);
+ virtual ~QLoggingCategoryPrivate();
+ bool statusMessageType(const QtMsgType &type);
+ bool _enabledDebug;
+ bool _enabledWarning;
+ bool _enabledCritical;
+ bool _registered;
+ const char *_categoryName;
+ int _references;
+};
+
+class QLoggingCategoryDefault : public QLoggingCategory
+{
+public:
+ QLoggingCategoryDefault();
+};
+
Q_AUTOTEST_EXPORT QLoggingPrivate *qtLoggerInstance();
diff --git a/tests/auto/logger/logger.pro b/tests/auto/logger/logger.pro
index 4e6b4c7..6a67eb1 100644
--- a/tests/auto/logger/logger.pro
+++ b/tests/auto/logger/logger.pro
@@ -2,6 +2,6 @@ TEMPLATE = app
TARGET = tst_qlogger
CONFIG += testcase
-QT = core testlib logger
+QT = core testlib logger-private
SOURCES += tst_qlogger.cpp
diff --git a/tests/auto/logger/tst_qlogger.cpp b/tests/auto/logger/tst_qlogger.cpp
index 5753818..0bdbb4e 100644
--- a/tests/auto/logger/tst_qlogger.cpp
+++ b/tests/auto/logger/tst_qlogger.cpp
@@ -40,11 +40,13 @@
****************************************************************************/
#include <QtTest/QtTest>
-#include <QtLogger/QtLogger>
-#include <QtTest/QtTest>
#include <QFile>
#include <QMutexLocker>
#include <QtCore/qlogging.h>
+#undef protected
+#define protected public
+#include <QtLogger/QtLogger>
+#include <private/qlogger_p.h>
QT_LOG_CATEGORY(TST_LOG, "tst.log")
QT_LOG_CATEGORY(TST_LOG1, "tst.log1")
@@ -106,11 +108,10 @@ static void myCustomMessageHandler(QtMsgType type, const QMessageLogContext &con
{
QMutexLocker locker(&threadmutex);
logMessage = qMyMessageFormatString(type, context, msg);
-// if (QLoggingCategories::isEnabled() && context.category){
- if (QLoggingCategories::isEnabled()){
+// if (isEnabled() && context.category){
if (multithreadtest)
threadtest.append(logMessage);
- }
+ // }
}
class CfgFile
@@ -219,7 +220,6 @@ inline QString cleanLogLine(QString& qstring)
}
//QTLOGGER_USE_NAMESPACE
-
class tst_QLogger : public QObject
{
Q_OBJECT
@@ -521,6 +521,62 @@ private slots:
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
}
+ void checkLogWithCategoryObject()
+ {
+ _configFile->clear();
+ _configFile->addKey("LoggingCategoryObject", true);
+ QLoggingCategory *pcategorybject = 0;
+ qSetLoggingRules(_configFile->array());
+ {
+ QLoggingCategory mycategoryobject("LoggingCategoryObject");
+ pcategorybject = &mycategoryobject;
+ logMessage = "no change";
+
+ QString buf = QString::fromLatin1("LoggingCategoryObject: debug, My Category Object");
+ qCDebug(mycategoryobject) << "My Category Object";
+ QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
+
+ buf = QString::fromLatin1("LoggingCategoryObject: warning, My Category Object");
+ qCWarning(mycategoryobject) << "My Category Object";
+ QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
+
+ buf = QString::fromLatin1("LoggingCategoryObject: critical, My Category Object");
+ qCCritical(mycategoryobject) << "My Category Object";
+ QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
+
+ QLoggingCategory mycategoryobject2("LoggingCategoryObject");
+ buf = QString::fromLatin1("LoggingCategoryObject: debug, My Category Object");
+ qCDebug(mycategoryobject) << "My Category Object";
+ QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
+
+ buf = QString::fromLatin1("LoggingCategoryObject: warning, My Category Object");
+ qCWarning(mycategoryobject) << "My Category Object";
+ QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
+
+ buf = QString::fromLatin1("LoggingCategoryObject: critical, My Category Object");
+ qCCritical(mycategoryobject) << "My Category Object";
+ QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
+ }
+ //check if mycategoryobject still registered.
+ QLoggingPrivate *logger = qtLoggerInstance();
+ QVERIFY(!logger->_registeredCategories.contains(pcategorybject));
+ }
+
+ void checkEmptyCategoryName()
+ {
+ QLoggingCategory mycategoryobject("");
+
+ logMessage = "no change";
+ QString buf = QString::fromLatin1("no change");
+ qCDebug(mycategoryobject) << "My Category Object";
+ QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
+
+ QLoggingCategory mycategoryobject1(0);
+ buf = QString::fromLatin1("no change");
+ qCDebug(mycategoryobject1) << "My Category Object";
+ QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
+ }
+
void checkMultithreading()
{
multithreadtest = true;