Revert "Add tracing to logging framework"

The tracing API still misses some real-world exposure. Let's
re-do this in dev to have more time.

This reverts parts of following commits:

466e0dff4b
7a47aebe9e
a652bab6a7
8f0654ceb8
4162522edd
32f27b4367
9ff81bdc1a

Change-Id: If97340c37b8b3363f597683336a8390d5ff386f1
Reviewed-by: hjk <hjk121@nokiamail.com>
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
This commit is contained in:
Kai Koehne 2013-11-04 16:12:32 +01:00 committed by The Qt Project
parent 0491a7a298
commit 79b975756a
11 changed files with 9 additions and 644 deletions

View File

@ -1,180 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <QCoreApplication>
#include <QLoggingCategory>
//![1]
QLoggingCategory theFooArea("foo");
QLoggingCategory theBarArea("bar");
QLoggingCategory theBazArea("baz");
//![1]
// Note: These locations are Ubuntu specific.
// Note: To make the example work with user permissions, make sure
// the files are user-writable and the path leading there accessible.
const char traceSwitch[] = "/sys/kernel/debug/tracing/tracing_on";
const char traceSink[] = "/sys/kernel/debug/tracing/trace_marker";
// The base class only serves as a facility to share code
// between the "single line" data logging aspect and the
// scoped "measuring" aspect.
// Both aspects and the base class could be combined into
// a single tracer serving both purposes, but are split
// here for clarity.
// Error handling is left as an exercise.
//![2]
class MyTracerBase : public QTracer
{
public:
MyTracerBase() {
enable = ::open(traceSwitch, O_WRONLY);
marker = ::open(traceSink, O_WRONLY);
}
~MyTracerBase() {
::close(enable);
::close(marker);
}
protected:
int enable;
int marker;
};
//![2]
//![2]
class MyTracer : public MyTracerBase
{
public:
void start() { ::write(marker, "B", 1); }
void end() { ::write(marker, "E", 1); }
};
//![2]
//![3]
class MyDataLogger : public MyTracerBase
{
public:
MyDataLogger() {
buf[0] = 0;
pos = 0;
}
void record(int i) { pos += sprintf(buf + pos, "%d", i); }
void record(const char *msg) { pos += sprintf(buf + pos, "%s", msg); }
void end() { ::write(marker, buf, pos); pos = 0; }
private:
char buf[100];
int pos;
};
//![3]
// Simplest possible example for "measuring".
//![4]
int foo(int i)
{
qCTraceGuard(theFooArea);
// Here could be some lengthy code.
return i * i;
}
//![4]
// We can switch on/off tracing dynamically.
// The tracer will be temporarily switched off at the third call
// and re-enabled at the eighth.
//![5]
int bar(int i)
{
static int n = 0;
++n;
if (n == 3)
theBarArea.setEnabled(QtTraceMsg, false);
if (n == 8)
theBarArea.setEnabled(QtTraceMsg, true);
qCTraceGuard(theBarArea);
return i * i;
}
//![5]
// An example to create "complex" log messages.
//![6]
int baz(int i)
{
qCTrace(theBazArea) << 32 << "some stuff";
return i * i;
}
//![6]
//![7]
namespace {
static struct Init
{
Init() {
tracer.addToCategory(theFooArea);
tracer.addToCategory(theBarArea);
logger.addToCategory(theBazArea);
}
MyTracer tracer;
MyDataLogger logger;
} initializer;
}
//![7]

View File

@ -1,59 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
int foo(int i);
int bar(int i);
int baz(int i);
int main()
{
int s = 0;
for (int i = 0; i != 10; ++i)
s += foo(i);
for (int i = 0; i != 10; ++i)
s += bar(i);
for (int i = 0; i != 10; ++i)
s += baz(i);
return s;
}

View File

@ -1,2 +0,0 @@
SOURCES += ftracer.cpp main.cpp

View File

