1 // Author: Max Howell <max.howell@methylblue.com>, (C) 2003-5
2 // Author: Mark Kretschmann <kretschmann@kde.org>, (C) 2007
3 // Copyright: See COPYING file that comes with this distribution
9 // We always want debug output available at runtime
10 #undef QT_NO_DEBUG_OUTPUT
11 #undef KDE_NO_DEBUG_OUTPUT
15 #include <KConfigGroup>
17 #include <QApplication>
24 #include "amarok_export.h"
27 #define __PRETTY_FUNCTION__ __FUNCTION__
32 * @short kdebug with indentation functionality and convenience macros
33 * @author Max Howell <max.howell@methylblue.com>
37 * #define DEBUG_PREFIX "Blah"
42 * Debug::Block myBlock( __PRETTY_FUNCTION__ );
44 * debug() << "output1" << endl;
45 * debug() << "output2" << endl;
50 * app: BEGIN: void function()
53 * app: END: void function(): Took 0.1s
62 extern AMAROK_EXPORT QMutex mutex
; // defined in app.cpp
64 // we can't use a statically instantiated QCString for the indent, because
65 // static namespaces are unique to each dlopened library. So we piggy back
66 // the QCString on the KApplication instance
68 #define qOApp reinterpret_cast<QObject*>(qApp)
69 class Indent
: QObject
71 friend QString
&modifieableIndent();
72 Indent() : QObject( qOApp
) { setObjectName( "DEBUG_indent" ); }
76 inline QString
&modifieableIndent()
78 QObject
* o
= qOApp
? qOApp
->findChild
<QObject
*>( "DEBUG_indent" ) : 0;
79 QString
&ret
= (o
? static_cast<Indent
*>( o
) : new Indent
)->m_string
;
83 inline QString
indent()
85 return modifieableIndent();
88 inline bool debugEnabled()
90 KConfigGroup config
= KGlobal::config()->group( "General" );
91 const bool debug
= config
.readEntry( "Debug Enabled", false );
96 inline kdbgstream
dbgstream()
98 return debugEnabled() ? kdbgstream( QtDebugMsg
) : kDebugDevNull();
104 #define AMK_PREFIX ""
106 #define AMK_PREFIX "[" DEBUG_PREFIX "]"
118 static inline kdbgstream
debug() { mutex
.lock(); QString ind
= indent(); mutex
.unlock(); return dbgstream() << qPrintable( ind
+ AMK_PREFIX
); }
119 static inline kdbgstream
warning() { mutex
.lock(); QString ind
= indent(); mutex
.unlock(); return dbgstream() << qPrintable( ind
+ AMK_PREFIX
+ " [WARNING!]" ); }
120 static inline kdbgstream
error() { mutex
.lock(); QString ind
= indent(); mutex
.unlock(); return dbgstream() << qPrintable( ind
+ AMK_PREFIX
+ " [ERROR!]" ); }
121 static inline kdbgstream
fatal() { mutex
.lock(); QString ind
= indent(); mutex
.unlock(); return dbgstream() << qPrintable( ind
+ AMK_PREFIX
); }
123 typedef kdbgstream DebugStream
;
127 typedef kndbgstream NoDebugStream
;
131 using Debug::warning
;
134 using Debug::DebugStream
;
136 /// Standard function announcer
137 #define DEBUG_FUNC_INFO { Debug::mutex.lock(); kDebug() << Debug::indent() ; Debug::mutex.unlock(); }
140 #define DEBUG_LINE_INFO { Debug::mutex.lock(); kDebug() << Debug::indent() << "Line: " << __LINE__; Debug::mutex.unlock(); }
142 /// Convenience macro for making a standard Debug::Block
143 #define DEBUG_BLOCK Debug::Block uniquelyNamedStackAllocatedStandardBlock( __PRETTY_FUNCTION__ );
145 /// Use this to remind yourself to finish the implementation of a function
146 #define AMAROK_NOTIMPLEMENTED warning() << "NOT-IMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
148 /// Use this to alert other developers to stop using a function
149 #define AMAROK_DEPRECATED warning() << "DEPRECATED: " << __PRETTY_FUNCTION__ << endl;
155 * @class Debug::Block
156 * @short Use this to label sections of your code
162 * Debug::Block myBlock( "section" );
164 * debug() << "output1" << endl;
165 * debug() << "output2" << endl;
170 * app: BEGIN: section
171 * app: [prefix] output1
172 * app: [prefix] output2
173 * app: END: section - Took 0.1s
183 Block( const char *label
)
186 if( !debugEnabled() ) return;
189 gettimeofday( &m_start
, 0 );
191 kDebug() << "BEGIN:" << label
;
192 Debug::modifieableIndent() += " ";
198 if( !debugEnabled() ) return;
202 gettimeofday( &end
, 0 );
204 end
.tv_sec
-= m_start
.tv_sec
;
205 if( end
.tv_usec
< m_start
.tv_usec
) {
206 // Manually carry a one from the seconds field.
207 end
.tv_usec
+= 1000000;
210 end
.tv_usec
-= m_start
.tv_usec
;
212 double duration
= double(end
.tv_sec
) + (double(end
.tv_usec
) / 1000000.0);
214 Debug::modifieableIndent().truncate( Debug::indent().length() - 2 );
215 kDebug() << "END__:" << m_label
216 << "- Took" << qPrintable( QString::number( duration
, 'g', 2 ) + "s" );
223 * @name Debug::stamp()
224 * @short To facilitate crash/freeze bugs, by making it easy to mark code that has been processed
236 * Will output (assuming the crash occurs in function2()
246 debug() << "| Stamp: " << ++n
<< endl
;
257 * @short You can pass anything to this and it will output it as a list
259 * debug() << (Debug::List() << anInt << aString << aQStringList << aDouble) << endl;
262 typedef QList
<QVariant
> List
;