Line data Source code
1 : /****************************************************************************
2 : **
3 : ** Copyright (C) 2016 The Qt Company Ltd.
4 : ** Copyright (C) 2016 Intel Corporation.
5 : ** Contact: https://www.qt.io/licensing/
6 : **
7 : ** This file is part of the QtCore module of the Qt Toolkit.
8 : **
9 : ** $QT_BEGIN_LICENSE:LGPL$
10 : ** Commercial License Usage
11 : ** Licensees holding valid commercial Qt licenses may use this file in
12 : ** accordance with the commercial license agreement provided with the
13 : ** Software or, alternatively, in accordance with the terms contained in
14 : ** a written agreement between you and The Qt Company. For licensing terms
15 : ** and conditions see https://www.qt.io/terms-conditions. For further
16 : ** information use the contact form at https://www.qt.io/contact-us.
17 : **
18 : ** GNU Lesser General Public License Usage
19 : ** Alternatively, this file may be used under the terms of the GNU Lesser
20 : ** General Public License version 3 as published by the Free Software
21 : ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 : ** packaging of this file. Please review the following information to
23 : ** ensure the GNU Lesser General Public License version 3 requirements
24 : ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 : **
26 : ** GNU General Public License Usage
27 : ** Alternatively, this file may be used under the terms of the GNU
28 : ** General Public License version 2.0 or (at your option) the GNU General
29 : ** Public license version 3 or any later version approved by the KDE Free
30 : ** Qt Foundation. The licenses are as published by the Free Software
31 : ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 : ** included in the packaging of this file. Please review the following
33 : ** information to ensure the GNU General Public License requirements will
34 : ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 : ** https://www.gnu.org/licenses/gpl-3.0.html.
36 : **
37 : ** $QT_END_LICENSE$
38 : **
39 : ****************************************************************************/
40 :
41 : #ifndef QDEBUG_H
42 : #define QDEBUG_H
43 :
44 : #include <QtCore/qalgorithms.h>
45 : #include <QtCore/qhash.h>
46 : #include <QtCore/qlist.h>
47 : #include <QtCore/qmap.h>
48 : #include <QtCore/qpair.h>
49 : #include <QtCore/qtextstream.h>
50 : #include <QtCore/qstring.h>
51 : #include <QtCore/qvector.h>
52 : #include <QtCore/qset.h>
53 : #include <QtCore/qcontiguouscache.h>
54 : #include <QtCore/qsharedpointer.h>
55 :
56 : // all these have already been included by various headers above, but don't rely on indirect includes:
57 : #include <vector>
58 : #include <list>
59 : #include <map>
60 : #include <utility>
61 :
62 : QT_BEGIN_NAMESPACE
63 :
64 :
65 : class Q_CORE_EXPORT QDebug
66 : {
67 : friend class QMessageLogger;
68 : friend class QDebugStateSaverPrivate;
69 : struct Stream {
70 : enum { DefaultVerbosity = 2, VerbosityShift = 29, VerbosityMask = 0x7 };
71 :
72 : Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg),
73 : space(true), message_output(false), flags(DefaultVerbosity << VerbosityShift) {}
74 : Stream(QString *string) : ts(string, QIODevice::WriteOnly), ref(1), type(QtDebugMsg),
75 : space(true), message_output(false), flags(DefaultVerbosity << VerbosityShift) {}
76 : Stream(QtMsgType t) : ts(&buffer, QIODevice::WriteOnly), ref(1), type(t),
77 : space(true), message_output(true), flags(DefaultVerbosity << VerbosityShift) {}
78 : QTextStream ts;
79 : QString buffer;
80 : int ref;
81 : QtMsgType type;
82 : bool space;
83 : bool message_output;
84 : QMessageLogContext context;
85 :
86 : enum FormatFlag { // Note: Bits 29..31 are reserved for the verbose level introduced in 5.6.
87 : NoQuotes = 0x1
88 : };
89 :
90 : // ### Qt 6: unify with space, introduce own version member
91 : bool testFlag(FormatFlag flag) const { return (context.version > 1) ? (flags & flag) : false; }
92 : void setFlag(FormatFlag flag) { if (context.version > 1) { flags |= flag; } }
93 : void unsetFlag(FormatFlag flag) { if (context.version > 1) { flags &= ~flag; } }
94 : int verbosity() const
95 : { return context.version > 1 ? (flags >> VerbosityShift) & VerbosityMask : int(Stream::DefaultVerbosity); }
96 : void setVerbosity(int v)
97 : {
98 : if (context.version > 1) {
99 : flags &= ~(VerbosityMask << VerbosityShift);
100 : flags |= (v & VerbosityMask) << VerbosityShift;
101 : }
102 : }
103 : // added in 5.4
104 : int flags;
105 : } *stream;
106 :
107 : enum Latin1Content { ContainsBinary = 0, ContainsLatin1 };
108 :
109 : void putUcs4(uint ucs4);
110 : void putString(const QChar *begin, size_t length);
111 : void putByteArray(const char *begin, size_t length, Latin1Content content);
112 : public:
113 : inline QDebug(QIODevice *device) : stream(new Stream(device)) {}
114 : inline QDebug(QString *string) : stream(new Stream(string)) {}
115 : inline QDebug(QtMsgType t) : stream(new Stream(t)) {}
116 : inline QDebug(const QDebug &o):stream(o.stream) { ++stream->ref; }
117 : inline QDebug &operator=(const QDebug &other);
118 : ~QDebug();
119 : inline void swap(QDebug &other) Q_DECL_NOTHROW { qSwap(stream, other.stream); }
120 :
121 : QDebug &resetFormat();
122 :
123 : inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
124 : inline QDebug &nospace() { stream->space = false; return *this; }
125 0 : inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
126 : int verbosity() const { return stream->verbosity(); }
127 : void setVerbosity(int verbosityLevel) { stream->setVerbosity(verbosityLevel); }
128 :
129 : bool autoInsertSpaces() const { return stream->space; }
130 : void setAutoInsertSpaces(bool b) { stream->space = b; }
131 :
132 : inline QDebug "e() { stream->unsetFlag(Stream::NoQuotes); return *this; }
133 : inline QDebug &noquote() { stream->setFlag(Stream::NoQuotes); return *this; }
134 : inline QDebug &maybeQuote(char c = '"') { if (!(stream->testFlag(Stream::NoQuotes))) stream->ts << c; return *this; }
135 :
136 : inline QDebug &operator<<(QChar t) { putUcs4(t.unicode()); return maybeSpace(); }
137 0 : inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
138 : inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
139 : inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
140 : inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); }
141 : #ifdef Q_COMPILER_UNICODE_STRINGS
142 : inline QDebug &operator<<(char16_t t) { return *this << QChar(ushort(t)); }
143 : inline QDebug &operator<<(char32_t t) { putUcs4(t); return maybeSpace(); }
144 : #endif
145 : inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); }
146 : inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); }
147 : inline QDebug &operator<<(signed long t) { stream->ts << t; return maybeSpace(); }
148 : inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); }
149 0 : inline QDebug &operator<<(qint64 t) { stream->ts << t; return maybeSpace(); }
150 : inline QDebug &operator<<(quint64 t) { stream->ts << t; return maybeSpace(); }
151 : inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
152 : inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
153 0 : inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
154 : #if QT_STRINGVIEW_LEVEL < 2
155 0 : inline QDebug &operator<<(const QString & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
156 : inline QDebug &operator<<(const QStringRef & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
157 : #endif
158 : inline QDebug &operator<<(QStringView s) { putString(s.data(), size_t(s.size())); return maybeSpace(); }
159 : inline QDebug &operator<<(QLatin1String t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
160 : inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
161 : inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
162 : #ifdef Q_COMPILER_NULLPTR
163 : inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
164 : #endif
165 : inline QDebug &operator<<(QTextStreamFunction f) {
166 : stream->ts << f;
167 : return *this;
168 : }
169 :
170 : inline QDebug &operator<<(QTextStreamManipulator m)
171 : { stream->ts << m; return *this; }
172 : };
173 :
174 : Q_DECLARE_SHARED(QDebug)
175 :
176 : class QDebugStateSaverPrivate;
177 : class Q_CORE_EXPORT QDebugStateSaver
178 : {
179 : public:
180 : QDebugStateSaver(QDebug &dbg);
181 : ~QDebugStateSaver();
182 : private:
183 : Q_DISABLE_COPY(QDebugStateSaver)
184 : QScopedPointer<QDebugStateSaverPrivate> d;
185 : };
186 :
187 : class QNoDebug
188 : {
189 : public:
190 : inline QNoDebug &operator<<(QTextStreamFunction) { return *this; }
191 : inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }
192 : inline QNoDebug &space() { return *this; }
193 : inline QNoDebug &nospace() { return *this; }
194 : inline QNoDebug &maybeSpace() { return *this; }
195 : inline QNoDebug "e() { return *this; }
196 : inline QNoDebug &noquote() { return *this; }
197 : inline QNoDebug &maybeQuote(const char = '"') { return *this; }
198 :
199 : template<typename T>
200 : inline QNoDebug &operator<<(const T &) { return *this; }
201 : };
202 :
203 : inline QDebug &QDebug::operator=(const QDebug &other)
204 : {
205 : if (this != &other) {
206 : QDebug copy(other);
207 : qSwap(stream, copy.stream);
208 : }
209 : return *this;
210 : }
211 :
212 : namespace QtPrivate {
213 :
214 : template <typename SequentialContainer>
215 : inline QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c)
216 : {
217 : const bool oldSetting = debug.autoInsertSpaces();
218 : debug.nospace() << which << '(';
219 : typename SequentialContainer::const_iterator it = c.begin(), end = c.end();
220 : if (it != end) {
221 : debug << *it;
222 : ++it;
223 : }
224 : while (it != end) {
225 : debug << ", " << *it;
226 : ++it;
227 : }
228 : debug << ')';
229 : debug.setAutoInsertSpaces(oldSetting);
230 : return debug.maybeSpace();
231 : }
232 :
233 : } // namespace QtPrivate
234 :
235 : template <class T>
236 : inline QDebug operator<<(QDebug debug, const QList<T> &list)
237 : {
238 : return QtPrivate::printSequentialContainer(debug, "" /*for historical reasons*/, list);
239 : }
240 :
241 : template <typename T>
242 : inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
243 : {
244 : return QtPrivate::printSequentialContainer(debug, "QVector", vec);
245 : }
246 :
247 : template <typename T, typename Alloc>
248 : inline QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec)
249 : {
250 : return QtPrivate::printSequentialContainer(debug, "std::vector", vec);
251 : }
252 :
253 : template <typename T, typename Alloc>
254 : inline QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec)
255 : {
256 : return QtPrivate::printSequentialContainer(debug, "std::list", vec);
257 : }
258 :
259 : template <typename Key, typename T, typename Compare, typename Alloc>
260 : inline QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
261 : {
262 : return QtPrivate::printSequentialContainer(debug, "std::map", map); // yes, sequential: *it is std::pair
263 : }
264 :
265 : template <typename Key, typename T, typename Compare, typename Alloc>
266 : inline QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map)
267 : {
268 : return QtPrivate::printSequentialContainer(debug, "std::multimap", map); // yes, sequential: *it is std::pair
269 : }
270 :
271 : template <class Key, class T>
272 : inline QDebug operator<<(QDebug debug, const QMap<Key, T> &map)
273 : {
274 : const bool oldSetting = debug.autoInsertSpaces();
275 : debug.nospace() << "QMap(";
276 : for (typename QMap<Key, T>::const_iterator it = map.constBegin();
277 : it != map.constEnd(); ++it) {
278 : debug << '(' << it.key() << ", " << it.value() << ')';
279 : }
280 : debug << ')';
281 : debug.setAutoInsertSpaces(oldSetting);
282 : return debug.maybeSpace();
283 : }
284 :
285 : template <class Key, class T>
286 : inline QDebug operator<<(QDebug debug, const QHash<Key, T> &hash)
287 : {
288 : const bool oldSetting = debug.autoInsertSpaces();
289 : debug.nospace() << "QHash(";
290 : for (typename QHash<Key, T>::const_iterator it = hash.constBegin();
291 : it != hash.constEnd(); ++it)
292 : debug << '(' << it.key() << ", " << it.value() << ')';
293 : debug << ')';
294 : debug.setAutoInsertSpaces(oldSetting);
295 : return debug.maybeSpace();
296 : }
297 :
298 : template <class T1, class T2>
299 : inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
300 : {
301 : const bool oldSetting = debug.autoInsertSpaces();
302 : debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')';
303 : debug.setAutoInsertSpaces(oldSetting);
304 : return debug.maybeSpace();
305 : }
306 :
307 : template <class T1, class T2>
308 : inline QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair)
309 : {
310 : const bool oldSetting = debug.autoInsertSpaces();
311 : debug.nospace() << "std::pair(" << pair.first << ',' << pair.second << ')';
312 : debug.setAutoInsertSpaces(oldSetting);
313 : return debug.maybeSpace();
314 : }
315 :
316 : template <typename T>
317 : inline QDebug operator<<(QDebug debug, const QSet<T> &set)
318 : {
319 : return QtPrivate::printSequentialContainer(debug, "QSet", set);
320 : }
321 :
322 : template <class T>
323 : inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
324 : {
325 : const bool oldSetting = debug.autoInsertSpaces();
326 : debug.nospace() << "QContiguousCache(";
327 : for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
328 : debug << cache[i];
329 : if (i != cache.lastIndex())
330 : debug << ", ";
331 : }
332 : debug << ')';
333 : debug.setAutoInsertSpaces(oldSetting);
334 : return debug.maybeSpace();
335 : }
336 :
337 : template <class T>
338 : inline QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr)
339 : {
340 : QDebugStateSaver saver(debug);
341 : debug.nospace() << "QSharedPointer(" << ptr.data() << ")";
342 : return debug;
343 : }
344 :
345 : Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value);
346 :
347 : template <typename Int>
348 : void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
349 : {
350 : const QDebugStateSaver saver(debug);
351 : debug.resetFormat();
352 : debug.nospace() << "QFlags(" << hex << showbase;
353 : bool needSeparator = false;
354 : for (uint i = 0; i < sizeofT * 8; ++i) {
355 : if (value & (Int(1) << i)) {
356 : if (needSeparator)
357 : debug << '|';
358 : else
359 : needSeparator = true;
360 : debug << (Int(1) << i);
361 : }
362 : }
363 : debug << ')';
364 : }
365 :
366 : #if !defined(QT_NO_QOBJECT) && !defined(Q_QDOC)
367 : Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, int value, const QMetaObject *meta, const char *name);
368 : Q_CORE_EXPORT QDebug qt_QMetaEnum_flagDebugOperator(QDebug &dbg, quint64 value, const QMetaObject *meta, const char *name);
369 :
370 : template<typename T>
371 : typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, QDebug>::type
372 : operator<<(QDebug dbg, T value)
373 : {
374 : const QMetaObject *obj = qt_getEnumMetaObject(value);
375 : const char *name = qt_getEnumName(value);
376 : return qt_QMetaEnum_debugOperator(dbg, typename QFlags<T>::Int(value), obj, name);
377 : }
378 :
379 : template <class T>
380 : inline typename std::enable_if<
381 : QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<QFlags<T> >::Value,
382 : QDebug>::type
383 : qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
384 : {
385 : const QMetaObject *obj = qt_getEnumMetaObject(T());
386 : const char *name = qt_getEnumName(T());
387 : return qt_QMetaEnum_flagDebugOperator(debug, quint64(flags), obj, name);
388 : }
389 :
390 : template <class T>
391 : inline typename std::enable_if<
392 : !QtPrivate::IsQEnumHelper<T>::Value && !QtPrivate::IsQEnumHelper<QFlags<T> >::Value,
393 : QDebug>::type
394 : qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
395 : #else // !QT_NO_QOBJECT && !Q_QDOC
396 : template <class T>
397 : inline QDebug qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
398 : #endif
399 : {
400 : qt_QMetaEnum_flagDebugOperator(debug, sizeof(T), typename QFlags<T>::Int(flags));
401 : return debug;
402 : }
403 :
404 : template<typename T>
405 : inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
406 : {
407 : // We have to use an indirection otherwise specialisation of some other overload of the
408 : // operator<< the compiler would try to instantiate QFlags<T> for the std::enable_if
409 : return qt_QMetaEnum_flagDebugOperator_helper(debug, flags);
410 : }
411 :
412 : #ifdef Q_OS_MAC
413 :
414 : // We provide QDebug stream operators for commonly used Core Foundation
415 : // and Core Graphics types, as well as NSObject. Additional CF/CG types
416 : // may be added by the user, using Q_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE.
417 :
418 : #define QT_FOR_EACH_CORE_FOUNDATION_TYPE(F) \
419 : F(CFArray) \
420 : F(CFURL) \
421 : F(CFData) \
422 : F(CFNumber) \
423 : F(CFDictionary) \
424 : F(CFLocale) \
425 : F(CFDate) \
426 : F(CFBoolean) \
427 : F(CFTimeZone) \
428 :
429 : #define QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(F) \
430 : F(CFError) \
431 : F(CFBundle) \
432 :
433 : #define QT_FOR_EACH_CORE_GRAPHICS_TYPE(F) \
434 : F(CGPath) \
435 :
436 : #define QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(F) \
437 : F(CGColorSpace) \
438 : F(CGImage) \
439 : F(CGFont) \
440 : F(CGColor) \
441 :
442 : #define QT_FORWARD_DECLARE_CF_TYPE(type) Q_FORWARD_DECLARE_CF_TYPE(type);
443 : #define QT_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type);
444 : #define QT_FORWARD_DECLARE_CG_TYPE(type) Q_FORWARD_DECLARE_CG_TYPE(type);
445 : #define QT_FORWARD_DECLARE_MUTABLE_CG_TYPE(type) Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(type);
446 :
447 : QT_END_NAMESPACE
448 : Q_FORWARD_DECLARE_CF_TYPE(CFString);
449 : Q_FORWARD_DECLARE_OBJC_CLASS(NSObject);
450 : QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_CF_TYPE)
451 : QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_MUTABLE_CF_TYPE)
452 : QT_FOR_EACH_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_CG_TYPE)
453 : QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_MUTABLE_CG_TYPE)
454 : QT_BEGIN_NAMESPACE
455 :
456 : #define QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType) \
457 : Q_CORE_EXPORT QDebug operator<<(QDebug, CFType##Ref);
458 :
459 : #define Q_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType) \
460 : QDebug operator<<(QDebug debug, CFType##Ref ref) \
461 : { \
462 : if (!ref) \
463 : return debug << QT_STRINGIFY(CFType) "Ref(0x0)"; \
464 : if (CFStringRef description = CFCopyDescription(ref)) { \
465 : QDebugStateSaver saver(debug); \
466 : debug.noquote() << description; \
467 : CFRelease(description); \
468 : } \
469 : return debug; \
470 : }
471 :
472 : // Defined in qcore_mac_objc.mm
473 : Q_CORE_EXPORT QDebug operator<<(QDebug, const NSObject *);
474 : Q_CORE_EXPORT QDebug operator<<(QDebug, CFStringRef);
475 :
476 : QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
477 : QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
478 : QT_FOR_EACH_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
479 : QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
480 :
481 : #undef QT_FORWARD_DECLARE_CF_TYPE
482 : #undef QT_FORWARD_DECLARE_MUTABLE_CF_TYPE
483 : #undef QT_FORWARD_DECLARE_CG_TYPE
484 : #undef QT_FORWARD_DECLARE_MUTABLE_CG_TYPE
485 :
486 : #endif // Q_OS_MAC
487 :
488 : QT_END_NAMESPACE
489 :
490 : #endif // QDEBUG_H
|