@ -729,10 +729,6 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
A message generated by the qCritical() function.
\value QtFatalMsg
A message generated by the qFatal() function.
\value QtTraceMsg
Used by the qCTrace() macro. Trace events are usually passed only
to dedicated \a QTracer objects, and do not appear in the installed
message handler.
\value QtSystemMsg

View File

@ -816,7 +816,6 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont
case QtWarningMsg: message.append(QLatin1String("warning")); break;
case QtCriticalMsg:message.append(QLatin1String("critical")); break;
case QtFatalMsg: message.append(QLatin1String("fatal")); break;
case QtTraceMsg: message.append(QLatin1String("trace")); break;
}
} else if (token == fileTokenC) {
if (context.file)
@ -874,7 +873,6 @@ static void android_default_message_handler(QtMsgType type,
{
android_LogPriority priority;
switch (type) {
case QtTraceMsg:
case QtDebugMsg: priority = ANDROID_LOG_DEBUG; break;
case QtWarningMsg: priority = ANDROID_LOG_WARN; break;
case QtCriticalMsg: priority = ANDROID_LOG_ERROR; break;

View File

@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
class QDebug;
class QNoDebug;
enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtTraceMsg, QtSystemMsg = QtCriticalMsg };
enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtSystemMsg = QtCriticalMsg };
class QMessageLogContext
{

View File

@ -75,10 +75,9 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
\l isCriticalEnabled(), \l isTraceEnabled(), as well as \l isEnabled()
to check whether messages for the given message type should be logged.
\note The qCDebug(), qCWarning(), qCCritical(), qCTrace() and
qCTraceGuard() macros prevent arguments from being evaluated if the
respective message types are not enabled for the category, so explicit
checking is not needed:
\note The qCDebug(), qCWarning(), qCCritical() macros prevent arguments
from being evaluated if the respective message types are not enabled for the
category, so explicit checking is not needed:
\snippet qloggingcategory/main.cpp 4
@ -103,14 +102,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
\snippet qloggingcategory/main.cpp 3
*/
typedef QVector<QTracer *> Tracers;
class QLoggingCategoryPrivate
{
public:
Tracers tracers;
};
/*!
Constructs a QLoggingCategory object with the provided \a category name.
The object becomes the local identifier for the category.
@ -118,15 +109,11 @@ public:
If \a category is \c{0}, the category name is changed to \c "default".
*/
QLoggingCategory::QLoggingCategory(const char *category)
: d(new QLoggingCategoryPrivate),
: d(0),
name(0),
enabledDebug(false),
enabledWarning(true),
enabledCritical(true),
enabledTrace(false),
placeholder1(false),
placeholder2(false),
placeholder3(false)
enabledCritical(true)
{
bool isDefaultCategory
= (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0);
@ -151,7 +138,6 @@ QLoggingCategory::~QLoggingCategory()
{
if (QLoggingRegistry *reg = QLoggingRegistry::instance())
reg->unregisterCategory(this);
delete d;
}
/*!
@ -193,18 +179,6 @@ QLoggingCategory::~QLoggingCategory()
expensive generation of data that is only used for debug output.
*/
/*!
\fn bool QLoggingCategory::isTraceEnabled() const
Returns \c true if the tracers associated with this category should
receive messages. Returns \c false otherwise.
\note The \l qCTrace() and \l qCTraceGuard() macros already do this check
before executing any
code. However, calling this method may be useful to avoid
expensive generation of data that is only used for debug output.
*/
/*!
Returns \c true if a message of type \a msgtype for the category should be
shown. Returns \c false otherwise.
@ -215,7 +189,6 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
case QtDebugMsg: return enabledDebug;
case QtWarningMsg: return enabledWarning;
case QtCriticalMsg: return enabledCritical;
case QtTraceMsg: return enabledTrace;
case QtFatalMsg: return true;
}
return false;
@ -237,7 +210,6 @@ void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
case QtDebugMsg: enabledDebug = enable; break;
case QtWarningMsg: enabledWarning = enable; break;
case QtCriticalMsg: enabledCritical = enable; break;
case QtTraceMsg: enabledTrace = enable; break;
case QtFatalMsg: break;
}
}
@ -313,7 +285,7 @@ QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter)
where \c <category> is the name of the category, potentially with \c{*} as a
wildcard symbol at the start and/or the end. The optional \c <type> must
be either \c debug, \c warning, \c critical, or \c trace.
be either \c debug, \c warning, or \c critical.
Example:
@ -394,56 +366,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\sa qCritical()
*/
/*!
\relates QLoggingCategory
\macro qCTrace(category)
\since 5.2
Returns an output stream for trace messages in the logging category
\a category.
The macro expands to code that checks whether
\l QLoggingCategory::isTraceEnabled() evaluates to \c true.
If so, the stream arguments are processed and sent to the \l QTracer objects
registered with the category.
\note Arguments are not processed if trace output for the category is not
enabled, so do not rely on any side effects.
Example:
\snippet qtracer/ftracer.cpp 6
\sa qCTraceGuard() QTraceGuard
*/
/*!
\relates QLoggingCategory
\macro qCTraceGuard(category)
\since 5.2
The macro expands to code that creates a guard object with automatic
storage. The guard constructor checks whether
\l QLoggingCategory::isTraceEnabled() evaluates to \c true.
If so, the stream arguments are processed and the \c{start()}
functions of the \l QTracer objects registered with the \a category are
called.
The guard destructor also checks whether the category is enabled for
tracing and if so, the \c{end()}
functions of the \l QTracer objects registered with the \a category are called.
\note Arguments are always processed, even if trace output for the
category is disabled. They will, however, in that case not be passed
to the \c{record()} functions of the registered tracers.
Example:
\snippet qtracer/ftracer.cpp 4
\sa qCTrace() QTracer
*/
/*!
\macro Q_DECLARE_LOGGING_CATEGORY(name)
\relates QLoggingCategory
@ -469,234 +391,4 @@ void QLoggingCategory::setFilterRules(const QString &rules)
This macro must be used outside of a class or method.
*/
/*!
\class QTracer
\inmodule QtCore
\since 5.2
\brief The QTracer class provides an interface for handling
trace events associated with a logging category.
\c QTracer objects are registered with logging categories.
Multiple \c QTracer objects
can be registered with the same category, and the same
\c QTracer object can be registered with different categories.
If code containing \c qCTrace is executed, and the associated
logging category is enabled for tracing, all \c QTracer objects
that are registered with the category are notified.
\c QTracer objects
*/
/*!
\fn QTracer::QTracer()
Constructs a tracer object.
Example:
\snippet qtracer/ftracer.cpp 2
*/
/*!
\fn QTracer::~QTracer()
Destroys the tracer object.
*/
/*!
Registers this tracer for the \a category.
The tracer will later be notified of messages of type
\c QtTraceMsg, as long as that message type
is enabled in the category.
Example:
\snippet qtracer/ftracer.cpp 1
\codeline
\snippet qtracer/ftracer.cpp 7
*/
void QTracer::addToCategory(QLoggingCategory &category)
{
category.d->tracers.append(this);
}
/*!
\fn void QTracer::start()
This function is invoked when a tracing activity starts,
typically from the constructor of a \c QTraceGuard object
defined by \c qCTrace() or \c qCTraceGuard().
The base implementation does nothing. \c QTracer subclasses
are advised to override it if needed.
\sa qCTrace(), qCTraceGuard()
*/
/*!
\fn void QTracer::end()
This function is invoked when a tracing activity ends,
typically from the destructor of a \c QTraceGuard object
defined by \c qCTrace() or \c qCTraceGuard().
The base implementation does nothing. It is common for
\c QTracer subclasses to override it to perform flushing
of collected data.
\sa qCTrace(), qCTraceGuard()
*/
/*!
\fn void QTracer::record(int data)
This function is invoked during a tracing activity to
pass integer \a data to the \c QTracer object.
Example:
\snippet qtracer/ftracer.cpp 3
*/
/*!
\fn void QTracer::record(const char *data)
This function is invoked during a tracing activity to
pass string \a data to the \c QTracer object.
*/
/*!
\fn void QTracer::record(const QVariant &data)
This function is invoked during a tracing activity to
pass abitrary (non-integer, non-string) \a data to
the \c QTracer object.
*/
/*!
\class QTraceGuard
\since 5.2
\inmodule QtCore
\brief The QTraceGuard class facilitates notifications to
\c QTracer objects.
\c QTraceGuard objects are typically implicitly created on the
stack when using the \c qCTrace or \c qCTraceGuard macros and
are associated to a \c QLoggingCategory.
The constructor of a \c QTraceGuard objects checks whether
its associated category is enabled, and if so, informs all
\c QTracer objects registered with the category that a
tracing activity starts.
The destructor of a \c QTraceGuard objects checks whether
its associated category is enabled, and if so, informs all
\c QTracer objects registered with the category that a
tracing activity ended.
A \c QTraceGuard object created by \c qCTrace will be destroyed
at the end of the full expression, a guard created by
\c qCTraceGuard at the end of the block containing the macro.
During the lifetime of a QTraceGuard object, its \c operator<<()
can be used to pass additional data to the active tracers.
The fast path handles only \c int and \c{const char *} data,
but it is possible to use arbitrary values wrapped in \c QVariants.
\sa QTracer
*/
/*!
\fn QTraceGuard::QTraceGuard(QLoggingCategory &category)
\internal
Constructs a trace guard object relaying to \a category.
*/
/*!
\fn QTraceGuard::~QTraceGuard()
\internal
Destroys the trace guard object.
*/
/*!
\internal
Calls \c start() on all registered tracers.
*/
void QTraceGuard::start()
{
const Tracers &tracers = target->d->tracers;
for (int i = tracers.size(); --i >= 0; )
tracers.at(i)->start();
}
/*!
\internal
Calls \c end() on all registered tracers.
*/
void QTraceGuard::end()
{
const Tracers &tracers = target->d->tracers;
for (int i = tracers.size(); --i >= 0; )
tracers.at(i)->end();
}
/*!
\internal
This function is called for int parameters passed to the
qCTrace stream.
*/
QTraceGuard &QTraceGuard::operator<<(int msg)
{
const Tracers &tracers = target->d->tracers;
for (int i = tracers.size(); --i >= 0; )
tracers.at(i)->record(msg);
return *this;
}
/*!
\internal
This function is called for string parameters passed to the
qCTrace stream.
*/
QTraceGuard &QTraceGuard::operator<<(const char *msg)
{
const Tracers &tracers = target->d->tracers;
for (int i = tracers.size(); --i >= 0; )
tracers.at(i)->record(msg);
return *this;
}
/*!
\internal
This function is called for QVariant parameters passed to the
qCTrace stream.
*/
QTraceGuard &QTraceGuard::operator<<(const QVariant &msg)
{
const Tracers &tracers = target->d->tracers;
for (int i = tracers.size(); --i >= 0; )
tracers.at(i)->record(msg);
return *this;
}
QT_END_NAMESPACE

View File

@ -44,14 +44,9 @@
#include <QtCore/qglobal.h>
#include <QtCore/qdebug.h>
#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
class QTracer;
class QTraceGuard;
class QLoggingCategoryPrivate;
class Q_CORE_EXPORT QLoggingCategory
{
Q_DISABLE_COPY(QLoggingCategory)
@ -65,7 +60,6 @@ public:
bool isDebugEnabled() const { return enabledDebug; }
bool isWarningEnabled() const { return enabledWarning; }
bool isCriticalEnabled() const { return enabledCritical; }
bool isTraceEnabled() const { return enabledTrace; }
const char *categoryName() const { return name; }
@ -80,66 +74,13 @@ public:
static void setFilterRules(const QString &rules);
private:
friend class QLoggingCategoryPrivate;
friend class QLoggingRegistry;
friend class QTraceGuard;
friend class QTracer;
QLoggingCategoryPrivate *d;
void *d; // reserved for future use
const char *name;
bool enabledDebug;
bool enabledWarning;
bool enabledCritical;
bool enabledTrace;
// reserve space for future use
bool placeholder1;
bool placeholder2;
bool placeholder3;
};
class Q_CORE_EXPORT QTracer
{
Q_DISABLE_COPY(QTracer)
public:
QTracer() {}
virtual ~QTracer() {}
void addToCategory(QLoggingCategory &category);
virtual void start() {}
virtual void end() {}
virtual void record(int) {}
virtual void record(const char *) {}
virtual void record(const QVariant &) {}
};
class Q_CORE_EXPORT QTraceGuard
{
Q_DISABLE_COPY(QTraceGuard)
public:
QTraceGuard(QLoggingCategory &category)
{
target = category.isTraceEnabled() ? &category : 0;
if (target)
start();
}
~QTraceGuard()
{
if (target)
end();
}
QTraceGuard &operator<<(int msg);
QTraceGuard &operator<<(const char *msg);
QTraceGuard &operator<<(const QVariant &msg);
private:
void start();
void end();
QLoggingCategory *target;
bool placeholder[5]; // reserve for future use
};
#define Q_DECLARE_LOGGING_CATEGORY(name) \
@ -162,17 +103,6 @@ private:
#define qCCritical(category) \
for (bool enabled = category().isCriticalEnabled(); enabled; enabled = false) \
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical()
#define qCTrace(category) \
for (bool enabled = category.isTraceEnabled(); Q_UNLIKELY(enabled); enabled = false) \
QTraceGuard(category)
#define Q_TRACE_GUARD_NAME_HELPER(line) qTraceGuard ## line
#define Q_TRACE_GUARD_NAME(line) Q_TRACE_GUARD_NAME_HELPER(line)
#define qCTraceGuard(category) \
QTraceGuard Q_TRACE_GUARD_NAME(__LINE__)(category);
#if defined(QT_NO_DEBUG_OUTPUT)
# undef qCDebug

View File

@ -86,9 +86,6 @@ int QLoggingRule::pass(const QString &categoryName, QtMsgType msgType) const
case QtCriticalMsg:
fullCategory += QLatin1String(".critical");
break;
case QtTraceMsg:
fullCategory += QLatin1String(".trace");
break;
default:
break;
}
@ -291,7 +288,6 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
bool debug = (cat->categoryName() == qtDefaultCategoryName);
bool warning = true;
bool critical = true;
bool trace = true;
QString categoryName = QLatin1String(cat->categoryName());
QLoggingRegistry *reg = QLoggingRegistry::instance();
@ -305,15 +301,11 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
filterpass = item.pass(categoryName, QtCriticalMsg);
if (filterpass != 0)
critical = (filterpass > 0);
filterpass = item.pass(categoryName, QtTraceMsg);
if (filterpass != 0)
trace = (filterpass > 0);
}
cat->setEnabled(QtDebugMsg, debug);
cat->setEnabled(QtWarningMsg, warning);
cat->setEnabled(QtCriticalMsg, critical);
cat->setEnabled(QtTraceMsg, trace);
}

View File

@ -257,7 +257,6 @@ namespace QTest {
}
switch (type) {
case QtTraceMsg:
case QtDebugMsg:
QTest::TestLoggers::addMessage(QAbstractTestLogger::QDebug, msg);
break;

View File

@ -69,7 +69,6 @@ QByteArray qMyMessageFormatString(QtMsgType type, const QMessageLogContext &cont
case QtWarningMsg: message.append(".warning"); break;
case QtCriticalMsg:message.append(".critical"); break;
case QtFatalMsg: message.append(".fatal"); break;
case QtTraceMsg: message.append(".trace"); break;
}
message.append(": ");
message.append(qPrintable(str));