add check for role to data()
[amarok.git] / src / debug.h
blobc14317492a1c2a9d07419e6b65f9fe0100daf8bc
1 // Author: Max Howell <max.howell@methylblue.com>, (C) 2003-5
2 // Copyright: See COPYING file that comes with this distribution
3 //
5 #ifndef AMAROK_DEBUG_H
6 #define AMAROK_DEBUG_H
8 #include <kdebug.h>
9 #include <QApplication>
10 #include <QMutex>
11 #include <QObject>
13 #include <iostream>
14 #include <sys/time.h>
16 #include "amarok_export.h"
18 #ifdef _WIN32
19 #define __PRETTY_FUNCTION__ __FUNCTION__
20 #endif
22 /**
23 * @namespace Debug
24 * @short kdebug with indentation functionality and convenience macros
25 * @author Max Howell <max.howell@methylblue.com>
27 * Usage:
29 * #define DEBUG_PREFIX "Blah"
30 * #include "debug.h"
32 * void function()
33 * {
34 * Debug::Block myBlock( __PRETTY_FUNCTION__ );
36 * debug() << "output1" << endl;
37 * debug() << "output2" << endl;
38 * }
40 * Will output:
42 * app: BEGIN: void function()
43 * app: [Blah] output1
44 * app: [Blah] output2
45 * app: END: void function(): Took 0.1s
47 * @see Block
48 * @see CrashHelper
49 * @see ListStream
52 namespace Debug
54 extern AMAROK_EXPORT QMutex mutex; // defined in app.cpp
56 // we can't use a statically instantiated QCString for the indent, because
57 // static namespaces are unique to each dlopened library. So we piggy back
58 // the QCString on the KApplication instance
60 #define qOApp reinterpret_cast<QObject*>(qApp)
61 class Indent : QObject
63 friend QString &modifieableIndent();
64 Indent() : QObject( qOApp ) { setObjectName( "DEBUG_indent" ); }
65 QString m_string;
68 inline QString &modifieableIndent()
70 QObject* o = qOApp ? qOApp->findChild<QObject*>( "DEBUG_indent" ) : 0;
71 QString &ret = (o ? static_cast<Indent*>( o ) : new Indent)->m_string;
72 return ret;
75 inline QString indent()
77 return modifieableIndent();
79 #undef qApp
82 #ifdef NDEBUG
83 static inline kndbgstream debug() { return kndbgstream(); }
84 static inline kndbgstream warning() { return kndbgstream(); }
85 static inline kndbgstream error() { return kndbgstream(); }
86 static inline kndbgstream fatal() { return kndbgstream(); }
88 typedef kndbgstream DebugStream;
89 #else
90 #ifndef DEBUG_PREFIX
91 #define AMK_PREFIX ""
92 #else
93 #define AMK_PREFIX "[" DEBUG_PREFIX "] "
94 #endif
96 //from kdebug.h
97 enum DebugLevels {
98 KDEBUG_INFO = 0,
99 KDEBUG_WARN = 1,
100 KDEBUG_ERROR = 2,
101 KDEBUG_FATAL = 3
104 static inline kdbgstream debug() { mutex.lock(); QString ind = indent(); mutex.unlock(); return kdbgstream( QtDebugMsg ) << ind + AMK_PREFIX; }
105 static inline kdbgstream warning() { mutex.lock(); QString ind = indent(); mutex.unlock(); return kdbgstream( QtDebugMsg ) << ind + AMK_PREFIX << "[WARNING!] "; }
106 static inline kdbgstream error() { mutex.lock(); QString ind = indent(); mutex.unlock(); return kdbgstream( QtDebugMsg ) << ind + AMK_PREFIX << "[ERROR!] "; }
107 static inline kdbgstream fatal() { mutex.lock(); QString ind = indent(); mutex.unlock(); return kdbgstream( QtDebugMsg ) << ind + AMK_PREFIX; }
109 typedef kdbgstream DebugStream;
111 #undef AMK_PREFIX
112 #endif
114 typedef kndbgstream NoDebugStream;
117 using Debug::debug;
118 using Debug::warning;
119 using Debug::error;
120 using Debug::fatal;
121 using Debug::DebugStream;
123 /// Standard function announcer
124 #define DEBUG_FUNC_INFO { Debug::mutex.lock(); kDebug() << Debug::indent() << k_funcinfo << endl; Debug::mutex.unlock(); }
126 /// Announce a line
127 #define DEBUG_LINE_INFO { Debug::mutex.lock(); kDebug() << Debug::indent() << k_funcinfo << "Line: " << __LINE__ << endl; Debug::mutex.unlock(); }
129 /// Convenience macro for making a standard Debug::Block
130 #define DEBUG_BLOCK Debug::Block uniquelyNamedStackAllocatedStandardBlock( __PRETTY_FUNCTION__ );
132 /// Use this to remind yourself to finish the implementation of a function
133 #define AMAROK_NOTIMPLEMENTED warning() << "NOT-IMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
135 /// Use this to alert other developers to stop using a function
136 #define AMAROK_DEPRECATED warning() << "DEPRECATED: " << __PRETTY_FUNCTION__ << endl;
139 namespace Debug
142 * @class Debug::Block
143 * @short Use this to label sections of your code
145 * Usage:
147 * void function()
149 * Debug::Block myBlock( "section" );
151 * debug() << "output1" << endl;
152 * debug() << "output2" << endl;
155 * Will output:
157 * app: BEGIN: section
158 * app: [prefix] output1
159 * app: [prefix] output2
160 * app: END: section - Took 0.1s
164 class Block
166 timeval m_start;
167 const char *m_label;
169 public:
170 Block( const char *label )
171 : m_label( label )
173 mutex.lock();
174 gettimeofday( &m_start, 0 );
176 kDebug() << "BEGIN: " << label << "\n";
177 Debug::modifieableIndent() += " ";
178 mutex.unlock();
181 ~Block()
183 mutex.lock();
184 timeval end;
185 gettimeofday( &end, 0 );
187 end.tv_sec -= m_start.tv_sec;
188 if( end.tv_usec < m_start.tv_usec) {
189 // Manually carry a one from the seconds field.
190 end.tv_usec += 1000000;
191 end.tv_sec--;
193 end.tv_usec -= m_start.tv_usec;
195 double duration = double(end.tv_sec) + (double(end.tv_usec) / 1000000.0);
197 Debug::modifieableIndent().truncate( Debug::indent().length() - 2 );
198 kDebug() << "END__: " << m_label
199 << " - Took " << QString::number( duration, 'g', 2 ) << "s\n";
200 mutex.unlock();
206 * @name Debug::stamp()
207 * @short To facilitate crash/freeze bugs, by making it easy to mark code that has been processed
209 * Usage:
212 * Debug::stamp();
213 * function1();
214 * Debug::stamp();
215 * function2();
216 * Debug::stamp();
219 * Will output (assuming the crash occurs in function2()
221 * app: Stamp: 1
222 * app: Stamp: 2
226 inline void stamp()
228 static int n = 0;
229 debug() << "| Stamp: " << ++n << endl;
234 #include <QVariant>
236 namespace Debug
239 * @class Debug::List
240 * @short You can pass anything to this and it will output it as a list
242 * debug() << (Debug::List() << anInt << aString << aQStringList << aDouble) << endl;
245 typedef QList<QVariant> List;
248 #endif