diff options
author | Kai Koehne <kai.koehne@nokia.com> | 2012-02-10 15:54:50 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-13 12:02:11 +0100 |
commit | 23688d8942895507f4bc1517dd3c161134f4f9d0 (patch) | |
tree | 72832472d5a4cda9782d730429e4c45541d0c4c8 /src/corelib/global/qlogging.cpp | |
parent | d4441b014803e782abcd9ab598df5035f0ff58ed (diff) |
Reshuffle code between qglobal, qlogging
Make the content of the .h, .cpp files match.
Change-Id: Ib2506aeff74281ec4bcbf04d21da451038391203
Reviewed-by: David Faure <faure@kde.org>
Diffstat (limited to 'src/corelib/global/qlogging.cpp')
-rw-r--r-- | src/corelib/global/qlogging.cpp | 465 |
1 files changed, 464 insertions, 1 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 164b846074..8a75f5a9ea 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -44,6 +44,7 @@ #include "qbytearray.h" #include "qstring.h" #include "qvarlengtharray.h" +#include "qdebug.h" #include <stdio.h> @@ -79,6 +80,254 @@ QT_BEGIN_NAMESPACE \sa QMessageLogContext, qDebug(), qWarning(), qCritical(), qFatal() */ +#if !defined(QT_NO_EXCEPTIONS) +/*! + \internal + Uses a local buffer to output the message. Not locale safe + cuts off + everything after character 255, but will work in out of memory situations. +*/ +static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) +{ + char emergency_buf[256] = { '\0' }; + emergency_buf[255] = '\0'; + if (msg) + qvsnprintf(emergency_buf, 255, msg, ap); + QMessageLogContext context; + qt_message_output(msgType, context, emergency_buf); +} +#endif + +/*! + \internal +*/ +static void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg, + va_list ap) +{ +#if !defined(QT_NO_EXCEPTIONS) + if (std::uncaught_exception()) { + qEmergencyOut(msgType, msg, ap); + return; + } +#endif + QByteArray buf; + if (msg) { + QT_TRY { + buf = QString().vsprintf(msg, ap).toLocal8Bit(); + } QT_CATCH(const std::bad_alloc &) { +#if !defined(QT_NO_EXCEPTIONS) + qEmergencyOut(msgType, msg, ap); + // don't rethrow - we use qWarning and friends in destructors. + return; +#endif + } + } + qt_message_output(msgType, context, buf.constData()); +} + +#undef qDebug +/*! + \fn qDebug(const char *message, ...) + \relates <QtGlobal> + + Calls the message handler with the debug message \a msg. If no + message handler has been installed, the message is printed to + stderr. Under Windows, the message is sent to the console, if it is a + console application; otherwise, it is sent to the debugger. This + function does nothing if \c QT_NO_DEBUG_OUTPUT was defined + during compilation. + + If you pass the function a format string and a list of arguments, + it works in similar way to the C printf() function. The format + should be a Latin-1 string. + + Example: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 24 + + If you include \c <QtDebug>, a more convenient syntax is also + available: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 25 + + With this syntax, the function returns a QDebug object that is + configured to use the QtDebugMsg message type. It automatically + puts a single space between each item, and outputs a newline at + the end. It supports many C++ and Qt types. + + To suppress the output at run-time, install your own message handler + with qInstallMessageHandler(). + + \sa qWarning(), qCritical(), qFatal(), qInstallMessageHandler(), + {Debugging Techniques} +*/ + +void QMessageLogger::debug(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); // use variable arg list + 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 <QtGlobal> + + Calls the message handler with the warning message \a msg. If no + message handler has been installed, the message is printed to + stderr. Under Windows, the message is sent to the debugger. This + function does nothing if \c QT_NO_WARNING_OUTPUT was defined + during compilation; it exits if the environment variable \c + QT_FATAL_WARNINGS is defined. + + This function takes a format string and a list of arguments, + similar to the C printf() function. The format should be a Latin-1 + string. + + Example: + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 26 + + If you include <QtDebug>, a more convenient syntax is + also available: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 27 + + This syntax inserts a space between each item, and + appends a newline at the end. + + To suppress the output at runtime, install your own message handler + with qInstallMessageHandler(). + + \sa qDebug(), qCritical(), qFatal(), qInstallMessageHandler(), + {Debugging Techniques} +*/ + +void QMessageLogger::warning(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); // use variable arg list + 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 <QtGlobal> + + Calls the message handler with the critical message \a msg. If no + message handler has been installed, the message is printed to + stderr. Under Windows, the message is sent to the debugger. + + This function takes a format string and a list of arguments, + similar to the C printf() function. The format should be a Latin-1 + string. + + Example: + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 28 + + If you include <QtDebug>, a more convenient syntax is + also available: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 29 + + A space is inserted between the items, and a newline is + appended at the end. + + To suppress the output at runtime, install your own message handler + with qInstallMessageHandler(). + + \sa qDebug(), qWarning(), qFatal(), qInstallMessageHandler(), + {Debugging Techniques} +*/ + +void QMessageLogger::critical(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); // use variable arg list + 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 + +#undef qFatal +/*! + \fn qFatal(const char *message, ...) + \relates <QtGlobal> + + Calls the message handler with the fatal message \a msg. If no + message handler has been installed, the message is printed to + stderr. Under Windows, the message is sent to the debugger. + + If you are using the \bold{default message handler} this function will + abort on Unix systems to create a core dump. On Windows, for debug builds, + this function will report a _CRT_ERROR enabling you to connect a debugger + to the application. + + This function takes a format string and a list of arguments, + similar to the C printf() function. + + Example: + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 30 + + To suppress the output at runtime, install your own message handler + with qInstallMessageHandler(). + + \sa qDebug(), qCritical(), qWarning(), qInstallMessageHandler(), + {Debugging Techniques} +*/ + +void QMessageLogger::fatal(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); // use variable arg list + qt_message(QtFatalMsg, context, msg, ap); + va_end(ap); +} + /*! \internal */ @@ -345,7 +594,7 @@ Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern) \internal */ Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, const QMessageLogContext &context, - const char *str) + const char *str) { QByteArray message; @@ -389,4 +638,218 @@ Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, const QMessageLogC return message; } +static QtMsgHandler msgHandler = 0; // pointer to debug handler (without context) +static QMessageHandler messageHandler = 0; // pointer to debug handler (with context) + +/*! + \internal +*/ +static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, + const char *buf) +{ + QByteArray logMessage = qMessageFormatString(type, context, buf); +#if defined(Q_OS_WINCE) + QString fstr = QString::fromLocal8Bit(logMessage); + OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16())); +#else + fprintf(stderr, "%s", logMessage.constData()); + fflush(stderr); +#endif +} + +/*! + \internal +*/ +static void qDefaultMsgHandler(QtMsgType type, const char *buf) +{ + QMessageLogContext emptyContext; + qDefaultMessageHandler(type, emptyContext, buf); +} + +/*! + \internal +*/ +void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const char *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 + && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) { + +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); +#if !defined(Q_OS_WINCE) + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, buf); +#else + int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__), + __LINE__, _CRT_WIDE(QT_VERSION_STR), + reinterpret_cast<const wchar_t *> ( + QString::fromLatin1(buf).utf16())); +#endif + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW)) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } +} + +void qErrnoWarning(const char *msg, ...) +{ + // qt_error_string() will allocate anyway, so we don't have + // to be careful here (like we do in plain qWarning()) + QString buf; + va_list ap; + va_start(ap, msg); + if (msg) + buf.vsprintf(msg, ap); + va_end(ap); + + QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(), + qt_error_string(-1).toLocal8Bit().constData()); +} + +void qErrnoWarning(int code, const char *msg, ...) +{ + // qt_error_string() will allocate anyway, so we don't have + // to be careful here (like we do in plain qWarning()) + QString buf; + va_list ap; + va_start(ap, msg); + if (msg) + buf.vsprintf(msg, ap); + va_end(ap); + + QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(), + qt_error_string(code).toLocal8Bit().constData()); +} + +#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 qWinMessageHandler(QtMsgType t, const QMessageLogContext &context, + const char *str); +#endif + +/*! + \typedef QtMsgHandler + \relates <QtGlobal> + \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 + + This typedef is deprecated, you should use QMessageHandler instead. + \sa QtMsgType, QMessageHandler, qInstallMsgHandler(), qInstallMessageHandler() +*/ + +/*! + \typedef QMessageHandler + \relates <QtGlobal> + \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() +*/ + +/*! + \fn QMessageHandler qInstallMessageHandler(QMessageHandler handler) + \relates <QtGlobal> + \since 5.0 + + Installs a Qt message \a handler which has been defined + previously. Returns a pointer to the previous message handler + (which may be 0). + + The message handler is a function that prints out debug messages, + warnings, critical and fatal error messages. The Qt library (debug + mode) contains hundreds of warning messages that are printed + when internal errors (usually invalid function arguments) + occur. Qt built in release mode also contains such warnings unless + QT_NO_WARNING_OUTPUT and/or QT_NO_DEBUG_OUTPUT have been set during + compilation. If you implement your own message handler, you get total + control of these messages. + + The default message handler prints the message to the standard + output under X11 or to the debugger under Windows. If it is a + fatal message, the application aborts immediately. + + 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 qInstallMessageHandler(0). + + Example: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 23 + + \sa qDebug(), qWarning(), qCritical(), qFatal(), QtMsgType, + {Debugging Techniques} +*/ + +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; +} + +/*! + \fn QtMsgHandler qInstallMsgHandler(QtMsgHandler handler) + \relates <QtGlobal> + \deprecated + + Installs a Qt message \a handler which has been defined + previously. This method is deprecated, use qInstallMessageHandler + instead. + \sa QtMsgHandler, qInstallMessageHandler +*/ + +QtMsgHandler qInstallMsgHandler(QtMsgHandler h) +{ + //if handler is 0, set it to the + //default message handler + if (!msgHandler) + msgHandler = qDefaultMsgHandler; + QtMsgHandler old = msgHandler; + msgHandler = h; +#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) + if (!msgHandler && usingWinMain) + msgHandler = qWinMsgHandler; +#endif + return old; +} + QT_END_NAMESPACE |