From d394ca7f27197cfbfc28eb9a08eb0db261dd9d3d Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 17 Jan 2012 16:20:45 +0100 Subject: QtDebug: Include file, line, function information Record the file, line, and function where a qDebug, qWarning, qCritical or qFatal call happens, and make this information available in a custom message handler. The patch uses the C preprocessor to replace qDebug, qWarning, ... with a line that also records the current file, line, and function. Custom message handlers can access this information via a new QMessageLogContext argument. Change-Id: I0a9b89c1d137e41775932d3b1a35da4ebf12d18d Reviewed-by: David Faure --- src/corelib/global/global.pri | 6 +- src/corelib/global/qglobal.cpp | 205 ++++++++++++++++++++++------ src/corelib/global/qglobal.h | 62 +-------- src/corelib/global/qlogging.cpp | 76 +++++++++++ src/corelib/global/qlogging.h | 161 ++++++++++++++++++++++ src/corelib/io/qdebug.h | 27 +--- src/corelib/kernel/qcoreapplication_win.cpp | 4 + src/tools/bootstrap/bootstrap.pro | 1 + 8 files changed, 418 insertions(+), 124 deletions(-) create mode 100644 src/corelib/global/qlogging.cpp create mode 100644 src/corelib/global/qlogging.h (limited to 'src') diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 027542c6ea..fca9969db0 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -5,13 +5,15 @@ HEADERS += \ global/qnamespace.h \ global/qendian.h \ global/qnumeric_p.h \ - global/qnumeric.h + global/qnumeric.h \ + global/qlogging.h SOURCES += \ global/qglobal.cpp \ global/qlibraryinfo.cpp \ global/qmalloc.cpp \ - global/qnumeric.cpp + global/qnumeric.cpp \ + global/qlogging.cpp # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 75bc1ec06f..01b3e2ec32 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -47,6 +47,7 @@ #include "qdir.h" #include "qstringlist.h" #include "qdatetime.h" +#include "qdebug.h" #ifndef QT_NO_QOBJECT #include @@ -442,8 +443,12 @@ QT_BEGIN_NAMESPACE Finally, the QtMsgType definition identifies the various messages that can be generated and sent to a Qt message handler; - QtMsgHandler is a type definition for a pointer to a function with - the signature \c {void myMsgHandler(QtMsgType, const char *)}. + QMessageHandler is a type definition for a pointer to a function with + the signature + \c {void myMessageHandler(QtMsgType, const QMessageLogContext &, const char *)}. + QMessageLogContext class contains the line, file, and function the + message was logged at. This information is created by the QMessageLogger + class. \section1 Functions @@ -473,8 +478,8 @@ QT_BEGIN_NAMESPACE The remaining functions are qRound() and qRound64(), which both accept a \l qreal value as their argument returning the value rounded up to the nearest integer and 64-bit integer respectively, - the qInstallMsgHandler() function which installs the given - QtMsgHandler, and the qVersion() function which returns the + the qInstallMessageHandler() function which installs the given + QMessageHandler, and the qVersion() function which returns the version number of Qt at run-time as a string. \section1 Macros @@ -675,15 +680,31 @@ QT_BEGIN_NAMESPACE /*! \typedef QtMsgHandler \relates + \deprecated This is a typedef for a pointer to a function with the following signature: \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 7 - \sa QtMsgType, qInstallMsgHandler() + This typedef is deprecated, you should use QMessageHandler instead. + \sa QtMsgType, QMessageHandler, qInstallMsgHandler(), qInstallMessageHandler() */ +/*! + \typedef QMessageHandler + \relates + \since 5.0 + + This is a typedef for a pointer to a function with the following + signature: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 49 + + \sa QtMsgType, qInstallMessageHandler() +*/ + + /*! \enum QtMsgType \relates @@ -704,7 +725,7 @@ QT_BEGIN_NAMESPACE \value QtSystemMsg - \sa QtMsgHandler, qInstallMsgHandler() + \sa QMessageHandler, qInstallMessageHandler() */ /*! \typedef QFunctionPointer @@ -1705,7 +1726,8 @@ Q_CORE_EXPORT unsigned int qt_int_sqrt(unsigned int n) void *qMemCopy(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); } void *qMemSet(void *dest, int c, size_t n) { return memset(dest, c, n); } -static QtMsgHandler handler = 0; // pointer to debug handler +static QtMsgHandler msgHandler = 0; // pointer to debug handler (without context) +static QMessageHandler messageHandler = 0; // pointer to debug handler (with context) #if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \ defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L @@ -1786,10 +1808,22 @@ QString qt_error_string(int errorCode) return ret.trimmed(); } - /*! \fn QtMsgHandler qInstallMsgHandler(QtMsgHandler handler) \relates + \deprecated + + Installs a Qt message \a handler which has been defined + previously. This method is deprecated, use qInstallMessageHandler + instead. + + \sa QtMsgHandler, qInstallMessageHandler +*/ + +/*! + \fn QMessageHandler qInstallMessageHandler(QMessageHandler handler) + \relates + \since 5.0 Installs a Qt message \a handler which has been defined previously. Returns a pointer to the previous message handler @@ -1811,7 +1845,7 @@ QString qt_error_string(int errorCode) Only one message handler can be defined, since this is usually done on an application-wide basis to control debug output. - To restore the message handler, call \c qInstallMsgHandler(0). + To restore the message handler, call \c qInstallMessageHandler(0). Example: @@ -1820,9 +1854,12 @@ QString qt_error_string(int errorCode) \sa qDebug(), qWarning(), qCritical(), qFatal(), QtMsgType, {Debugging Techniques} */ + #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) extern bool usingWinMain; -extern Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str); +extern Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char *str); +extern Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &context, + const char *str); #endif /*! @@ -1840,17 +1877,38 @@ static void qDefaultMsgHandler(QtMsgType, const char *buf) #endif } +/*! + \internal +*/ +static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &, const char *buf) +{ + qDefaultMsgHandler(type, buf); +} + +QMessageHandler qInstallMessageHandler(QMessageHandler h) +{ + if (!messageHandler) + messageHandler = qDefaultMessageHandler; + QMessageHandler old = messageHandler; + messageHandler = h; +#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) + if (!messageHandler && usingWinMain) + messageHandler = qWinMessageHandler; +#endif + return old; +} + QtMsgHandler qInstallMsgHandler(QtMsgHandler h) { //if handler is 0, set it to the //default message handler - if (!handler) - handler = qDefaultMsgHandler; - QtMsgHandler old = handler; - handler = h; + if (!msgHandler) + msgHandler = qDefaultMsgHandler; + QtMsgHandler old = msgHandler; + msgHandler = h; #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) - if (!handler && usingWinMain) - handler = qWinMsgHandler; + if (!msgHandler && usingWinMain) + msgHandler = qWinMsgHandler; #endif return old; } @@ -1858,11 +1916,20 @@ QtMsgHandler qInstallMsgHandler(QtMsgHandler h) /*! \internal */ -void qt_message_output(QtMsgType msgType, const char *buf) +void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const char *buf) { - if (!handler) - handler = qDefaultMsgHandler; - (*handler)(msgType, buf); + if (!msgHandler) + msgHandler = qDefaultMsgHandler; + if (!messageHandler) + messageHandler = qDefaultMessageHandler; + + // prefer new message handler over the old one + if (msgHandler == qDefaultMsgHandler + || messageHandler != qDefaultMessageHandler) { + (*messageHandler)(msgType, context, buf); + } else { + (*msgHandler)(msgType, buf); + } if (msgType == QtFatalMsg || (msgType == QtWarningMsg @@ -1904,14 +1971,15 @@ static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) emergency_buf[255] = '\0'; if (msg) qvsnprintf(emergency_buf, 255, msg, ap); - qt_message_output(msgType, emergency_buf); + QMessageLogContext context; + qt_message_output(msgType, context, emergency_buf); } #endif /*! \internal */ -static void qt_message(QtMsgType msgType, const char *msg, va_list ap) +static void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg, va_list ap) { #if !defined(QT_NO_EXCEPTIONS) if (std::uncaught_exception()) { @@ -1931,11 +1999,12 @@ static void qt_message(QtMsgType msgType, const char *msg, va_list ap) #endif } } - qt_message_output(msgType, buf.constData()); + qt_message_output(msgType, context, buf.constData()); } #undef qDebug /*! + \fn qDebug(const char *message, ...) \relates Calls the message handler with the debug message \a msg. If no @@ -1964,21 +2033,42 @@ static void qt_message(QtMsgType msgType, const char *msg, va_list ap) the end. It supports many C++ and Qt types. To suppress the output at run-time, install your own message handler - with qInstallMsgHandler(). + with qInstallMessageHandler(). - \sa qWarning(), qCritical(), qFatal(), qInstallMsgHandler(), + \sa qWarning(), qCritical(), qFatal(), qInstallMessageHandler(), {Debugging Techniques} */ -void qDebug(const char *msg, ...) + +void QMessageLogger::debug(const char *msg, ...) { va_list ap; va_start(ap, msg); // use variable arg list - qt_message(QtDebugMsg, msg, ap); + qt_message(QtDebugMsg, context, msg, ap); va_end(ap); } +#ifndef QT_NO_DEBUG_STREAM + +QDebug QMessageLogger::debug() +{ + QDebug dbg = QDebug(QtDebugMsg); + QMessageLogContext &ctxt = dbg.stream->context; + ctxt.file = context.file; + ctxt.line = context.line; + ctxt.function = context.function; + return dbg; +} + +QNoDebug QMessageLogger::noDebug() +{ + return QNoDebug(); +} + +#endif + #undef qWarning /*! + \fn qWarning(const char *message, ...) \relates Calls the message handler with the warning message \a msg. If no @@ -2004,20 +2094,35 @@ void qDebug(const char *msg, ...) appends a newline at the end. To suppress the output at runtime, install your own message handler - with qInstallMsgHandler(). + with qInstallMessageHandler(). - \sa qDebug(), qCritical(), qFatal(), qInstallMsgHandler(), + \sa qDebug(), qCritical(), qFatal(), qInstallMessageHandler(), {Debugging Techniques} */ -void qWarning(const char *msg, ...) + +void QMessageLogger::warning(const char *msg, ...) { va_list ap; va_start(ap, msg); // use variable arg list - qt_message(QtWarningMsg, msg, ap); + qt_message(QtWarningMsg, context, msg, ap); va_end(ap); } +#ifndef QT_NO_DEBUG_STREAM +QDebug QMessageLogger::warning() +{ + QDebug dbg = QDebug(QtWarningMsg); + QMessageLogContext &ctxt = dbg.stream->context; + ctxt.file = context.file; + ctxt.line = context.line; + ctxt.function = context.function; + return dbg; +} +#endif + +#undef qCritical /*! + \fn qCritical(const char *message, ...) \relates Calls the message handler with the critical message \a msg. If no @@ -2040,19 +2145,32 @@ void qWarning(const char *msg, ...) appended at the end. To suppress the output at runtime, install your own message handler - with qInstallMsgHandler(). + with qInstallMessageHandler(). - \sa qDebug(), qWarning(), qFatal(), qInstallMsgHandler(), + \sa qDebug(), qWarning(), qFatal(), qInstallMessageHandler(), {Debugging Techniques} */ -void qCritical(const char *msg, ...) + +void QMessageLogger::critical(const char *msg, ...) { va_list ap; va_start(ap, msg); // use variable arg list - qt_message(QtCriticalMsg, msg, ap); + qt_message(QtCriticalMsg, context, msg, ap); va_end(ap); } +#ifndef QT_NO_DEBUG_STREAM +QDebug QMessageLogger::critical() +{ + QDebug dbg = QDebug(QtCriticalMsg); + QMessageLogContext &ctxt = dbg.stream->context; + ctxt.file = context.file; + ctxt.line = context.line; + ctxt.function = context.function; + return dbg; +} +#endif + void qErrnoWarning(const char *msg, ...) { // qt_error_string() will allocate anyway, so we don't have @@ -2064,7 +2182,8 @@ void qErrnoWarning(const char *msg, ...) buf.vsprintf(msg, ap); va_end(ap); - qCritical("%s (%s)", buf.toLocal8Bit().constData(), qt_error_string(-1).toLocal8Bit().constData()); + QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(), + qt_error_string(-1).toLocal8Bit().constData()); } void qErrnoWarning(int code, const char *msg, ...) @@ -2078,10 +2197,13 @@ void qErrnoWarning(int code, const char *msg, ...) buf.vsprintf(msg, ap); va_end(ap); - qCritical("%s (%s)", buf.toLocal8Bit().constData(), qt_error_string(code).toLocal8Bit().constData()); + QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(), + qt_error_string(code).toLocal8Bit().constData()); } +#undef qFatal /*! + \fn qFatal(const char *message, ...) \relates Calls the message handler with the fatal message \a msg. If no @@ -2100,16 +2222,17 @@ void qErrnoWarning(int code, const char *msg, ...) \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 30 To suppress the output at runtime, install your own message handler - with qInstallMsgHandler(). + with qInstallMessageHandler(). - \sa qDebug(), qCritical(), qWarning(), qInstallMsgHandler(), + \sa qDebug(), qCritical(), qWarning(), qInstallMessageHandler(), {Debugging Techniques} */ -void qFatal(const char *msg, ...) + +void QMessageLogger::fatal(const char *msg, ...) { va_list ap; va_start(ap, msg); // use variable arg list - qt_message(QtFatalMsg, msg, ap); + qt_message(QtFatalMsg, context, msg, ap); va_end(ap); } diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 2e6f6c32a8..681cd55bb0 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1637,65 +1637,12 @@ inline void qUnused(T &x) { (void)x; } # define qPrintable(string) QString(string).toLocal8Bit().constData() #endif -Q_CORE_EXPORT void qDebug(const char *, ...) /* print debug message */ -#if defined(Q_CC_GNU) && !defined(__INSURE__) - __attribute__ ((format (printf, 1, 2))) -#endif -; - -Q_CORE_EXPORT void qWarning(const char *, ...) /* print warning message */ -#if defined(Q_CC_GNU) && !defined(__INSURE__) - __attribute__ ((format (printf, 1, 2))) -#endif -; - class QString; Q_CORE_EXPORT QString qt_error_string(int errorCode = -1); -Q_CORE_EXPORT void qCritical(const char *, ...) /* print critical message */ -#if defined(Q_CC_GNU) && !defined(__INSURE__) - __attribute__ ((format (printf, 1, 2))) -#endif -; -Q_CORE_EXPORT void qFatal(const char *, ...) /* print fatal message and exit */ -#if defined(Q_CC_GNU) && !defined(__INSURE__) - __attribute__ ((format (printf, 1, 2))) -#endif -; Q_CORE_EXPORT void qErrnoWarning(int code, const char *msg, ...); Q_CORE_EXPORT void qErrnoWarning(const char *msg, ...); -/* - Forward declarations only. - - In order to use the qDebug() stream, you must #include -*/ -class QDebug; -class QNoDebug; -#if !defined(QT_NO_DEBUG_OUTPUT) && !defined(QT_NO_DEBUG_STREAM) -Q_CORE_EXPORT_INLINE QDebug qDebug(); -#else -inline QNoDebug qDebug(); -#endif -#if !defined(QT_NO_WARNING_OUTPUT) && !defined(QT_NO_DEBUG_STREAM) -Q_CORE_EXPORT_INLINE QDebug qWarning(); -#else -inline QNoDebug qWarning(); -#endif -#if !defined(QT_NO_DEBUG_STREAM) -Q_CORE_EXPORT_INLINE QDebug qCritical(); -#endif - -#define QT_NO_QDEBUG_MACRO while (false) qDebug -#ifdef QT_NO_DEBUG_OUTPUT -# define qDebug QT_NO_QDEBUG_MACRO -#endif -#define QT_NO_QWARNING_MACRO while (false) qWarning -#ifdef QT_NO_WARNING_OUTPUT -# define qWarning QT_NO_QWARNING_MACRO -#endif - - Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line); #if !defined(Q_ASSERT) @@ -1774,12 +1721,6 @@ inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; } # endif #endif -enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtSystemMsg = QtCriticalMsg }; - -Q_CORE_EXPORT void qt_message_output(QtMsgType, const char *buf); - -typedef void (*QtMsgHandler)(QtMsgType, const char *); -Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler); typedef void (*QFunctionPointer)(); @@ -2499,6 +2440,9 @@ template struct QEnableIf { typedef T Type; }; QT_END_NAMESPACE QT_END_HEADER +// qDebug and friends +#include "qlogging.h" + #endif /* __cplusplus */ #endif /* QGLOBAL_H */ diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp new file mode 100644 index 0000000000..bc26c9b6b7 --- /dev/null +++ b/src/corelib/global/qlogging.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QMessageLogContext + \relates + \brief The QMessageLogContext class provides additional information about a log message. + \since 5.0 + + The class provides information about the source code location a qDebug(), qWarning(), + qCritical() or qFatal() message was generated. + + \sa QMessageLogger, QMessageHandler, qInstallMessageHandler() +*/ + +/*! + \class QMessageLogger + \relates + \brief The QMessageLogger class generates log messages. + \since 5.0 + + QMessageLogger is used to generate messages for the Qt logging framework. Most of the time + is transparently used through the qDebug(), qWarning(), qCritical, or qFatal() functions, + which are actually macros that expand to QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug() + et al. + + One example of direct use is to forward errors that stem from a scripting language, e.g. QML: + + \snippet doc/src/snippets/code/qlogging/qlogging.cpp 1 + + \sa QMessageLogContext, qDebug(), qWarning(), qCritical(), qFatal() +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h new file mode 100644 index 0000000000..c6edc7bc48 --- /dev/null +++ b/src/corelib/global/qlogging.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifndef QLOGGING_H +#define QLOGGING_H + +#if 0 +// header is automatically included in qglobal.h +#pragma qt_no_master_include +#endif + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +/* + Forward declarations only. + + In order to use the qDebug() stream, you must #include +*/ +class QDebug; +class QNoDebug; + +enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtSystemMsg = QtCriticalMsg }; + +class QMessageLogContext +{ + Q_DISABLE_COPY(QMessageLogContext) +public: + QMessageLogContext() : version(1), line(0), file(0), function(0) {} + Q_DECL_CONSTEXPR QMessageLogContext(const char *file, int line, const char *function) + : version(1), line(line), file(file), function(function) {} + + int version; + int line; + const char *file; + const char *function; + +private: + friend class QMessageLogger; + friend class QDebug; +}; + +class Q_CORE_EXPORT QMessageLogger +{ + Q_DISABLE_COPY(QMessageLogger) +public: + QMessageLogger() : context() {} + Q_DECL_CONSTEXPR QMessageLogger(const char *file, int line, const char *function) + : context(file, line, function) {} + + void debug(const char *msg, ...) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#endif + ; + void noDebug(const char *, ...) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#endif + {} + void warning(const char *msg, ...) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#endif + ; + void critical(const char *msg, ...) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#endif + ; + void fatal(const char *msg, ...) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#endif + ; + +#ifndef QT_NO_DEBUG_STREAM + QDebug debug(); + QDebug warning(); + QDebug critical(); + + QNoDebug noDebug(); +#endif // QT_NO_DEBUG_STREAM + +private: + QMessageLogContext context; +}; + +Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &context, const char *buf); + +/* + qDebug, qWarning, qCritical, qFatal are redefined to automatically include context information + */ +#define qDebug QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug +#define qWarning QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).warning +#define qCritical QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).critical +#define qFatal QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).fatal + +#define QT_NO_QDEBUG_MACRO while (false) QMessageLogger().noDebug +#define QT_NO_QWARNING_MACRO while (false) QMessageLogger().noDebug + +#ifdef QT_NO_DEBUG_OUTPUT +# undef qDebug +# define qDebug QT_NO_QDEBUG_MACRO +#endif +#ifdef QT_NO_WARNING_OUTPUT +# undef qWarning +# define qWarning QT_NO_QWARNING_MACRO +#endif + +// deprecated. Use qInstallMessageHandler instead! +typedef void (*QtMsgHandler)(QtMsgType, const char *); +Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler); + +typedef void (*QMessageHandler)(QtMsgType, const QMessageLogContext &, const char *); +Q_CORE_EXPORT QMessageHandler qInstallMessageHandler(QMessageHandler); + +QT_END_HEADER +QT_END_NAMESPACE + +#endif // QLOGGING_H diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 5c38fcfbbb..c268660573 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE class Q_CORE_EXPORT QDebug { + friend class QMessageLogger; struct Stream { Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg), space(true), message_output(false) {} Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg), space(true), message_output(false) {} @@ -70,6 +71,7 @@ class Q_CORE_EXPORT QDebug QtMsgType type; bool space; bool message_output; + QMessageLogContext context; } *stream; public: inline QDebug(QIODevice *device) : stream(new Stream(device)) {} @@ -81,7 +83,9 @@ public: if (!--stream->ref) { if(stream->message_output) { QT_TRY { - qt_message_output(stream->type, stream->buffer.toLocal8Bit().data()); + qt_message_output(stream->type, + stream->context, + stream->buffer.toLocal8Bit().data()); } QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ } } delete stream; @@ -269,27 +273,6 @@ inline QDebug operator<<(QDebug debug, const QFlags &flags) return debug.space(); } -#if !defined(QT_NO_DEBUG_OUTPUT) && !defined(QT_NO_DEBUG_STREAM) -Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } -#else -#undef qDebug -inline QNoDebug qDebug() { return QNoDebug(); } -#define qDebug QT_NO_QDEBUG_MACRO -#endif - -#if !defined(QT_NO_WARNING_OUTPUT) && !defined(QT_NO_DEBUG_STREAM) -Q_CORE_EXPORT_INLINE QDebug qWarning() { return QDebug(QtWarningMsg); } -#else -#undef qWarning -inline QNoDebug qWarning() { return QNoDebug(); } -#define qWarning QT_NO_QWARNING_MACRO -#endif - -#if !defined(QT_NO_DEBUG_STREAM) -Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); } -#endif - - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 137f8baf5e..e087174d8b 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -161,6 +161,10 @@ Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str) staticCriticalSection.unlock(); } +Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &, const char* str) +{ + qWinMsgHandler(t, str); +} /***************************************************************************** qWinMain() - Initializes Windows. Called from WinMain() in qtmain_win.cpp diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index b5869d826c..fdf41c55c2 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -51,6 +51,7 @@ SOURCES += \ ../../corelib/codecs/qtextcodec.cpp \ ../../corelib/codecs/qutfcodec.cpp \ ../../corelib/global/qglobal.cpp \ + ../../corelib/global/qlogging.cpp \ ../../corelib/global/qmalloc.cpp \ ../../corelib/global/qnumeric.cpp \ ../../corelib/io/qabstractfileengine.cpp \ -- cgit v1.2.3