1 | /* This file is part of the KDE libraries |
2 | Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) |
3 | 2000-2002 Stephan Kulow (coolo@kde.org) |
4 | 2002 Holger Freyther (freyther@kde.org) |
5 | |
6 | This library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Library General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2 of the License, or (at your option) any later version. |
10 | |
11 | This library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Library General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Library General Public License |
17 | along with this library; see the file COPYING.LIB. If not, write to |
18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | Boston, MA 02110-1301, USA. |
20 | */ |
21 | |
22 | #ifndef _KDEBUG_H_ |
23 | #define _KDEBUG_H_ |
24 | |
25 | #include <kdecore_export.h> |
26 | |
27 | #include <QtCore/QDebug> |
28 | #include <QtCore/QElapsedTimer> |
29 | |
30 | /** |
31 | * \addtogroup kdebug Debug message generators |
32 | * @{ |
33 | * KDE debug message streams let you and the user control just how many debug |
34 | * messages you see. Debug message printing is controlled by (un)defining |
35 | * QT_NO_DEBUG when compiling your source. If QT_NO_DEBUG is defined then debug |
36 | * messages are not printed by default but can still be enabled by runtime |
37 | * configuration, e.g. via kdebugdialog or by editing kdebugrc. |
38 | * |
39 | * You can also control what you see: process name, area name, method name, |
40 | * file and line number, timestamp, etc. using environment variables. |
41 | * See http://techbase.kde.org/SysAdmin/Environment_Variables#KDE_DEBUG_NOPROCESSINFO |
42 | */ |
43 | |
44 | #if !defined(KDE_NO_DEBUG_OUTPUT) |
45 | # if defined(QT_NO_DEBUG_OUTPUT) || defined(QT_NO_DEBUG_STREAM) |
46 | # define KDE_NO_DEBUG_OUTPUT |
47 | # endif |
48 | #endif |
49 | |
50 | #if !defined(KDE_NO_WARNING_OUTPUT) |
51 | # if defined(QT_NO_WARNING_OUTPUT) |
52 | # define KDE_NO_WARNING_OUTPUT |
53 | # endif |
54 | #endif |
55 | |
56 | #ifdef QT_NO_DEBUG /* The application is compiled in release mode */ |
57 | # define KDE_DEBUG_ENABLED_BY_DEFAULT false |
58 | #else |
59 | # define KDE_DEBUG_ENABLED_BY_DEFAULT true |
60 | #endif |
61 | |
62 | /** |
63 | * An indicator of where you are in a source file, to be used in |
64 | * warnings (perhaps debug messages too). |
65 | * @deprecated kDebug takes care of printing the method name automatically now |
66 | */ |
67 | #define k_funcinfo "" |
68 | |
69 | /** |
70 | * An indicator of where you are in a source file, to be used in |
71 | * warnings (perhaps debug messages too). Gives an accurate |
72 | * idea of where the message comes from. Not suitable for |
73 | * user-visible messages. |
74 | * @deprecated kDebug takes care of printing the method name automatically now |
75 | */ |
76 | #define k_lineinfo "[" << __FILE__ << ":" << __LINE__ << "] " |
77 | |
78 | /** |
79 | * @internal |
80 | * Returns a debug stream that may or may not output anything. |
81 | */ |
82 | KDECORE_EXPORT QDebug kDebugStream(QtMsgType level, int area, const char *file = 0, |
83 | int line = -1, const char *funcinfo = 0); |
84 | |
85 | /** |
86 | * @internal |
87 | * Returns a debug stream that goes the way of the blackhole. |
88 | */ |
89 | KDECORE_EXPORT QDebug kDebugDevNull(); |
90 | |
91 | /** |
92 | * @internal |
93 | * The actual backtrace. |
94 | */ |
95 | KDECORE_EXPORT QString kRealBacktrace(int); |
96 | |
97 | |
98 | /** |
99 | * \relates KGlobal |
100 | * Returns a backtrace. |
101 | * Note: Hidden symbol visibility may negatively affect the information provided |
102 | * by kBacktrace - you may want to pass -D__KDE_HAVE_GCC_VISIBILITY=0 to cmake |
103 | * to turn hidden symbol visibility off. |
104 | * @param levels the number of levels of the backtrace |
105 | * @return a backtrace |
106 | */ |
107 | #if !defined(KDE_NO_DEBUG_OUTPUT) |
108 | inline QString kBacktrace(int levels=-1) { return kRealBacktrace(levels); } |
109 | #else |
110 | static inline QString kBacktrace(int=-1) { return QString(); } |
111 | #endif |
112 | |
113 | /** |
114 | * \relates KGlobal |
115 | * Deletes the kdebugrc cache and therefore forces KDebug to reread the |
116 | * config file |
117 | */ |
118 | KDECORE_EXPORT void kClearDebugConfig(); |
119 | |
120 | #ifndef KDE_DEFAULT_DEBUG_AREA |
121 | # define KDE_DEFAULT_DEBUG_AREA 0 |
122 | #endif |
123 | |
124 | /*! |
125 | \macro KDE_DEFAULT_DEBUG_AREA |
126 | \relates KGlobal |
127 | |
128 | Denotes the debug area to use in kDebug/kWarning etc when not |
129 | explicitly specified. The default is 0 (zero). |
130 | |
131 | Define this macro to the debug area of your application/component |
132 | before including any KDE headers. Usually, you want to add code like |
133 | this to your \c CMakeLists.txt: |
134 | |
135 | \code |
136 | ... |
137 | add_definitions( -DKDE_DEFAULT_DEBUG_AREA=1234 ) |
138 | ... |
139 | \endcode |
140 | |
141 | This way, you save repeating the debug area all over your source |
142 | code, in each debug/warning statement. |
143 | */ |
144 | |
145 | #if !defined(KDE_NO_DEBUG_OUTPUT) |
146 | /** |
147 | * \relates KGlobal |
148 | * Returns a debug stream. You can use it to print debug |
149 | * information. |
150 | * @param area an id to identify the output, KDE_DEFAULT_DEBUG_AREA for default |
151 | */ |
152 | static inline QDebug kDebug(int area = KDE_DEFAULT_DEBUG_AREA) |
153 | { return kDebugStream(QtDebugMsg, area); } |
154 | static inline QDebug kDebug(bool cond, int area = KDE_DEFAULT_DEBUG_AREA) |
155 | { return cond ? kDebug(area) : kDebugDevNull(); } |
156 | |
157 | #else // KDE_NO_DEBUG_OUTPUT |
158 | static inline QDebug kDebug(int = KDE_DEFAULT_DEBUG_AREA) { return kDebugDevNull(); } |
159 | static inline QDebug kDebug(bool, int = KDE_DEFAULT_DEBUG_AREA) { return kDebugDevNull(); } |
160 | #endif |
161 | |
162 | #if !defined(KDE_NO_WARNING_OUTPUT) |
163 | /** |
164 | * \relates KGlobal |
165 | * Returns a warning stream. You can use it to print warning |
166 | * information. |
167 | * @param area an id to identify the output, KDE_DEFAULT_DEBUG_AREA for default |
168 | */ |
169 | static inline QDebug kWarning(int area = KDE_DEFAULT_DEBUG_AREA) |
170 | { return kDebugStream(QtWarningMsg, area); } |
171 | static inline QDebug kWarning(bool cond, int area = KDE_DEFAULT_DEBUG_AREA) |
172 | { return cond ? kWarning(area) : kDebugDevNull(); } |
173 | |
174 | #else // KDE_NO_WARNING_OUTPUT |
175 | static inline QDebug kWarning(int = KDE_DEFAULT_DEBUG_AREA) { return kDebugDevNull(); } |
176 | static inline QDebug kWarning(bool, int = KDE_DEFAULT_DEBUG_AREA) { return kDebugDevNull(); } |
177 | #endif |
178 | |
179 | /** |
180 | * \relates KGlobal |
181 | * Returns an error stream. You can use it to print error |
182 | * information. |
183 | * @param area an id to identify the output, KDE_DEFAULT_DEBUG_AREA for default |
184 | */ |
185 | static inline QDebug kError(int area = KDE_DEFAULT_DEBUG_AREA) |
186 | { return kDebugStream(QtCriticalMsg, area); } |
187 | static inline QDebug kError(bool cond, int area = KDE_DEFAULT_DEBUG_AREA) |
188 | { return cond ? kError(area) : kDebugDevNull(); } |
189 | |
190 | /** |
191 | * \relates KGlobal |
192 | * Returns a fatal error stream. You can use it to print fatal error |
193 | * information. |
194 | * @param area an id to identify the output, KDE_DEFAULT_DEBUG_AREA for default |
195 | */ |
196 | static inline QDebug kFatal(int area = KDE_DEFAULT_DEBUG_AREA) |
197 | { return kDebugStream(QtFatalMsg, area); } |
198 | static inline QDebug kFatal(bool cond, int area = KDE_DEFAULT_DEBUG_AREA) |
199 | { return cond ? kFatal(area) : kDebugDevNull(); } |
200 | |
201 | struct KDebugTag { }; ///! @internal just a tag class |
202 | typedef QDebug (*KDebugStreamFunction)(QDebug, KDebugTag); ///< @internal |
203 | inline QDebug operator<<(QDebug s, KDebugStreamFunction f) |
204 | { return (*f)(s, KDebugTag()); } |
205 | |
206 | /** |
207 | * \relates KGlobal |
208 | * Print a message describing the last system error. |
209 | * @param s the debug stream to write to |
210 | * @return the debug stream (@p s) |
211 | * @see perror(3) |
212 | */ |
213 | KDECORE_EXPORT QDebug perror(QDebug, KDebugTag); |
214 | |
215 | // operators for KDE types |
216 | class KUrl; |
217 | class KDateTime; |
218 | class QObject; |
219 | KDECORE_EXPORT QDebug operator<<(QDebug s, const KUrl &url); |
220 | KDECORE_EXPORT QDebug operator<<(QDebug s, const KDateTime &time); |
221 | |
222 | #if 1 || defined(KDE3_SUPPORT) |
223 | #ifndef KDE_NO_DEPRECATED |
224 | class KDE_DEPRECATED kndbgstream { }; |
225 | typedef QDebug kdbgstream; |
226 | |
227 | static inline KDE_DEPRECATED QDebug kdDebug(int area = KDE_DEFAULT_DEBUG_AREA) { return kDebug(area); } |
228 | static inline KDE_DEPRECATED QDebug kdWarning(int area = KDE_DEFAULT_DEBUG_AREA) { return kWarning(area); } |
229 | static inline KDE_DEPRECATED QDebug kdError(int area = KDE_DEFAULT_DEBUG_AREA) { return kError(area); } |
230 | static inline KDE_DEPRECATED QDebug kdFatal(int area = KDE_DEFAULT_DEBUG_AREA) { return kFatal(area); } |
231 | inline KDE_DEPRECATED QString kdBacktrace(int levels=-1) { return kBacktrace( levels ); } |
232 | |
233 | static inline KDE_DEPRECATED QDebug kndDebug() { return kDebugDevNull(); } |
234 | #endif |
235 | #endif |
236 | |
237 | class WrongSyntax {}; |
238 | |
239 | /** |
240 | * @internal |
241 | * A class for using operator() |
242 | */ |
243 | class KDebug //krazy= ? |
244 | { |
245 | const char *file; |
246 | const char *funcinfo; |
247 | int line; |
248 | QtMsgType level; |
249 | public: |
250 | class Block; |
251 | explicit inline KDebug(QtMsgType type, const char *f = 0, int l = -1, const char *info = 0) |
252 | : file(f), funcinfo(info), line(l), level(type) |
253 | { |
254 | #ifdef KDE4_CMAKE_TOPLEVEL_DIR_LENGTH // set by FindKDE4Internal.cmake |
255 | file = file + KDE4_CMAKE_TOPLEVEL_DIR_LENGTH + 1; |
256 | #endif |
257 | } |
258 | |
259 | inline QDebug operator()(int area = KDE_DEFAULT_DEBUG_AREA) |
260 | { return kDebugStream(level, area, file, line, funcinfo); } |
261 | inline QDebug operator()(bool cond, int area = KDE_DEFAULT_DEBUG_AREA) |
262 | { if (cond) return operator()(area); return kDebugDevNull(); } |
263 | |
264 | /// @internal |
265 | static KDECORE_EXPORT bool hasNullOutput(QtMsgType type, |
266 | bool condition, |
267 | int area, |
268 | bool enableByDefault); |
269 | |
270 | /// @internal |
271 | static inline bool hasNullOutputQtDebugMsg(int area = KDE_DEFAULT_DEBUG_AREA) |
272 | { return hasNullOutput(QtDebugMsg, true, area, KDE_DEBUG_ENABLED_BY_DEFAULT); } |
273 | /// @internal |
274 | static inline bool hasNullOutputQtDebugMsg(bool condition, int area = KDE_DEFAULT_DEBUG_AREA) |
275 | { return hasNullOutput(QtDebugMsg, condition, area, KDE_DEBUG_ENABLED_BY_DEFAULT); } |
276 | |
277 | /** |
278 | * @since 4.4 |
279 | * Register a debug area dynamically. |
280 | * @param areaName the name of the area |
281 | * @param enabled whether debug output should be enabled by default |
282 | * (users can override this in kdebugdialog or with DisableAll=true in kdebugrc) |
283 | * @return the area code that was allocated for this area |
284 | * |
285 | * Typical usage: |
286 | * If all uses of the debug area are restricted to a single class, add a method like this |
287 | * (e.g. into the Private class, if there's one) |
288 | * <code> |
289 | * static int debugArea() { static int s_area = KDebug::registerArea("areaName"); return s_area; } |
290 | * </code> |
291 | * Please do not use a file-static int, it would (indirectly) create KGlobal too early, |
292 | * create KConfig instances too early (breaking unittests which set KDEHOME), etc. |
293 | * By using a function as shown above, you make it all happen on-demand, rather than upfront. |
294 | * |
295 | * If all uses of the debug area are restricted to a single .cpp file, do the same |
296 | * but outside any class, and then use a more specific name for the function. |
297 | * |
298 | * If however multiple classes and files need the debug area, then |
299 | * declare it in one file without static, and use "extern int debugArea();" |
300 | * in other files (with a better name for the function of course). |
301 | */ |
302 | static KDECORE_EXPORT int registerArea(const QByteArray& areaName, bool enabled = true); |
303 | |
304 | private: |
305 | WrongSyntax operator()(const char*) {return WrongSyntax();} // error! Use kDebug() << "..." or kWarning() << "..." instead. |
306 | }; |
307 | |
308 | |
309 | #if !defined(KDE_NO_DEBUG_OUTPUT) |
310 | /* __VA_ARGS__ should work with any supported GCC version and MSVC > 2005 */ |
311 | # if defined(Q_CC_GNU) || (defined(Q_CC_MSVC) && _MSC_VER >= 1500) |
312 | # define kDebug(...) for (bool _k_kDebugDoOutput_ = !KDebug::hasNullOutputQtDebugMsg(__VA_ARGS__); \ |
313 | KDE_ISUNLIKELY(_k_kDebugDoOutput_); _k_kDebugDoOutput_ = false) \ |
314 | KDebug(QtDebugMsg, __FILE__, __LINE__, Q_FUNC_INFO)(__VA_ARGS__) |
315 | # else |
316 | # define kDebug KDebug(QtDebugMsg, __FILE__, __LINE__, Q_FUNC_INFO) |
317 | # endif |
318 | #else |
319 | # define kDebug while (false) kDebug |
320 | #endif |
321 | #if !defined(KDE_NO_WARNING_OUTPUT) |
322 | # define kWarning KDebug(QtWarningMsg, __FILE__, __LINE__, Q_FUNC_INFO) |
323 | #else |
324 | # define kWarning while (false) kWarning |
325 | #endif |
326 | |
327 | #ifndef KDE_NO_DEBUG_OUTPUT |
328 | |
329 | /** |
330 | * @class KDebug::Block |
331 | * @short Use this to label sections of your code |
332 | * @since 4.6 |
333 | * |
334 | * Usage: |
335 | * <code> |
336 | * void function() |
337 | * { |
338 | * KDebug::Block myBlock( "section" ); |
339 | * |
340 | * debug() << "output1" << endl; |
341 | * debug() << "output2" << endl; |
342 | * } |
343 | * </code> |
344 | * |
345 | * Will output: |
346 | * |
347 | * app: BEGIN: section |
348 | * app: [prefix] output1 |
349 | * app: [prefix] output2 |
350 | * app: END: section - Took 0.1s |
351 | * |
352 | * Alternatively, use the KDEBUG_BLOCK macro, for automatic naming. |
353 | */ |
354 | class KDECORE_EXPORT KDebug::Block |
355 | { |
356 | public: |
357 | Block(const char* label, int area = KDE_DEFAULT_DEBUG_AREA); |
358 | ~Block(); |
359 | |
360 | private: |
361 | QElapsedTimer m_startTime; |
362 | const char *m_label; // KDE5 TODO: REMOVE |
363 | int m_area; |
364 | int m_color; |
365 | class Private; |
366 | Private* d; |
367 | }; |
368 | |
369 | /** |
370 | * Convenience macro for making a standard KDebug::Block |
371 | */ |
372 | #define KDEBUG_BLOCK KDebug::Block _kDebugBlock(Q_FUNC_INFO); |
373 | |
374 | #else |
375 | |
376 | class KDECORE_EXPORT KDebug::Block |
377 | { |
378 | public: |
379 | Block(const char*, int = KDE_DEFAULT_DEBUG_AREA) {} |
380 | ~Block() {} |
381 | }; |
382 | |
383 | #define KDEBUG_BLOCK |
384 | |
385 | #endif |
386 | |
387 | /** |
388 | * Convenience macro, use this to remind yourself to finish the implementation of a function |
389 | * The function name will appear in the output (unless $KDE_DEBUG_NOMETHODNAME is set) |
390 | * @since 4.6 |
391 | */ |
392 | #define KWARNING_NOTIMPLEMENTED kWarning() << "NOT-IMPLEMENTED"; |
393 | |
394 | /** |
395 | * Convenience macro, use this to alert other developers to stop using a function |
396 | * The function name will appear in the output (unless $KDE_DEBUG_NOMETHODNAME is set) |
397 | * @since 4.6 |
398 | */ |
399 | #define KWARNING_DEPRECATED kWarning() << "DEPRECATED"; |
400 | |
401 | /** @} */ |
402 | |
403 | #endif |
404 | |