Codebase list dtkwidget / dfe033c
change dlog -> dutil/log Change-Id: I5dc77ced2acdd273e048a913409f1cff6e7bc075 Iceyer 8 years ago
195 changed file(s) with 3960 addition(s) and 3983 deletion(s). Raw diff Collapse all Expand all
00 #!/bin/bash
11
2 tr '\n' ' ' < $1 | sed -e "s/#include//g" | sed -e "s/\"//g"
2 public_header=$1
3 headers=`tr '\n' ' ' < $public_header | sed -e "s/#include//g" | sed -e "s/\"//g"`
4 file_dir=$(dirname "${public_header}")
5 for f in $headers
6 do
7 echo $file_dir/$f
8 done
+0
-138
dlog/AbstractAppender.cpp less more
0 // Local
1 #include "AbstractAppender.h"
2
3 // Qt
4 #include <QMutexLocker>
5
6 namespace Dtk {
7 namespace Log {
8
9 /**
10 * \class AbstractAppender
11 *
12 * \brief The AbstractAppender class provides an abstract base class for writing a log entries.
13 *
14 * The AbstractAppender class is the base interface class for all log appenders that could be used with Logger.
15 *
16 * AbstractAppender provides a common implementation for the thread safe, mutex-protected logging of application
17 * messages, such as ConsoleAppender, FileAppender or something else. AbstractAppender is abstract and can not be
18 * instantiated, but you can use any of its subclasses or create a custom log appender at your choice.
19 *
20 * Appenders are the logical devices that is aimed to be attached to Logger object by calling
21 * Logger::registerAppender(). On each log record call from the application Logger object sequentially calls write()
22 * function on all the appenders registered in it.
23 *
24 * You can subclass AbstractAppender to implement a logging target of any kind you like. It may be the external logging
25 * subsystem (for example, syslog in *nix), XML file, SQL database entries, D-Bus messages or anything else you can
26 * imagine.
27 *
28 * For the simple non-structured plain text logging (for example, to a plain text file or to the console output) you may
29 * like to subclass the AbstractStringAppender instead of AbstractAppender, which will give you a more convinient way to
30 * control the format of the log output.
31 *
32 * \sa AbstractStringAppender
33 * \sa Logger::registerAppender()
34 */
35
36
37 //! Constructs a AbstractAppender object.
38 AbstractAppender::AbstractAppender()
39 : m_detailsLevel(Logger::Debug)
40 {}
41
42
43 //! Destructs the AbstractAppender object.
44 AbstractAppender::~AbstractAppender()
45 {}
46
47
48 //! Returns the current details level of appender.
49 /**
50 * Log records with a log level lower than a current detailsLevel() will be silently ignored by appender and would not
51 * be sent to its append() function.
52 *
53 * It provides additional logging flexibility, allowing you to set the different severity levels for different types
54 * of logs.
55 *
56 * \note This function is thread safe.
57 *
58 * \sa setDetailsLevel()
59 * \sa Logger::LogLevel
60 */
61 Logger::LogLevel AbstractAppender::detailsLevel() const
62 {
63 QMutexLocker locker(&m_detailsLevelMutex);
64 return m_detailsLevel;
65 }
66
67
68 //! Sets the current details level of appender.
69 /**
70 * Default details level is Logger::Debug
71 *
72 * \note This function is thread safe.
73 *
74 * \sa detailsLevel()
75 * \sa Logger::LogLevel
76 */
77 void AbstractAppender::setDetailsLevel(Logger::LogLevel level)
78 {
79 QMutexLocker locker(&m_detailsLevelMutex);
80 m_detailsLevel = level;
81 }
82
83
84
85 //! Sets the current details level of appender
86 /**
87 * This function is provided for convenience, it behaves like an above function.
88 *
89 * \sa detailsLevel()
90 * \sa Logger::LogLevel
91 */
92 void AbstractAppender::setDetailsLevel(const QString& level)
93 {
94 setDetailsLevel(Logger::levelFromString(level));
95 }
96
97
98 //! Tries to write the log record to this logger
99 /**
100 * This is the function called by Logger object to write a log message to the appender.
101 *
102 * \note This function is thread safe.
103 *
104 * \sa Logger::write()
105 * \sa detailsLevel()
106 */
107 void AbstractAppender::write(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
108 const char* function, const QString& category, const QString& message)
109 {
110 if (logLevel >= detailsLevel())
111 {
112 QMutexLocker locker(&m_writeMutex);
113 append(timeStamp, logLevel, file, line, function, category, message);
114 }
115 }
116
117
118 /**
119 * \fn virtual void AbstractAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file,
120 * int line, const char* function, const QString& message)
121 *
122 * \brief Writes the log record to the logger instance
123 *
124 * This function is called every time when user tries to write a message to this AbstractAppender instance using
125 * the write() function. Write function works as proxy and transfers only the messages with log level more or equal
126 * to the current logLevel().
127 *
128 * Overload this function when you are implementing a custom appender.
129 *
130 * \note This function is not needed to be thread safe because it is never called directly by Logger object. The
131 * write() function works as a proxy and protects this function from concurrent access.
132 *
133 * \sa Logger::write()
134 */
135
136 }
137 }
+0
-53
dlog/AbstractAppender.h less more
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef ABSTRACTAPPENDER_H
14 #define ABSTRACTAPPENDER_H
15
16 // Local
17 #include "CuteLogger_global.h"
18 #include <Logger.h>
19
20 // Qt
21 #include <QMutex>
22
23 namespace Dtk {
24 namespace Log {
25
26 class CUTELOGGERSHARED_EXPORT AbstractAppender
27 {
28 public:
29 AbstractAppender();
30 virtual ~AbstractAppender();
31
32 Logger::LogLevel detailsLevel() const;
33 void setDetailsLevel(Logger::LogLevel level);
34 void setDetailsLevel(const QString& level);
35
36 void write(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line, const char* function,
37 const QString& category, const QString& message);
38
39 protected:
40 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
41 const char* function, const QString& category, const QString& message) = 0;
42
43 private:
44 QMutex m_writeMutex;
45
46 Logger::LogLevel m_detailsLevel;
47 mutable QMutex m_detailsLevelMutex;
48 };
49
50 }}
51
52 #endif // ABSTRACTAPPENDER_H
+0
-463
dlog/AbstractStringAppender.cpp less more
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) Nikolay Matyunin (matyunin.n at gmail dot com)
2
3 Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License version 2.1
7 as published by the Free Software Foundation and appearing in the file
8 LICENSE.LGPL included in the packaging of this file.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14 */
15 // Local
16 #include "AbstractStringAppender.h"
17
18 // Qt
19 #include <QReadLocker>
20 #include <QWriteLocker>
21 #include <QDateTime>
22 #include <QRegExp>
23 #include <QCoreApplication>
24 #include <QThread>
25
26 namespace Dtk {
27 namespace Log {
28
29 /**
30 * \class AbstractStringAppender
31 *
32 * \brief The AbstractStringAppender class provides a convinient base for appenders working with plain text formatted
33 * logs.
34 *
35 * AbstractSringAppender is the simple extension of the AbstractAppender class providing the convinient way to create
36 * custom log appenders working with a plain text formatted log targets.
37 *
38 * It have the formattedString() protected function that formats the logging arguments according to a format set with
39 * setFormat().
40 *
41 * This class can not be directly instantiated because it contains pure virtual function inherited from AbstractAppender
42 * class.
43 *
44 * For more detailed description of customizing the log output format see the documentation on the setFormat() function.
45 */
46
47
48 const char formattingMarker = '%';
49
50
51 //! Constructs a new string appender object
52 AbstractStringAppender::AbstractStringAppender()
53 : m_format(QLatin1String("%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n"))
54 {}
55
56
57 //! Returns the current log format string.
58 /**
59 * The default format is set to "%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n". You can set a different log record
60 * format using the setFormat() function.
61 *
62 * \sa setFormat(const QString&)
63 */
64 QString AbstractStringAppender::format() const
65 {
66 QReadLocker locker(&m_formatLock);
67 return m_format;
68 }
69
70
71 //! Sets the logging format for writing strings to the log target with this appender.
72 /**
73 * The string format seems to be very common to those developers who have used a standart sprintf function.
74 *
75 * Log output format is a simple QString with the special markers (starting with % sign) which will be replaced with
76 * it's internal meaning when writing a log record.
77 *
78 * Controlling marker begins with the percent sign (%) which is followed by the command inside {} brackets
79 * (the command describes, what will be put to log record instead of marker).
80 * Optional field width argument may be specified right after the command (through the colon symbol before the closing bracket)
81 * Some commands requires an additional formatting argument (in the second {} brackets).
82 *
83 * Field width argument works almost identically to the \c QString::arg() \c fieldWidth argument (and uses it
84 * internally). For example, \c "%{type:-7}" will be replaced with the left padded debug level of the message
85 * (\c "Debug ") or something. For the more detailed description of it you may consider to look to the Qt
86 * Reference Documentation.
87 *
88 * Supported marker commands are:
89 * \arg \c %{time} - timestamp. You may specify your custom timestamp format using the second {} brackets after the marker,
90 * timestamp format here will be similiar to those used in QDateTime::toString() function. For example,
91 * "%{time}{dd-MM-yyyy, HH:mm}" may be replaced with "17-12-2010, 20:17" depending on current date and time.
92 * The default format used here is "HH:mm:ss.zzz".
93 * \arg \c %{type} - Log level. Possible log levels are shown in the Logger::LogLevel enumerator.
94 * \arg \c %{Type} - Uppercased log level.
95 * \arg \c %{typeOne} - One letter log level.
96 * \arg \c %{TypeOne} - One uppercase letter log level.
97 * \arg \c %{File} - Full source file name (with path) of the file that requested log recording. Uses the \c __FILE__
98 * preprocessor macro.
99 * \arg \c %{file} - Short file name (with stripped path).
100 * \arg \c %{line} - Line number in the source file. Uses the \c __LINE__ preprocessor macro.
101 * \arg \c %{Function} - Name of function that called on of the LOG_* macros. Uses the \c Q_FUNC_INFO macro provided with
102 * Qt.
103 * \arg \c %{function} - Similiar to the %{Function}, but the function name is stripped using stripFunctionName
104 * \arg \c %{message} - The log message sent by the caller.
105 * \arg \c %{category} - The log category.
106 * \arg \c %{appname} - Application name (returned by QCoreApplication::applicationName() function).
107 * \arg \c %{pid} - Application pid (returned by QCoreApplication::applicationPid() function).
108 * \arg \c %{threadid} - ID of current thread.
109 * \arg \c %% - Convinient marker that is replaced with the single \c % mark.
110 *
111 * \note Format doesn't add \c '\\n' to the end of the format line. Please consider adding it manually.
112 *
113 * \sa format()
114 * \sa stripFunctionName()
115 * \sa Logger::LogLevel
116 */
117 void AbstractStringAppender::setFormat(const QString& format)
118 {
119 QWriteLocker locker(&m_formatLock);
120 m_format = format;
121 }
122
123
124 //! Strips the long function signature (as added by Q_FUNC_INFO macro)
125 /**
126 * The string processing drops the returning type, arguments and template parameters of function. It is definitely
127 * useful for enchancing the log output readability.
128 * \return stripped function name
129 */
130 QString AbstractStringAppender::stripFunctionName(const char* name)
131 {
132 return QString::fromLatin1(qCleanupFuncinfo(name));
133 }
134
135
136 // The function was backported from Qt5 sources (qlogging.h)
137 QByteArray AbstractStringAppender::qCleanupFuncinfo(const char* name)
138 {
139 QByteArray info(name);
140
141 // Strip the function info down to the base function name
142 // note that this throws away the template definitions,
143 // the parameter types (overloads) and any const/volatile qualifiers.
144 if (info.isEmpty())
145 return info;
146
147 int pos;
148
149 // skip trailing [with XXX] for templates (gcc)
150 pos = info.size() - 1;
151 if (info.endsWith(']')) {
152 while (--pos) {
153 if (info.at(pos) == '[')
154 info.truncate(pos);
155 }
156 }
157
158 bool hasLambda = false;
159 QRegExp lambdaRegex("::<lambda\\(.*\\)>");
160 int lambdaIndex = lambdaRegex.indexIn(QString::fromLatin1(info));
161 if (lambdaIndex != -1)
162 {
163 hasLambda = true;
164 info.remove(lambdaIndex, lambdaRegex.matchedLength());
165 }
166
167 // operator names with '(', ')', '<', '>' in it
168 static const char operator_call[] = "operator()";
169 static const char operator_lessThan[] = "operator<";
170 static const char operator_greaterThan[] = "operator>";
171 static const char operator_lessThanEqual[] = "operator<=";
172 static const char operator_greaterThanEqual[] = "operator>=";
173
174 // canonize operator names
175 info.replace("operator ", "operator");
176
177 // remove argument list
178 forever {
179 int parencount = 0;
180 pos = info.lastIndexOf(')');
181 if (pos == -1) {
182 // Don't know how to parse this function name
183 return info;
184 }
185
186 // find the beginning of the argument list
187 --pos;
188 ++parencount;
189 while (pos && parencount) {
190 if (info.at(pos) == ')')
191 ++parencount;
192 else if (info.at(pos) == '(')
193 --parencount;
194 --pos;
195 }
196 if (parencount != 0)
197 return info;
198
199 info.truncate(++pos);
200
201 if (info.at(pos - 1) == ')') {
202 if (info.indexOf(operator_call) == pos - (int)strlen(operator_call))
203 break;
204
205 // this function returns a pointer to a function
206 // and we matched the arguments of the return type's parameter list
207 // try again
208 info.remove(0, info.indexOf('('));
209 info.chop(1);
210 continue;
211 } else {
212 break;
213 }
214 }
215
216 if (hasLambda)
217 info.append("::lambda");
218
219 // find the beginning of the function name
220 int parencount = 0;
221 int templatecount = 0;
222 --pos;
223
224 // make sure special characters in operator names are kept
225 if (pos > -1) {
226 switch (info.at(pos)) {
227 case ')':
228 if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1)
229 pos -= 2;
230 break;
231 case '<':
232 if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1)
233 --pos;
234 break;
235 case '>':
236 if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1)
237 --pos;
238 break;
239 case '=': {
240 int operatorLength = (int)strlen(operator_lessThanEqual);
241 if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1)
242 pos -= 2;
243 else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1)
244 pos -= 2;
245 break;
246 }
247 default:
248 break;
249 }
250 }
251
252 while (pos > -1) {
253 if (parencount < 0 || templatecount < 0)
254 return info;
255
256 char c = info.at(pos);
257 if (c == ')')
258 ++parencount;
259 else if (c == '(')
260 --parencount;
261 else if (c == '>')
262 ++templatecount;
263 else if (c == '<')
264 --templatecount;
265 else if (c == ' ' && templatecount == 0 && parencount == 0)
266 break;
267
268 --pos;
269 }
270 info = info.mid(pos + 1);
271
272 // remove trailing '*', '&' that are part of the return argument
273 while ((info.at(0) == '*')
274 || (info.at(0) == '&'))
275 info = info.mid(1);
276
277 // we have the full function name now.
278 // clean up the templates
279 while ((pos = info.lastIndexOf('>')) != -1) {
280 if (!info.contains('<'))
281 break;
282
283 // find the matching close
284 int end = pos;
285 templatecount = 1;
286 --pos;
287 while (pos && templatecount) {
288 register char c = info.at(pos);
289 if (c == '>')
290 ++templatecount;
291 else if (c == '<')
292 --templatecount;
293 --pos;
294 }
295 ++pos;
296 info.remove(pos, end - pos + 1);
297 }
298
299 return info;
300 }
301
302
303 //! Returns the string to record to the logging target, formatted according to the format().
304 /**
305 * \sa format()
306 * \sa setFormat(const QString&)
307 */
308 QString AbstractStringAppender::formattedString(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file,
309 int line, const char* function, const QString& category, const QString& message) const
310 {
311 QString f = format();
312 const int size = f.size();
313
314 QString result;
315
316 int i = 0;
317 while (i < f.size())
318 {
319 QChar c = f.at(i);
320
321 // We will silently ignore the broken % marker at the end of string
322 if (c != QLatin1Char(formattingMarker) || (i + 2) >= size)
323 {
324 result.append(c);
325 }
326 else
327 {
328 i += 2;
329 QChar currentChar = f.at(i);
330 QString command;
331 int fieldWidth = 0;
332
333 if (currentChar.isLetter())
334 {
335 command.append(currentChar);
336 int j = 1;
337 while ((i + j) < size && f.at(i + j).isLetter())
338 {
339 command.append(f.at(i+j));
340 j++;
341 }
342
343 i+=j;
344 currentChar = f.at(i);
345
346 // Check for the padding instruction
347 if (currentChar == QLatin1Char(':'))
348 {
349 currentChar = f.at(++i);
350 if (currentChar.isDigit() || currentChar.category() == QChar::Punctuation_Dash)
351 {
352 int j = 1;
353 while ((i + j) < size && f.at(i + j).isDigit())
354 j++;
355 fieldWidth = f.mid(i, j).toInt();
356
357 i += j;
358 }
359 }
360 }
361
362 // Log record chunk to insert instead of formatting instruction
363 QString chunk;
364
365 // Time stamp
366 if (command == QLatin1String("time"))
367 {
368 if (f.at(i + 1) == QLatin1Char('{'))
369 {
370 int j = 1;
371 while ((i + 2 + j) < size && f.at(i + 2 + j) != QLatin1Char('}'))
372 j++;
373
374 if ((i + 2 + j) < size)
375 {
376 chunk = timeStamp.toString(f.mid(i + 2, j));
377
378 i += j;
379 i += 2;
380 }
381 }
382
383 if (chunk.isNull())
384 chunk = timeStamp.toString(QLatin1String("HH:mm:ss.zzz"));
385 }
386
387 // Log level
388 else if (command == QLatin1String("type"))
389 chunk = Logger::levelToString(logLevel);
390
391 // Uppercased log level
392 else if (command == QLatin1String("Type"))
393 chunk = Logger::levelToString(logLevel).toUpper();
394
395 // One letter log level
396 else if (command == QLatin1String("typeOne"))
397 chunk = Logger::levelToString(logLevel).left(1).toLower();
398
399 // One uppercase letter log level
400 else if (command == QLatin1String("TypeOne"))
401 chunk = Logger::levelToString(logLevel).left(1).toUpper();
402
403 // Filename
404 else if (command == QLatin1String("File"))
405 chunk = QLatin1String(file);
406
407 // Filename without a path
408 else if (command == QLatin1String("file"))
409 chunk = QString(QLatin1String(file)).section('/', -1);
410
411 // Source line number
412 else if (command == QLatin1String("line"))
413 chunk = QString::number(line);
414
415 // Function name, as returned by Q_FUNC_INFO
416 else if (command == QLatin1String("Function"))
417 chunk = QString::fromLatin1(function);
418
419 // Stripped function name
420 else if (command == QLatin1String("function"))
421 chunk = stripFunctionName(function);
422
423 // Log message
424 else if (command == QLatin1String("message"))
425 chunk = message;
426
427 else if (command == QLatin1String("category"))
428 chunk = category;
429
430 // Application pid
431 else if (command == QLatin1String("pid"))
432 chunk = QString::number(QCoreApplication::applicationPid());
433
434 // Appplication name
435 else if (command == QLatin1String("appname"))
436 chunk = QCoreApplication::applicationName();
437
438 // Thread ID (duplicates Qt5 threadid debbuging way)
439 else if (command == QLatin1String("threadid"))
440 chunk = QLatin1String("0x") + QString::number(qlonglong(QThread::currentThread()->currentThread()), 16);
441
442 // We simply replace the double formatting marker (%) with one
443 else if (command == QString(formattingMarker))
444 chunk = QLatin1Char(formattingMarker);
445
446 // Do not process any unknown commands
447 else
448 {
449 chunk = QString(formattingMarker);
450 chunk.append(command);
451 }
452
453 result.append(QString(QLatin1String("%1")).arg(chunk, fieldWidth));
454 }
455
456 ++i;
457 }
458
459 return result;
460 }
461
462 }}
+0
-50
dlog/AbstractStringAppender.h less more
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef ABSTRACTSTRINGAPPENDER_H
14 #define ABSTRACTSTRINGAPPENDER_H
15
16 // Local
17 #include "CuteLogger_global.h"
18 #include <AbstractAppender.h>
19
20 // Qt
21 #include <QReadWriteLock>
22
23 namespace Dtk {
24 namespace Log {
25
26 class CUTELOGGERSHARED_EXPORT AbstractStringAppender : public AbstractAppender
27 {
28 public:
29 AbstractStringAppender();
30
31 virtual QString format() const;
32 void setFormat(const QString&);
33
34 static QString stripFunctionName(const char*);
35
36 protected:
37 QString formattedString(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
38 const char* function, const QString& category, const QString& message) const;
39
40 private:
41 static QByteArray qCleanupFuncinfo(const char*);
42
43 QString m_format;
44 mutable QReadWriteLock m_formatLock;
45 };
46
47 }}
48
49 #endif // ABSTRACTSTRINGAPPENDER_H
+0
-69
dlog/ConsoleAppender.cpp less more
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 // Local
14 #include "ConsoleAppender.h"
15
16 // STL
17 #include <iostream>
18
19 namespace Dtk {
20 namespace Log {
21
22 /**
23 * \class ConsoleAppender
24 *
25 * \brief ConsoleAppender is the simple appender that writes the log records to the std::cerr output stream.
26 *
27 * ConsoleAppender uses "[%{type:-7}] <%{function}> %{message}\n" as a default output format. It is similar to the
28 * AbstractStringAppender but doesn't show a timestamp.
29 *
30 * You can modify ConsoleAppender output format without modifying your code by using \c QT_MESSAGE_PATTERN environment
31 * variable. If you need your application to ignore this environment variable you can call
32 * ConsoleAppender::ignoreEnvironmentPattern(true)
33 */
34
35
36 ConsoleAppender::ConsoleAppender()
37 : AbstractStringAppender(),
38 m_ignoreEnvPattern(false)
39 {
40 setFormat("[%{type:-7}] <%{function}> %{message}\n");
41 }
42
43
44 QString ConsoleAppender::format() const
45 {
46 const QString envPattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
47 return (m_ignoreEnvPattern || envPattern.isEmpty()) ? AbstractStringAppender::format() : (envPattern + "\n");
48 }
49
50
51 void ConsoleAppender::ignoreEnvironmentPattern(bool ignore)
52 {
53 m_ignoreEnvPattern = ignore;
54 }
55
56
57 //! Writes the log record to the std::cerr stream.
58 /**
59 * \sa AbstractStringAppender::format()
60 */
61 void ConsoleAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
62 const char* function, const QString& category, const QString& message)
63 {
64 std::cerr << qPrintable(formattedString(timeStamp, logLevel, file, line, function, category, message));
65 }
66
67 }
68 }
+0
-40
dlog/ConsoleAppender.h less more
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef CONSOLEAPPENDER_H
14 #define CONSOLEAPPENDER_H
15
16 #include "CuteLogger_global.h"
17 #include <AbstractStringAppender.h>
18
19 namespace Dtk {
20 namespace Log {
21
22 class CUTELOGGERSHARED_EXPORT ConsoleAppender : public AbstractStringAppender
23 {
24 public:
25 ConsoleAppender();
26 virtual QString format() const;
27 void ignoreEnvironmentPattern(bool ignore);
28
29 protected:
30 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
31 const char* function, const QString& category, const QString& message);
32
33 private:
34 bool m_ignoreEnvPattern;
35 };
36
37 }}
38
39 #endif // CONSOLEAPPENDER_H
+0
-54
dlog/CuteLogger_global.h less more
0 #ifndef CUTELOGGER_GLOBAL_H
1 #define CUTELOGGER_GLOBAL_H
2
3 #include <QtCore/qglobal.h>
4
5 // Accept any number of args >= N, but expand to just the Nth one.
6 // Here, N == 6.
7 #define _GET_NTH_ARG(_1, _2, _3, _4, _5, N, ...) N
8
9 // Define some macros to help us create overrides based on the
10 // arity of a for-each-style macro.
11 #define _fe_0(_call, ...)
12 #define _fe_1(_call, x) _call(x)
13 #define _fe_2(_call, x, ...) _call(x) _fe_1(_call, __VA_ARGS__)
14 #define _fe_3(_call, x, ...) _call(x) _fe_2(_call, __VA_ARGS__)
15 #define _fe_4(_call, x, ...) _call(x) _fe_3(_call, __VA_ARGS__)
16
17 /**
18 * Provide a for-each construct for variadic macros. Supports up
19 * to 4 args.
20 *
21 * Example usage1:
22 * #define FWD_DECLARE_CLASS(cls) class cls;
23 * CALL_MACRO_X_FOR_EACH(FWD_DECLARE_CLASS, Foo, Bar)
24 *
25 * Example usage 2:
26 * #define START_NS(ns) namespace ns {
27 * #define END_NS(ns) }
28 * #define MY_NAMESPACES System, Net, Http
29 * CALL_MACRO_X_FOR_EACH(START_NS, MY_NAMESPACES)
30 * typedef foo int;
31 * CALL_MACRO_X_FOR_EACH(END_NS, MY_NAMESPACES)
32 */
33 #define _CALL_MACRO_X_FOR_EACH(x, ...) \
34 _GET_NTH_ARG("ignored", ##__VA_ARGS__, \
35 _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(x, ##__VA_ARGS__)
36
37 #define _START_NS(ns) namespace ns {
38 #define _END_NS(ns) }/*##ns*/
39 #define MY_NAMESPACES System, Net, Http
40 #define NS_START(...) _CALL_MACRO_X_FOR_EACH(_START_NS, __VA_ARGS__)
41 #define NS_END(...) _CALL_MACRO_X_FOR_EACH(_END_NS, __VA_ARGS__)
42
43 #if defined(CUTELOGGER_LIBRARY)
44 # define CUTELOGGERSHARED_EXPORT Q_DECL_EXPORT
45 #else
46 #if defined(Q_OS_WIN32)
47 # define CUTELOGGERSHARED_EXPORT
48 #else
49 # define CUTELOGGERSHARED_EXPORT Q_DECL_IMPORT
50 #endif
51 #endif
52
53 #endif // CUTELOGGER_GLOBAL_H
+0
-8
dlog/DLog less more
0 #include "CuteLogger_global.h"
1 #include "RollingFileAppender.h"
2 #include "Logger.h"
3 #include "LogManager.h"
4 #include "FileAppender.h"
5 #include "ConsoleAppender.h"
6 #include "AbstractStringAppender.h"
7 #include "AbstractAppender.h"
+0
-108
dlog/FileAppender.cpp less more
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 // Local
14 #include "FileAppender.h"
15
16 // STL
17 #include <iostream>
18
19 namespace Dtk {
20 namespace Log {
21
22 /**
23 * \class FileAppender
24 *
25 * \brief Simple appender that writes the log records to the plain text file.
26 */
27
28
29 //! Constructs the new file appender assigned to file with the given name.
30 FileAppender::FileAppender(const QString& fileName)
31 {
32 setFileName(fileName);
33 }
34
35
36 FileAppender::~FileAppender()
37 {
38 closeFile();
39 }
40
41
42 //! Returns the name set by setFileName() or to the FileAppender constructor.
43 /**
44 * \sa setFileName()
45 */
46 QString FileAppender::fileName() const
47 {
48 QMutexLocker locker(&m_logFileMutex);
49 return m_logFile.fileName();
50 }
51
52
53 //! Sets the name of the file. The name can have no path, a relative path, or an absolute path.
54 /**
55 * \sa fileName()
56 */
57 void FileAppender::setFileName(const QString& s)
58 {
59 QMutexLocker locker(&m_logFileMutex);
60 if (m_logFile.isOpen())
61 m_logFile.close();
62
63 m_logFile.setFileName(s);
64 }
65
66
67 bool FileAppender::openFile()
68 {
69 bool isOpen = m_logFile.isOpen();
70 if (!isOpen)
71 {
72 isOpen = m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
73 if (isOpen)
74 m_logStream.setDevice(&m_logFile);
75 else
76 std::cerr << "<FileAppender::append> Cannot open the log file " << qPrintable(m_logFile.fileName()) << std::endl;
77 }
78 return isOpen;
79 }
80
81
82 //! Write the log record to the file.
83 /**
84 * \sa fileName()
85 * \sa AbstractStringAppender::format()
86 */
87 void FileAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
88 const char* function, const QString& category, const QString& message)
89 {
90 QMutexLocker locker(&m_logFileMutex);
91
92 if (openFile())
93 {
94 m_logStream << formattedString(timeStamp, logLevel, file, line, function, category, message);
95 m_logStream.flush();
96 m_logFile.flush();
97 }
98 }
99
100
101 void FileAppender::closeFile()
102 {
103 QMutexLocker locker(&m_logFileMutex);
104 m_logFile.close();
105 }
106
107 }}
+0
-51
dlog/FileAppender.h less more
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef FILEAPPENDER_H
14 #define FILEAPPENDER_H
15
16 // Logger
17 #include "CuteLogger_global.h"
18 #include <AbstractStringAppender.h>
19
20 // Qt
21 #include <QFile>
22 #include <QTextStream>
23
24 namespace Dtk {
25 namespace Log {
26
27 class CUTELOGGERSHARED_EXPORT FileAppender : public AbstractStringAppender
28 {
29 public:
30 FileAppender(const QString& fileName = QString());
31 ~FileAppender();
32
33 QString fileName() const;
34 void setFileName(const QString&);
35
36 protected:
37 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
38 const char* function, const QString& category, const QString& message);
39 bool openFile();
40 void closeFile();
41
42 private:
43 QFile m_logFile;
44 QTextStream m_logStream;
45 mutable QMutex m_logFileMutex;
46 };
47
48 }}
49
50 #endif // FILEAPPENDER_H
+0
-674
dlog/LICENSE less more
0 GNU GENERAL PUBLIC LICENSE
1 Version 3, 29 June 2007
2
3 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
4 Everyone is permitted to copy and distribute verbatim copies
5 of this license document, but changing it is not allowed.
6
7 Preamble
8
9 The GNU General Public License is a free, copyleft license for
10 software and other kinds of works.
11
12 The licenses for most software and other practical works are designed
13 to take away your freedom to share and change the works. By contrast,
14 the GNU General Public License is intended to guarantee your freedom to
15 share and change all versions of a program--to make sure it remains free
16 software for all its users. We, the Free Software Foundation, use the
17 GNU General Public License for most of our software; it applies also to
18 any other work released this way by its authors. You can apply it to
19 your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22 price. Our General Public Licenses are designed to make sure that you
23 have the freedom to distribute copies of free software (and charge for
24 them if you wish), that you receive source code or can get it if you
25 want it, that you can change the software or use pieces of it in new
26 free programs, and that you know you can do these things.
27
28 To protect your rights, we need to prevent others from denying you
29 these rights or asking you to surrender the rights. Therefore, you have
30 certain responsibilities if you distribute copies of the software, or if
31 you modify it: responsibilities to respect the freedom of others.
32
33 For example, if you distribute copies of such a program, whether
34 gratis or for a fee, you must pass on to the recipients the same
35 freedoms that you received. You must make sure that they, too, receive
36 or can get the source code. And you must show them these terms so they
37 know their rights.
38
39 Developers that use the GNU GPL protect your rights with two steps:
40 (1) assert copyright on the software, and (2) offer you this License
41 giving you legal permission to copy, distribute and/or modify it.
42
43 For the developers' and authors' protection, the GPL clearly explains
44 that there is no warranty for this free software. For both users' and
45 authors' sake, the GPL requires that modified versions be marked as
46 changed, so that their problems will not be attributed erroneously to
47 authors of previous versions.
48
49 Some devices are designed to deny users access to install or run
50 modified versions of the software inside them, although the manufacturer
51 can do so. This is fundamentally incompatible with the aim of
52 protecting users' freedom to change the software. The systematic
53 pattern of such abuse occurs in the area of products for individuals to
54 use, which is precisely where it is most unacceptable. Therefore, we
55 have designed this version of the GPL to prohibit the practice for those
56 products. If such problems arise substantially in other domains, we
57 stand ready to extend this provision to those domains in future versions
58 of the GPL, as needed to protect the freedom of users.
59
60 Finally, every program is threatened constantly by software patents.
61 States should not allow patents to restrict development and use of
62 software on general-purpose computers, but in those that do, we wish to
63 avoid the special danger that patents applied to a free program could
64 make it effectively proprietary. To prevent this, the GPL assures that
65 patents cannot be used to render the program non-free.
66
67 The precise terms and conditions for copying, distribution and
68 modification follow.
69
70 TERMS AND CONDITIONS
71
72 0. Definitions.
73
74 "This License" refers to version 3 of the GNU General Public License.
75
76 "Copyright" also means copyright-like laws that apply to other kinds of
77 works, such as semiconductor masks.
78
79 "The Program" refers to any copyrightable work licensed under this
80 License. Each licensee is addressed as "you". "Licensees" and
81 "recipients" may be individuals or organizations.
82
83 To "modify" a work means to copy from or adapt all or part of the work
84 in a fashion requiring copyright permission, other than the making of an
85 exact copy. The resulting work is called a "modified version" of the
86 earlier work or a work "based on" the earlier work.
87
88 A "covered work" means either the unmodified Program or a work based
89 on the Program.
90
91 To "propagate" a work means to do anything with it that, without
92 permission, would make you directly or secondarily liable for
93 infringement under applicable copyright law, except executing it on a
94 computer or modifying a private copy. Propagation includes copying,
95 distribution (with or without modification), making available to the
96 public, and in some countries other activities as well.
97
98 To "convey" a work means any kind of propagation that enables other
99 parties to make or receive copies. Mere interaction with a user through
100 a computer network, with no transfer of a copy, is not conveying.
101
102 An interactive user interface displays "Appropriate Legal Notices"
103 to the extent that it includes a convenient and prominently visible
104 feature that (1) displays an appropriate copyright notice, and (2)
105 tells the user that there is no warranty for the work (except to the
106 extent that warranties are provided), that licensees may convey the
107 work under this License, and how to view a copy of this License. If
108 the interface presents a list of user commands or options, such as a
109 menu, a prominent item in the list meets this criterion.
110
111 1. Source Code.
112
113 The "source code" for a work means the preferred form of the work
114 for making modifications to it. "Object code" means any non-source
115 form of a work.
116
117 A "Standard Interface" means an interface that either is an official
118 standard defined by a recognized standards body, or, in the case of
119 interfaces specified for a particular programming language, one that
120 is widely used among developers working in that language.
121
122 The "System Libraries" of an executable work include anything, other
123 than the work as a whole, that (a) is included in the normal form of
124 packaging a Major Component, but which is not part of that Major
125 Component, and (b) serves only to enable use of the work with that
126 Major Component, or to implement a Standard Interface for which an
127 implementation is available to the public in source code form. A
128 "Major Component", in this context, means a major essential component
129 (kernel, window system, and so on) of the specific operating system
130 (if any) on which the executable work runs, or a compiler used to
131 produce the work, or an object code interpreter used to run it.
132
133 The "Corresponding Source" for a work in object code form means all
134 the source code needed to generate, install, and (for an executable
135 work) run the object code and to modify the work, including scripts to
136 control those activities. However, it does not include the work's
137 System Libraries, or general-purpose tools or generally available free
138 programs which are used unmodified in performing those activities but
139 which are not part of the work. For example, Corresponding Source
140 includes interface definition files associated with source files for
141 the work, and the source code for shared libraries and dynamically
142 linked subprograms that the work is specifically designed to require,
143 such as by intimate data communication or control flow between those
144 subprograms and other parts of the work.
145
146 The Corresponding Source need not include anything that users
147 can regenerate automatically from other parts of the Corresponding
148 Source.
149
150 The Corresponding Source for a work in source code form is that
151 same work.
152
153 2. Basic Permissions.
154
155 All rights granted under this License are granted for the term of
156 copyright on the Program, and are irrevocable provided the stated
157 conditions are met. This License explicitly affirms your unlimited
158 permission to run the unmodified Program. The output from running a
159 covered work is covered by this License only if the output, given its
160 content, constitutes a covered work. This License acknowledges your
161 rights of fair use or other equivalent, as provided by copyright law.
162
163 You may make, run and propagate covered works that you do not
164 convey, without conditions so long as your license otherwise remains
165 in force. You may convey covered works to others for the sole purpose
166 of having them make modifications exclusively for you, or provide you
167 with facilities for running those works, provided that you comply with
168 the terms of this License in conveying all material for which you do
169 not control copyright. Those thus making or running the covered works
170 for you must do so exclusively on your behalf, under your direction
171 and control, on terms that prohibit them from making any copies of
172 your copyrighted material outside their relationship with you.
173
174 Conveying under any other circumstances is permitted solely under
175 the conditions stated below. Sublicensing is not allowed; section 10
176 makes it unnecessary.
177
178 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
179
180 No covered work shall be deemed part of an effective technological
181 measure under any applicable law fulfilling obligations under article
182 11 of the WIPO copyright treaty adopted on 20 December 1996, or
183 similar laws prohibiting or restricting circumvention of such
184 measures.
185
186 When you convey a covered work, you waive any legal power to forbid
187 circumvention of technological measures to the extent such circumvention
188 is effected by exercising rights under this License with respect to
189 the covered work, and you disclaim any intention to limit operation or
190 modification of the work as a means of enforcing, against the work's
191 users, your or third parties' legal rights to forbid circumvention of
192 technological measures.
193
194 4. Conveying Verbatim Copies.
195
196 You may convey verbatim copies of the Program's source code as you
197 receive it, in any medium, provided that you conspicuously and
198 appropriately publish on each copy an appropriate copyright notice;
199 keep intact all notices stating that this License and any
200 non-permissive terms added in accord with section 7 apply to the code;
201 keep intact all notices of the absence of any warranty; and give all
202 recipients a copy of this License along with the Program.
203
204 You may charge any price or no price for each copy that you convey,
205 and you may offer support or warranty protection for a fee.
206
207 5. Conveying Modified Source Versions.
208
209 You may convey a work based on the Program, or the modifications to
210 produce it from the Program, in the form of source code under the
211 terms of section 4, provided that you also meet all of these conditions:
212
213 a) The work must carry prominent notices stating that you modified
214 it, and giving a relevant date.
215
216 b) The work must carry prominent notices stating that it is
217 released under this License and any conditions added under section
218 7. This requirement modifies the requirement in section 4 to
219 "keep intact all notices".
220
221 c) You must license the entire work, as a whole, under this
222 License to anyone who comes into possession of a copy. This
223 License will therefore apply, along with any applicable section 7
224 additional terms, to the whole of the work, and all its parts,
225 regardless of how they are packaged. This License gives no
226 permission to license the work in any other way, but it does not
227 invalidate such permission if you have separately received it.
228
229 d) If the work has interactive user interfaces, each must display
230 Appropriate Legal Notices; however, if the Program has interactive
231 interfaces that do not display Appropriate Legal Notices, your
232 work need not make them do so.
233
234 A compilation of a covered work with other separate and independent
235 works, which are not by their nature extensions of the covered work,
236 and which are not combined with it such as to form a larger program,
237 in or on a volume of a storage or distribution medium, is called an
238 "aggregate" if the compilation and its resulting copyright are not
239 used to limit the access or legal rights of the compilation's users
240 beyond what the individual works permit. Inclusion of a covered work
241 in an aggregate does not cause this License to apply to the other
242 parts of the aggregate.
243
244 6. Conveying Non-Source Forms.
245
246 You may convey a covered work in object code form under the terms
247 of sections 4 and 5, provided that you also convey the
248 machine-readable Corresponding Source under the terms of this License,
249 in one of these ways:
250
251 a) Convey the object code in, or embodied in, a physical product
252 (including a physical distribution medium), accompanied by the
253 Corresponding Source fixed on a durable physical medium
254 customarily used for software interchange.
255
256 b) Convey the object code in, or embodied in, a physical product
257 (including a physical distribution medium), accompanied by a
258 written offer, valid for at least three years and valid for as
259 long as you offer spare parts or customer support for that product
260 model, to give anyone who possesses the object code either (1) a
261 copy of the Corresponding Source for all the software in the
262 product that is covered by this License, on a durable physical
263 medium customarily used for software interchange, for a price no
264 more than your reasonable cost of physically performing this
265 conveying of source, or (2) access to copy the
266 Corresponding Source from a network server at no charge.
267
268 c) Convey individual copies of the object code with a copy of the
269 written offer to provide the Corresponding Source. This
270 alternative is allowed only occasionally and noncommercially, and
271 only if you received the object code with such an offer, in accord
272 with subsection 6b.
273
274 d) Convey the object code by offering access from a designated
275 place (gratis or for a charge), and offer equivalent access to the
276 Corresponding Source in the same way through the same place at no
277 further charge. You need not require recipients to copy the
278 Corresponding Source along with the object code. If the place to
279 copy the object code is a network server, the Corresponding Source
280 may be on a different server (operated by you or a third party)
281 that supports equivalent copying facilities, provided you maintain
282 clear directions next to the object code saying where to find the
283 Corresponding Source. Regardless of what server hosts the
284 Corresponding Source, you remain obligated to ensure that it is
285 available for as long as needed to satisfy these requirements.
286
287 e) Convey the object code using peer-to-peer transmission, provided
288 you inform other peers where the object code and Corresponding
289 Source of the work are being offered to the general public at no
290 charge under subsection 6d.
291
292 A separable portion of the object code, whose source code is excluded
293 from the Corresponding Source as a System Library, need not be
294 included in conveying the object code work.
295
296 A "User Product" is either (1) a "consumer product", which means any
297 tangible personal property which is normally used for personal, family,
298 or household purposes, or (2) anything designed or sold for incorporation
299 into a dwelling. In determining whether a product is a consumer product,
300 doubtful cases shall be resolved in favor of coverage. For a particular
301 product received by a particular user, "normally used" refers to a
302 typical or common use of that class of product, regardless of the status
303 of the particular user or of the way in which the particular user
304 actually uses, or expects or is expected to use, the product. A product
305 is a consumer product regardless of whether the product has substantial
306 commercial, industrial or non-consumer uses, unless such uses represent
307 the only significant mode of use of the product.
308
309 "Installation Information" for a User Product means any methods,
310 procedures, authorization keys, or other information required to install
311 and execute modified versions of a covered work in that User Product from
312 a modified version of its Corresponding Source. The information must
313 suffice to ensure that the continued functioning of the modified object
314 code is in no case prevented or interfered with solely because
315 modification has been made.
316
317 If you convey an object code work under this section in, or with, or
318 specifically for use in, a User Product, and the conveying occurs as
319 part of a transaction in which the right of possession and use of the
320 User Product is transferred to the recipient in perpetuity or for a
321 fixed term (regardless of how the transaction is characterized), the
322 Corresponding Source conveyed under this section must be accompanied
323 by the Installation Information. But this requirement does not apply
324 if neither you nor any third party retains the ability to install
325 modified object code on the User Product (for example, the work has
326 been installed in ROM).
327
328 The requirement to provide Installation Information does not include a
329 requirement to continue to provide support service, warranty, or updates
330 for a work that has been modified or installed by the recipient, or for
331 the User Product in which it has been modified or installed. Access to a
332 network may be denied when the modification itself materially and
333 adversely affects the operation of the network or violates the rules and
334 protocols for communication across the network.
335
336 Corresponding Source conveyed, and Installation Information provided,
337 in accord with this section must be in a format that is publicly
338 documented (and with an implementation available to the public in
339 source code form), and must require no special password or key for
340 unpacking, reading or copying.
341
342 7. Additional Terms.
343
344 "Additional permissions" are terms that supplement the terms of this
345 License by making exceptions from one or more of its conditions.
346 Additional permissions that are applicable to the entire Program shall
347 be treated as though they were included in this License, to the extent
348 that they are valid under applicable law. If additional permissions
349 apply only to part of the Program, that part may be used separately
350 under those permissions, but the entire Program remains governed by
351 this License without regard to the additional permissions.
352
353 When you convey a copy of a covered work, you may at your option
354 remove any additional permissions from that copy, or from any part of
355 it. (Additional permissions may be written to require their own
356 removal in certain cases when you modify the work.) You may place
357 additional permissions on material, added by you to a covered work,
358 for which you have or can give appropriate copyright permission.
359
360 Notwithstanding any other provision of this License, for material you
361 add to a covered work, you may (if authorized by the copyright holders of
362 that material) supplement the terms of this License with terms:
363
364 a) Disclaiming warranty or limiting liability differently from the
365 terms of sections 15 and 16 of this License; or
366
367 b) Requiring preservation of specified reasonable legal notices or
368 author attributions in that material or in the Appropriate Legal
369 Notices displayed by works containing it; or
370
371 c) Prohibiting misrepresentation of the origin of that material, or
372 requiring that modified versions of such material be marked in
373 reasonable ways as different from the original version; or
374
375 d) Limiting the use for publicity purposes of names of licensors or
376 authors of the material; or
377
378 e) Declining to grant rights under trademark law for use of some
379 trade names, trademarks, or service marks; or
380
381 f) Requiring indemnification of licensors and authors of that
382 material by anyone who conveys the material (or modified versions of
383 it) with contractual assumptions of liability to the recipient, for
384 any liability that these contractual assumptions directly impose on
385 those licensors and authors.
386
387 All other non-permissive additional terms are considered "further
388 restrictions" within the meaning of section 10. If the Program as you
389 received it, or any part of it, contains a notice stating that it is
390 governed by this License along with a term that is a further
391 restriction, you may remove that term. If a license document contains
392 a further restriction but permits relicensing or conveying under this
393 License, you may add to a covered work material governed by the terms
394 of that license document, provided that the further restriction does
395 not survive such relicensing or conveying.
396
397 If you add terms to a covered work in accord with this section, you
398 must place, in the relevant source files, a statement of the
399 additional terms that apply to those files, or a notice indicating
400 where to find the applicable terms.
401
402 Additional terms, permissive or non-permissive, may be stated in the
403 form of a separately written license, or stated as exceptions;
404 the above requirements apply either way.
405
406 8. Termination.
407
408 You may not propagate or modify a covered work except as expressly
409 provided under this License. Any attempt otherwise to propagate or
410 modify it is void, and will automatically terminate your rights under
411 this License (including any patent licenses granted under the third
412 paragraph of section 11).
413
414 However, if you cease all violation of this License, then your
415 license from a particular copyright holder is reinstated (a)
416 provisionally, unless and until the copyright holder explicitly and
417 finally terminates your license, and (b) permanently, if the copyright
418 holder fails to notify you of the violation by some reasonable means
419 prior to 60 days after the cessation.
420
421 Moreover, your license from a particular copyright holder is
422 reinstated permanently if the copyright holder notifies you of the
423 violation by some reasonable means, this is the first time you have
424 received notice of violation of this License (for any work) from that
425 copyright holder, and you cure the violation prior to 30 days after
426 your receipt of the notice.
427
428 Termination of your rights under this section does not terminate the
429 licenses of parties who have received copies or rights from you under
430 this License. If your rights have been terminated and not permanently
431 reinstated, you do not qualify to receive new licenses for the same
432 material under section 10.
433
434 9. Acceptance Not Required for Having Copies.
435
436 You are not required to accept this License in order to receive or
437 run a copy of the Program. Ancillary propagation of a covered work
438 occurring solely as a consequence of using peer-to-peer transmission
439 to receive a copy likewise does not require acceptance. However,
440 nothing other than this License grants you permission to propagate or
441 modify any covered work. These actions infringe copyright if you do
442 not accept this License. Therefore, by modifying or propagating a
443 covered work, you indicate your acceptance of this License to do so.
444
445 10. Automatic Licensing of Downstream Recipients.
446
447 Each time you convey a covered work, the recipient automatically
448 receives a license from the original licensors, to run, modify and
449 propagate that work, subject to this License. You are not responsible
450 for enforcing compliance by third parties with this License.
451
452 An "entity transaction" is a transaction transferring control of an
453 organization, or substantially all assets of one, or subdividing an
454 organization, or merging organizations. If propagation of a covered
455 work results from an entity transaction, each party to that
456 transaction who receives a copy of the work also receives whatever
457 licenses to the work the party's predecessor in interest had or could
458 give under the previous paragraph, plus a right to possession of the
459 Corresponding Source of the work from the predecessor in interest, if
460 the predecessor has it or can get it with reasonable efforts.
461
462 You may not impose any further restrictions on the exercise of the
463 rights granted or affirmed under this License. For example, you may
464 not impose a license fee, royalty, or other charge for exercise of
465 rights granted under this License, and you may not initiate litigation
466 (including a cross-claim or counterclaim in a lawsuit) alleging that
467 any patent claim is infringed by making, using, selling, offering for
468 sale, or importing the Program or any portion of it.
469
470 11. Patents.
471
472 A "contributor" is a copyright holder who authorizes use under this
473 License of the Program or a work on which the Program is based. The
474 work thus licensed is called the contributor's "contributor version".
475
476 A contributor's "essential patent claims" are all patent claims
477 owned or controlled by the contributor, whether already acquired or
478 hereafter acquired, that would be infringed by some manner, permitted
479 by this License, of making, using, or selling its contributor version,
480 but do not include claims that would be infringed only as a
481 consequence of further modification of the contributor version. For
482 purposes of this definition, "control" includes the right to grant
483 patent sublicenses in a manner consistent with the requirements of
484 this License.
485
486 Each contributor grants you a non-exclusive, worldwide, royalty-free
487 patent license under the contributor's essential patent claims, to
488 make, use, sell, offer for sale, import and otherwise run, modify and
489 propagate the contents of its contributor version.
490
491 In the following three paragraphs, a "patent license" is any express
492 agreement or commitment, however denominated, not to enforce a patent
493 (such as an express permission to practice a patent or covenant not to
494 sue for patent infringement). To "grant" such a patent license to a
495 party means to make such an agreement or commitment not to enforce a
496 patent against the party.
497
498 If you convey a covered work, knowingly relying on a patent license,
499 and the Corresponding Source of the work is not available for anyone
500 to copy, free of charge and under the terms of this License, through a
501 publicly available network server or other readily accessible means,
502 then you must either (1) cause the Corresponding Source to be so
503 available, or (2) arrange to deprive yourself of the benefit of the
504 patent license for this particular work, or (3) arrange, in a manner
505 consistent with the requirements of this License, to extend the patent
506 license to downstream recipients. "Knowingly relying" means you have
507 actual knowledge that, but for the patent license, your conveying the
508 covered work in a country, or your recipient's use of the covered work
509 in a country, would infringe one or more identifiable patents in that
510 country that you have reason to believe are valid.
511
512 If, pursuant to or in connection with a single transaction or
513 arrangement, you convey, or propagate by procuring conveyance of, a
514 covered work, and grant a patent license to some of the parties
515 receiving the covered work authorizing them to use, propagate, modify
516 or convey a specific copy of the covered work, then the patent license
517 you grant is automatically extended to all recipients of the covered
518 work and works based on it.
519
520 A patent license is "discriminatory" if it does not include within
521 the scope of its coverage, prohibits the exercise of, or is
522 conditioned on the non-exercise of one or more of the rights that are
523 specifically granted under this License. You may not convey a covered
524 work if you are a party to an arrangement with a third party that is
525 in the business of distributing software, under which you make payment
526 to the third party based on the extent of your activity of conveying
527 the work, and under which the third party grants, to any of the
528 parties who would receive the covered work from you, a discriminatory
529 patent license (a) in connection with copies of the covered work
530 conveyed by you (or copies made from those copies), or (b) primarily
531 for and in connection with specific products or compilations that
532 contain the covered work, unless you entered into that arrangement,
533 or that patent license was granted, prior to 28 March 2007.
534
535 Nothing in this License shall be construed as excluding or limiting
536 any implied license or other defenses to infringement that may
537 otherwise be available to you under applicable patent law.
538
539 12. No Surrender of Others' Freedom.
540
541 If conditions are imposed on you (whether by court order, agreement or
542 otherwise) that contradict the conditions of this License, they do not
543 excuse you from the conditions of this License. If you cannot convey a
544 covered work so as to satisfy simultaneously your obligations under this
545 License and any other pertinent obligations, then as a consequence you may
546 not convey it at all. For example, if you agree to terms that obligate you
547 to collect a royalty for further conveying from those to whom you convey
548 the Program, the only way you could satisfy both those terms and this
549 License would be to refrain entirely from conveying the Program.
550
551 13. Use with the GNU Affero General Public License.
552
553 Notwithstanding any other provision of this License, you have
554 permission to link or combine any covered work with a work licensed
555 under version 3 of the GNU Affero General Public License into a single
556 combined work, and to convey the resulting work. The terms of this
557 License will continue to apply to the part which is the covered work,
558 but the special requirements of the GNU Affero General Public License,
559 section 13, concerning interaction through a network will apply to the
560 combination as such.
561
562 14. Revised Versions of this License.
563
564 The Free Software Foundation may publish revised and/or new versions of
565 the GNU General Public License from time to time. Such new versions will
566 be similar in spirit to the present version, but may differ in detail to
567 address new problems or concerns.
568
569 Each version is given a distinguishing version number. If the
570 Program specifies that a certain numbered version of the GNU General
571 Public License "or any later version" applies to it, you have the
572 option of following the terms and conditions either of that numbered
573 version or of any later version published by the Free Software
574 Foundation. If the Program does not specify a version number of the
575 GNU General Public License, you may choose any version ever published
576 by the Free Software Foundation.
577
578 If the Program specifies that a proxy can decide which future
579 versions of the GNU General Public License can be used, that proxy's
580 public statement of acceptance of a version permanently authorizes you
581 to choose that version for the Program.
582
583 Later license versions may give you additional or different
584 permissions. However, no additional obligations are imposed on any
585 author or copyright holder as a result of your choosing to follow a
586 later version.
587
588 15. Disclaimer of Warranty.
589
590 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
591 APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
592 HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
593 OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
594 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
595 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
596 IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
597 ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
598
599 16. Limitation of Liability.
600
601 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
602 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
603 THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
604 GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
605 USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
606 DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
607 PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
608 EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
609 SUCH DAMAGES.
610
611 17. Interpretation of Sections 15 and 16.
612
613 If the disclaimer of warranty and limitation of liability provided
614 above cannot be given local legal effect according to their terms,
615 reviewing courts shall apply local law that most closely approximates
616 an absolute waiver of all civil liability in connection with the
617 Program, unless a warranty or assumption of liability accompanies a
618 copy of the Program in return for a fee.
619
620 END OF TERMS AND CONDITIONS
621
622 How to Apply These Terms to Your New Programs
623
624 If you develop a new program, and you want it to be of the greatest
625 possible use to the public, the best way to achieve this is to make it
626 free software which everyone can redistribute and change under these terms.
627
628 To do so, attach the following notices to the program. It is safest
629 to attach them to the start of each source file to most effectively
630 state the exclusion of warranty; and each file should have at least
631 the "copyright" line and a pointer to where the full notice is found.
632
633 {one line to give the program's name and a brief idea of what it does.}
634 Copyright (C) {year} {name of author}
635
636 This program is free software: you can redistribute it and/or modify
637 it under the terms of the GNU General Public License as published by
638 the Free Software Foundation, either version 3 of the License, or
639 (at your option) any later version.
640
641 This program is distributed in the hope that it will be useful,
642 but WITHOUT ANY WARRANTY; without even the implied warranty of
643 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
644 GNU General Public License for more details.
645
646 You should have received a copy of the GNU General Public License
647 along with this program. If not, see <http://www.gnu.org/licenses/>.
648
649 Also add information on how to contact you by electronic and paper mail.
650
651 If the program does terminal interaction, make it output a short
652 notice like this when it starts in an interactive mode:
653
654 {project} Copyright (C) {year} {fullname}
655 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
656 This is free software, and you are welcome to redistribute it
657 under certain conditions; type `show c' for details.
658
659 The hypothetical commands `show w' and `show c' should show the appropriate
660 parts of the General Public License. Of course, your program's commands
661 might be different; for a GUI interface, you would use an "about box".
662
663 You should also get your employer (if you work as a programmer) or school,
664 if any, to sign a "copyright disclaimer" for the program, if necessary.
665 For more information on this, and how to apply and follow the GNU GPL, see
666 <http://www.gnu.org/licenses/>.
667
668 The GNU General Public License does not permit incorporating your program
669 into proprietary programs. If your program is a subroutine library, you
670 may consider it more useful to permit linking proprietary applications with
671 the library. If this is what you want to do, use the GNU Lesser General
672 Public License instead of this License. But first, please read
673 <http://www.gnu.org/philosophy/why-not-lgpl.html>.
+0
-74
dlog/LogManager.cpp less more
0 #include "LogManager.h"
1 #include <Logger.h>
2 #include <ConsoleAppender.h>
3 #include <RollingFileAppender.h>
4
5 namespace Dtk {
6 namespace Log {
7
8 /**
9 * \class DLogManager
10 *
11 * \brief DLogManager is the deepin user application log manager
12 */
13
14 DLogManager::DLogManager()
15 {
16 QString cachePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).at(0);
17 if (!QDir(cachePath).exists()){
18 QDir(cachePath).mkpath(cachePath);
19 }
20 m_logPath = joinPath(cachePath, QString("%1.log").arg(qApp->applicationName()));
21 m_format = "%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [%{file:-20} %{function:-35} %{line}] %{message}\n";
22 }
23
24 void DLogManager::initConsoleAppender(){
25 m_consoleAppender = new ConsoleAppender;
26 m_consoleAppender->setFormat(m_format);
27 logger->registerAppender(m_consoleAppender);
28 }
29
30 void DLogManager::initRollingFileAppender(){
31 m_rollingFileAppender = new RollingFileAppender(m_logPath);
32 m_rollingFileAppender->setFormat(m_format);
33 m_rollingFileAppender->setLogFilesLimit(5);
34 m_rollingFileAppender->setDatePattern(RollingFileAppender::DailyRollover);
35 logger->registerAppender(m_rollingFileAppender);
36 }
37
38 //! Registers the appender to write the log records to the Console
39 /**
40 * \sa registerFileAppender
41 */
42 void DLogManager::registerConsoleAppender(){
43 DLogManager::instance()->initConsoleAppender();
44 }
45
46 //! Registers the appender to write the log records to the file
47 /**
48 * \sa getlogFilePath
49 * \sa registerConsoleAppender
50 */
51 void DLogManager::registerFileAppender() {
52 DLogManager::instance()->initRollingFileAppender();
53 }
54
55 //! Return the path file log storage
56 /**
57 * \sa registerFileAppender
58 */
59 QString DLogManager::getlogFilePath(){
60 return DLogManager::instance()->m_logPath;
61 }
62
63 QString DLogManager::joinPath(const QString &path, const QString &fileName){
64 QString separator(QDir::separator());
65 return QString("%1%2%3").arg(path, separator, fileName);
66 }
67
68 DLogManager::~DLogManager()
69 {
70
71 }
72
73 }}
+0
-45
dlog/LogManager.h less more
0 #ifndef LOGMANAGER_H
1 #define LOGMANAGER_H
2
3 #include <QtCore>
4
5 namespace Dtk {
6 namespace Log {
7
8 class ConsoleAppender;
9 class RollingFileAppender;
10
11 class DLogManager
12 {
13 public:
14 static void registerConsoleAppender();
15 static void registerFileAppender();
16 static QString getlogFilePath();
17
18 signals:
19
20 public slots:
21
22 private:
23 QString m_format;
24 QString m_logPath;
25 ConsoleAppender* m_consoleAppender;
26 RollingFileAppender* m_rollingFileAppender;
27
28 void initConsoleAppender();
29 void initRollingFileAppender();
30 QString joinPath(const QString& path, const QString& fileName);
31
32 inline static DLogManager* instance(){
33 static DLogManager instance;
34 return &instance;
35 }
36 explicit DLogManager();
37 ~DLogManager();
38 DLogManager(const DLogManager &);
39 DLogManager & operator = (const DLogManager &);
40 };
41
42 }}
43
44 #endif // LOGMANAGER_H
+0
-1127
dlog/Logger.cpp less more
0 /*
1 Copyright (c) 2012 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 // Local
14 #include "Logger.h"
15 #include "AbstractAppender.h"
16 #include "AbstractStringAppender.h"
17
18 // Qt
19 #include <QCoreApplication>
20 #include <QReadWriteLock>
21 #include <QSemaphore>
22 #include <QDateTime>
23 #include <QIODevice>
24 #include <QTextCodec>
25
26 #if defined(Q_OS_ANDROID)
27 # include <android/log.h>
28 # include <AndroidAppender.h>
29 #endif
30
31 // STL
32 #include <iostream>
33
34 namespace Dtk {
35 namespace Log {
36
37 /**
38 * \file Logger.h
39 * \brief A file containing the description of Logger class and and additional useful macros for logging
40 */
41
42
43 /**
44 * \mainpage
45 *
46 * Logger is a simple way to write the history of your application lifecycle to any target logging device (which is
47 * called Appender and may write to any target you will implement with it: console, text file, XML or something - you
48 * choose) and to map logging message to a class, function, source file and line of code which it is called from.
49 *
50 * Some simple appenders (which may be considered an examples) are provided with the Logger itself: see ConsoleAppender
51 * and FileAppender documentation.
52 *
53 * It supports using it in a multithreaded applications, so all of its functions are thread safe.
54 *
55 * Simple usage example:
56 * \code
57 * #include <QCoreApplication>
58 *
59 * #include <DLog>
60 *
61 * using namespace Dtk::Log;
62 *
63 * int main(int argc, char* argv[])
64 * {
65 * QCoreApplication app(argc, argv);
66 *
67 * // 1 you can use standrd deepin application log format
68 * // 1.1 log to console
69 * DLogManager::registerConsoleAppender();
70 *
71 * // 1.2 log to standrd deepin user cache path: ~/.cache/{organ}/{appname}/
72 * // app.setOrganizationName("dtk-test"); // must set
73 * // app.setApplicationName("dlog-example"); // must set
74 * // dInfo()<< "LogFile:" << DLogManager::getlogFilePath();
75 * // DLogManager::registerFileAppender();
76 *
77 * // 1.3 log to stdout and file
78 * // DLogManager::registerFileAppender();
79 * // DLogManager::registerConsoleAppender();
80 *
81 * // 2 Register your own logger format;
82 * // ConsoleAppender* consoleAppender = new ConsoleAppender;
83 * // consoleAppender->setFormat("[%{type:-7}] <%{Function}> %{message}\n");
84 * // logger->registerAppender(consoleAppender);
85 *
86 * dInfo("Starting the application");
87 * int result = 1;
88 * dWarning() << "Something went wrong." << "Result code is" << result;
89 * return result;
90 * }
91 * \endcode
92 *
93 * Logger internally uses the lazy-initialized singleton object and needs no definite initialization, but you may
94 * consider registering a log appender before calling any log recording functions or macros.
95 *
96 * The library design of Logger allows you to simply mass-replace all occurrences of qDebug and similar calls with
97 * similar Logger macros (e.g. dDebug())
98 *
99 * \note Logger uses a singleton global instance which lives through all the application life cycle and self-destroys
100 * destruction of the QCoreApplication (or QApplication) instance. It needs a QCoreApplication instance to be
101 * created before any of the Logger's functions are called.
102 *
103 * \sa logger
104 * \sa dTrace, dDebug, dInfo, dWarning, dError, dFatal
105 * \sa dCTrace, dCDebug, dCInfo, dCWarning, dCError, dCFatal
106 * \sa dAssert
107 * \sa dTraceTime, dDebugTime, dInfoTime
108 * \sa AbstractAppender
109 */
110
111
112 /**
113 * \def logger
114 *
115 * \brief Macro returning the current instance of Logger object
116 *
117 * If you haven't created a local Logger object it returns the same value as the Logger::globalInstance() functions.
118 * This macro is a recommended way to get an access to the Logger instance used in current class.
119 *
120 * Example:
121 * \code
122 * ConsoleAppender* consoleAppender = new ConsoleAppender;
123 * logger->registerAppender(consoleAppender);
124 * \endcode
125 *
126 * \sa Dtk::Logger::globalInstance()
127 */
128
129
130 /**
131 * \def dTrace
132 *
133 * \brief Writes the trace log record
134 *
135 * This macro is the convinient way to call Logger::write(). It uses the common preprocessor macros \c __FILE__,
136 * \c __LINE__ and the standart Qt \c Q_FUNC_INFO macros to automatically determine the needed parameters to call
137 * Logger::write().
138 *
139 * \note This and other (dInfo() etc...) macros uses the variadic macro arguments to give convinient usage form for
140 * the different versions of Logger::write() (using the QString or const char* argument or returning the QDebug class
141 * instance). Not all compilers will support this. Please, consider reviewing your compiler documentation to ensure
142 * it support __VA_ARGS__ macro.
143 *
144 * \sa Dtk::Logger::LogLevel
145 * \sa Dtk::Logger::write()
146 */
147
148
149 /**
150 * \def dDebug
151 *
152 * \brief Writes the debug log record
153 *
154 * This macro records the debug log record using the Logger::write() function. It works similar to the dTrace()
155 * macro.
156 *
157 * \sa dTrace()
158 * \sa Dtk::Logger::LogLevel
159 * \sa Dtk::Logger::write()
160 */
161
162
163 /**
164 * \def dInfo
165 *
166 * \brief Writes the info log record
167 *
168 * This macro records the info log record using the Logger::write() function. It works similar to the dTrace()
169 * macro.
170 *
171 * \sa dTrace()
172 * \sa Dtk::Logger::LogLevel
173 * \sa Dtk::Logger::write()
174 */
175
176
177 /**
178 * \def dWarning
179 *
180 * \brief Write the warning log record
181 *
182 * This macro records the warning log record using the Logger::write() function. It works similar to the dTrace()
183 * macro.
184 *
185 * \sa dTrace()
186 * \sa Dtk::Logger::LogLevel
187 * \sa Dtk::Logger::write()
188 */
189
190
191 /**
192 * \def dError
193 *
194 * \brief Write the error log record
195 * This macro records the error log record using the Logger::write() function. It works similar to the dTrace()
196 * macro.
197 *
198 * \sa dTrace()
199 * \sa Dtk::Logger::LogLevel
200 * \sa Dtk::Logger::write()
201 */
202
203
204 /**
205 * \def dFatal
206 *
207 * \brief Write the fatal log record
208 *
209 * This macro records the fatal log record using the Logger::write() function. It works similar to the dTrace()
210 * macro.
211 *
212 * \note Recording of the log record using the Logger::Fatal log level will lead to calling the STL abort()
213 * function, which will interrupt the running of your software and begin the writing of the core dump.
214 *
215 * \sa dTrace()
216 * \sa Dtk::Logger::LogLevel
217 * \sa Dtk::Logger::write()
218 */
219
220
221 /**
222 * \def dCTrace(category)
223 *
224 * \brief Writes the trace log record to the specific category
225 *
226 * This macro is the similar to the dTrace() macro, but has a category parameter
227 * to write only to the category appenders (registered using Logger::registerCategoryAppender() method).
228 *
229 * \param category category name string
230 *
231 * \sa dTrace()
232 * \sa Dtk::Logger::LogLevel
233 * \sa Dtk::Logger::registerCategoryAppender()
234 * \sa Dtk::Logger::write()
235 * \sa dCategory(), dGlobalCategory()
236 */
237
238
239 /**
240 * \def dCDebug
241 *
242 * \brief Writes the debug log record to the specific category
243 *
244 * This macro records the debug log record using the Logger::write() function. It works similar to the dCTrace()
245 * macro.
246 *
247 * \sa dCTrace()
248 */
249
250
251 /**
252 * \def dCInfo
253 *
254 * \brief Writes the info log record to the specific category
255 *
256 * This macro records the info log record using the Logger::write() function. It works similar to the dCTrace()
257 * macro.
258 *
259 * \sa dCTrace()
260 */
261
262
263 /**
264 * \def dCWarning
265 *
266 * \brief Writes the warning log record to the specific category
267 *
268 * This macro records the warning log record using the Logger::write() function. It works similar to the dCTrace()
269 * macro.
270 *
271 * \sa dCTrace()
272 */
273
274
275 /**
276 * \def dCError
277 *
278 * \brief Writes the error log record to the specific category
279 *
280 * This macro records the error log record using the Logger::write() function. It works similar to the dCTrace()
281 * macro.
282 *
283 * \sa dCTrace()
284 */
285
286
287 /**
288 * \def dCFatal
289 *
290 * \brief Write the fatal log record to the specific category
291 *
292 * This macro records the fatal log record using the Logger::write() function. It works similar to the dCTrace()
293 * macro.
294 *
295 * \note Recording of the log record using the Logger::Fatal log level will lead to calling the STL abort()
296 * function, which will interrupt the running of your software and begin the writing of the core dump.
297 *
298 * \sa dCTrace()
299 */
300
301
302 /**
303 * \def dCategory(category)
304 *
305 * \brief Create logger instance inside your custom class to log all messages to the specified category
306 *
307 * This macro is used to pass all log messages inside your custom class to the specific category.
308 * You must include this macro inside your class declaration (similarly to the Q_OBJECT macro).
309 * Internally, this macro redefines loggerInstance() function, creates the local Logger object inside your class and
310 * sets the default category to the specified parameter.
311 *
312 * Thus, any call to loggerInstance() (for example, inside dTrace() macro) will return the local Logger object,
313 * so any logging message will be directed to the default category.
314 *
315 * \note This macro does not register any appender to the newly created logger instance. You should register
316 * logger appenders manually, inside your class.
317 *
318 * Usage example:
319 * \code
320 * class CustomClass : public QObject
321 * {
322 * Q_OBJECT
323 * dCategory("custom_category")
324 * ...
325 * };
326 *
327 * CustomClass::CustomClass(QObject* parent) : QObject(parent)
328 * {
329 * logger->registerAppender(new FileAppender("custom_category_log"));
330 * dTrace() << "Trace to the custom category log";
331 * }
332 * \endcode
333 *
334 * \sa Dtk::Logger::write()
335 * \sa dTrace
336 * \sa Dtk::Logger::registerCategoryAppender()
337 * \sa Dtk::Logger::setDefaultCategory()
338 * \sa dGlobalCategory
339 */
340
341
342 /**
343 * \def dGlobalCategory(category)
344 *
345 * \brief Create logger instance inside your custom class to log all messages both to the specified category and to
346 * the global logger instance.
347 *
348 * This macro is similar to dCategory(), but also passes all log messages to the global logger instance appenders.
349 * It is equal to defining the local category logger using dCategory macro and calling:
350 * \code logger->logToGlobalInstance(logger->defaultCategory(), true); \endcode
351 *
352 * \sa dCategory
353 * \sa Dtk::Logger::logToGlobalInstance()
354 * \sa Dtk::Logger::defaultCategory()
355 * \sa Dtk::Logger::registerCategoryAppender()
356 * \sa Dtk::Logger::write()
357 */
358
359
360
361 /**
362 * \def dAssert
363 *
364 * \brief Check the assertion
365 *
366 * This macro is a convinient and recommended to use way to call Logger::writeAssert() function. It uses the
367 * preprocessor macros (as the dDebug() does) to fill the necessary arguments of the Logger::writeAssert() call. It
368 * also uses undocumented but rather mature and stable \c qt_noop() function (which does nothing) when the assertion
369 * is true.
370 *
371 * Example:
372 * \code
373 * bool b = checkSomething();
374 * ...
375 * dAssert(b == true);
376 * \endcode
377 *
378 * \sa Dtk::Logger::writeAssert()
379 */
380
381
382 /**
383 * \def dTraceTime
384 *
385 * \brief Logs the processing time of current function / code block
386 *
387 * This macro automagically measures the function or code of block execution time and outputs it as a Logger::Trace
388 * level log record.
389 *
390 * Example:
391 * \code
392 * int foo()
393 * {
394 * dTraceTime();
395 * ... // Do some long operations
396 * return 0;
397 * } // Outputs: Function foo finished in <time> ms.
398 * \endcode
399 *
400 * If you are measuring a code of block execution time you may also add a name of block to the macro:
401 * \code
402 * int bar(bool doFoo)
403 * {
404 * dTraceTime();
405 *
406 * if (doFoo)
407 * {
408 * dTraceTime("Foo");
409 * ...
410 * }
411 *
412 * ...
413 * }
414 * // Outputs:
415 * // "Foo" finished in <time1> ms.
416 * // Function bar finished in <time2> ms.
417 * \endcode
418 *
419 * \note Macro switches to logging the seconds instead of milliseconds when the execution time reaches 10000 ms.
420 * \sa dDebugTime, dInfoTime
421 */
422
423
424 /**
425 * \def dDebugTime
426 *
427 * \brief Logs the processing time of current function / code block
428 *
429 * This macro automagically measures the function or code of block execution time and outputs it as a Logger::Debug
430 * level log record. It works similar to dTraceTime() macro.
431 *
432 * \sa dTraceTime
433 */
434
435
436 /**
437 * \def dInfoTime
438 *
439 * \brief Logs the processing time of current function / code block
440 *
441 * This macro automagically measures the function or code of block execution time and outputs it as a Logger::Info
442 * level log record. It works similar to dTraceTime() macro.
443 *
444 * \sa dTraceTime
445 */
446
447
448 /**
449 * \class Logger
450 *
451 * \brief Very simple but rather powerful component which may be used for logging your application activities.
452 *
453 * Global logger instance created on a first access to it (e.g. registering appenders, calling a dDebug() macro
454 * etc.) registers itself as a Qt default message handler and captures all the qDebug/dWarning/qCritical output.
455 *
456 * \note Qt 4 qDebug set of macro doesn't support capturing source function name, file name or line number so we
457 * recommend to use dDebug() and other Logger macros instead.
458 *
459 * \sa logger
460 * \sa [DLogger Documentation](index.html)
461 */
462
463 class LogDevice : public QIODevice
464 {
465 public:
466 LogDevice(Logger* l)
467 : m_logger(l),
468 m_semaphore(1)
469 {}
470
471 void lock(Logger::LogLevel logLevel, const char* file, int line, const char* function, const char* category)
472 {
473 m_semaphore.acquire();
474
475 if (!isOpen())
476 open(QIODevice::WriteOnly);
477
478 m_logLevel = logLevel;
479 m_file = file;
480 m_line = line;
481 m_function = function;
482 m_category = category;
483 }
484
485 protected:
486 qint64 readData(char*, qint64)
487 {
488 return 0;
489 }
490
491 qint64 writeData(const char* data, qint64 maxSize)
492 {
493 if (maxSize > 0)
494 m_logger->write(m_logLevel, m_file, m_line, m_function, m_category, QString::fromLocal8Bit(QByteArray(data, maxSize)));
495
496 m_semaphore.release();
497 return maxSize;
498 }
499
500 private:
501 Logger* m_logger;
502 QSemaphore m_semaphore;
503 Logger::LogLevel m_logLevel;
504 const char* m_file;
505 int m_line;
506 const char* m_function;
507 const char* m_category;
508 };
509
510
511 // Forward declarations
512 static void cleanupLoggerGlobalInstance();
513
514 #if QT_VERSION >= 0x050000
515 static void qtLoggerMessageHandler(QtMsgType, const QMessageLogContext& context, const QString& msg);
516 #else
517 static void qtLoggerMessageHandler(QtMsgType type, const char* msg);
518 #endif
519
520 /**
521 * \internal
522 *
523 * LoggerPrivate class implements the Singleton pattern in a thread-safe way. It contains a static pointer to the
524 * global logger instance protected by QReadWriteLock
525 */
526 class LoggerPrivate
527 {
528 public:
529 static Logger* globalInstance;
530 static QReadWriteLock globalInstanceLock;
531
532 QList<AbstractAppender*> appenders;
533 QMutex loggerMutex;
534
535 QMap<QString, bool> categories;
536 QMultiMap<QString, AbstractAppender*> categoryAppenders;
537 QString defaultCategory;
538
539 LogDevice* logDevice;
540 };
541
542
543 // Static fields initialization
544 Logger* LoggerPrivate::globalInstance = 0;
545 QReadWriteLock LoggerPrivate::globalInstanceLock;
546
547
548 static void cleanupLoggerGlobalInstance()
549 {
550 QWriteLocker locker(&LoggerPrivate::globalInstanceLock);
551
552 delete LoggerPrivate::globalInstance;
553 LoggerPrivate::globalInstance = 0;
554 }
555
556
557 #if QT_VERSION >= 0x050000
558 static void qtLoggerMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
559 {
560 Logger::LogLevel level;
561 switch (type)
562 {
563 case QtDebugMsg:
564 level = Logger::Debug;
565 break;
566 case QtInfoMsg:
567 level = Logger::Info;
568 break;
569 case QtWarningMsg:
570 level = Logger::Warning;
571 break;
572 case QtCriticalMsg:
573 level = Logger::Error;
574 break;
575 case QtFatalMsg:
576 level = Logger::Fatal;
577 break;
578 default:
579 level = Logger::Warning;
580 break;
581 }
582
583 bool isDefaultCategory = QString::fromLatin1(context.category) == "default";
584 Logger::globalInstance()->write(level, context.file, context.line, context.function, isDefaultCategory ? 0 : context.category, msg);
585 }
586
587 #else
588
589 static void qtLoggerMessageHandler(QtMsgType type, const char* msg)
590 {
591 switch (type)
592 {
593 case QtDebugMsg:
594 loggerInstance()->write(Logger::Debug, "", 0, "qDebug", 0, msg);
595 break;
596 case QtWarningMsg:
597 loggerInstance()->write(Logger::Warning, "", 0, "qDebug", 0, msg);
598 break;
599 case QtCriticalMsg:
600 loggerInstance()->write(Logger::Error, "", 0, "qDebug", 0, msg);
601 break;
602 case QtFatalMsg:
603 loggerInstance()->write(Logger::Fatal, "", 0, "qDebug", 0, msg);
604 break;
605 }
606 }
607 #endif
608
609
610 //! Construct the instance of Logger
611 /**
612 * If you're only using one global instance of logger you wouldn't probably need to use this constructor manually.
613 * Consider using [logger](@ref logger) macro instead to access the logger instance
614 */
615 Logger::Logger()
616 : d_ptr(new LoggerPrivate)
617 {
618 Q_D(Logger);
619
620 d->logDevice = new LogDevice(this);
621 }
622
623
624 //! Construct the instance of Logger and set logger default category
625 /**
626 * If you're only using one global instance of logger you wouldn't probably need to use this constructor manually.
627 * Consider using [logger](@ref logger) macro instead to access the logger instance and call
628 * [setDefaultCategory](@ref setDefaultCategory) method.
629 *
630 * \sa Logger()
631 * \sa setDefaultCategory()
632 */
633 Logger::Logger(const QString& defaultCategory)
634 : d_ptr(new LoggerPrivate)
635 {
636 Q_D(Logger);
637 d->logDevice = new LogDevice(this);
638
639 setDefaultCategory(defaultCategory);
640 }
641
642
643 //! Destroy the instance of Logger
644 /**
645 * You probably wouldn't need to use this function directly. Global instance of logger will be destroyed automatically
646 * at the end of your QCoreApplication execution
647 */
648 Logger::~Logger()
649 {
650 Q_D(Logger);
651
652 // Cleanup appenders
653 QMutexLocker appendersLocker(&d->loggerMutex);
654 qDeleteAll(d->appenders);
655 qDeleteAll(d->categoryAppenders);
656
657 // Cleanup device
658 delete d->logDevice;
659 appendersLocker.unlock();
660
661 delete d_ptr;
662 }
663
664
665 //! Converts the LogLevel enum value to its string representation
666 /**
667 * \param logLevel Log level to convert
668 *
669 * \sa LogLevel
670 * \sa levelFromString()
671 */
672 QString Logger::levelToString(Logger::LogLevel logLevel)
673 {
674 switch (logLevel)
675 {
676 case Trace:
677 return QLatin1String("Trace");
678 case Debug:
679 return QLatin1String("Debug");
680 case Info:
681 return QLatin1String("Info");
682 case Warning:
683 return QLatin1String("Warning");
684 case Error:
685 return QLatin1String("Error");
686 case Fatal:
687 return QLatin1String("Fatal");
688 }
689
690 return QString();
691 }
692
693
694 //! Converts the LogLevel string representation to enum value
695 /**
696 * Comparation of the strings is case independent. If the log level string provided cannot be understood
697 * Logger::Debug is returned.
698 *
699 * \param s String to be decoded
700 *
701 * \sa LogLevel
702 * \sa levelToString()
703 */
704 Logger::LogLevel Logger::levelFromString(const QString& s)
705 {
706 QString str = s.trimmed().toLower();
707
708 LogLevel result = Debug;
709
710 if (str == QLatin1String("trace"))
711 result = Trace;
712 else if (str == QLatin1String("debug"))
713 result = Debug;
714 else if (str == QLatin1String("info"))
715 result = Info;
716 else if (str == QLatin1String("warning"))
717 result = Warning;
718 else if (str == QLatin1String("error"))
719 result = Error;
720 else if (str == QLatin1String("fatal"))
721 result = Fatal;
722
723 return result;
724 }
725
726
727 //! Returns the global instance of Logger
728 /**
729 * In a most cases you shouldn't use this function directly. Consider using [logger](@ref logger) macro instead.
730 *
731 * \sa logger
732 */
733 Logger* Logger::globalInstance()
734 {
735 Logger* result = 0;
736 {
737 QReadLocker locker(&LoggerPrivate::globalInstanceLock);
738 result = LoggerPrivate::globalInstance;
739 }
740
741 if (!result)
742 {
743 QWriteLocker locker(&LoggerPrivate::globalInstanceLock);
744 LoggerPrivate::globalInstance = new Logger;
745
746 #if QT_VERSION >= 0x050000
747 qInstallMessageHandler(qtLoggerMessageHandler);
748 #else
749 qInstallMsgHandler(qtLoggerMessageHandler);
750 #endif
751 qAddPostRoutine(cleanupLoggerGlobalInstance);
752 result = LoggerPrivate::globalInstance;
753 }
754
755 return result;
756 }
757
758
759 //! Registers the appender to write the log records to
760 /**
761 * On the log writing call (using one of the macros or the write() function) Logger traverses through the list of
762 * the appenders and writes a log records to the each of them. Please, look through the AbstractAppender
763 * documentation to understand the concept of appenders.
764 *
765 * If no appenders was added to Logger, it falls back to logging into the \c std::cerr STL stream.
766 *
767 * \param appender Appender to register in the Logger
768 *
769 * \note Logger takes ownership on the appender and it will delete it on the application exit. According to this,
770 * appenders must be created on heap to prevent double destruction of the appender.
771 *
772 * \sa registerCategoryAppender
773 * \sa AbstractAppender
774 */
775 void Logger::registerAppender(AbstractAppender* appender)
776 {
777 Q_D(Logger);
778
779 QMutexLocker locker(&d->loggerMutex);
780
781 if (!d->appenders.contains(appender))
782 d->appenders.append(appender);
783 else
784 std::cerr << "Trying to register appender that was already registered" << std::endl;
785 }
786
787 //! Registers the appender to write the log records to the specific category
788 /**
789 * Calling this method, you can link some appender with the named category.
790 * On the log writing call to the specific category (calling write() with category parameter directly,
791 * writing to the default category, or using special dCDebug(), dCWarning() etc. macros),
792 * Logger writes the log message only to the list of registered category appenders.
793 *
794 * You can call logToGlobalInstance() to pass all category log messages to the global logger instance appenders
795 * (registered using registerAppender()).
796 * If no category appenders with specific name was registered to the Logger,
797 * it falls back to logging into the \c std::cerr STL stream, both with simple warning message.
798 *
799 * \param category Category name
800 * \param appender Appender to register in the Logger
801 *
802 * \note Logger takes ownership on the appender and it will delete it on the application exit. According to this,
803 * appenders must be created on heap to prevent double destruction of the appender.
804 *
805 * \sa registerAppender
806 * \sa dCTrace(), dCDebug(), dCInfo(), dCWarning(), dCError(), dCFatal()
807 * \sa dCategory(), dGlobalCategory()
808 * \sa logToGlobalInstance
809 * \sa setDefaultCategory
810 */
811 void Logger::registerCategoryAppender(const QString& category, AbstractAppender* appender)
812 {
813 Q_D(Logger);
814
815 QMutexLocker locker(&d->loggerMutex);
816
817 if (!d->categoryAppenders.values().contains(appender))
818 d->categoryAppenders.insert(category, appender);
819 else
820 std::cerr << "Trying to register appender that was already registered" << std::endl;
821 }
822
823 //! Sets default logging category
824 /**
825 * All log messages to this category appenders will also be written to general logger instance appenders (registered
826 * using [registerAppender](@ref registerAppender) method), and vice versa.
827 * In particular, any calls to the dDebug() macro will be treated as category logging,
828 * so you needn't to specify category name using dCDebug() macro.
829 *
830 * To unset the default category, pass a null string as a parameter.
831 *
832 * \param category Category name
833 *
834 * \note "category" format marker will be set to the category name for all of these messages
835 * (see [AbstractStringAppender::setFormat](@ref AbstractStringAppender::setFormat)).
836 *
837 * \sa defaultCategory()
838 * \sa registerCategoryAppender()
839 * \sa logToGlobalInstance()
840 */
841 void Logger::setDefaultCategory(const QString& category)
842 {
843 Q_D(Logger);
844
845 QMutexLocker locker(&d->loggerMutex);
846
847 d->defaultCategory = category;
848 }
849
850 //! Returns default logging category name
851 /**
852 * \sa setDefaultCategory
853 */
854 QString Logger::defaultCategory() const
855 {
856 Q_D(const Logger);
857 return d->defaultCategory;
858 }
859
860 //! Links some logging category with the global logger instance appenders.
861 /**
862 * If set to true, all log messages to the specified category appenders will also be written to the global logger instance appenders,
863 * registered using registerAppender().
864 *
865 * By default, all messages to the specific category are written only to the specific category appenders
866 * (registered using registerCategoryAppender()).
867 *
868 * \param category Category name
869 * \param logToGlobal Link or onlink the category from global logger instance appender
870 *
871 * \sa globalInstance
872 * \sa registerAppender
873 * \sa registerCategoryAppender
874 */
875 void Logger::logToGlobalInstance(const QString& category, bool logToGlobal)
876 {
877 Q_D(Logger);
878
879 if (this == globalInstance())
880 {
881 QMutexLocker locker(&d->loggerMutex);
882 d->categories.insert(category, logToGlobal);
883 }
884 else
885 {
886 globalInstance()->logToGlobalInstance(category, logToGlobal);
887 }
888 }
889
890
891 void Logger::write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
892 const QString& message, bool fromLocalInstance)
893 {
894 Q_D(Logger);
895
896 QMutexLocker locker(&d->loggerMutex);
897
898 QString logCategory = QString::fromLatin1(category);
899 if (logCategory.isNull() && !d->defaultCategory.isNull())
900 logCategory = d->defaultCategory;
901
902 bool wasWritten = false;
903 bool isGlobalInstance = this == globalInstance();
904 bool linkedToGlobal = isGlobalInstance && d->categories.value(logCategory, false);
905
906 if (!logCategory.isNull())
907 {
908 QList<AbstractAppender*> appenders = d->categoryAppenders.values(logCategory);
909 if (appenders.length() == 0)
910 {
911 if (logCategory != d->defaultCategory && !linkedToGlobal && !fromLocalInstance)
912 std::cerr << "No appenders assotiated with category " << qPrintable(logCategory) << std::endl;
913 }
914 else
915 {
916 foreach (AbstractAppender* appender, appenders)
917 appender->write(timeStamp, logLevel, file, line, function, logCategory, message);
918 wasWritten = true;
919 }
920 }
921
922 // the default category is linked to the main logger appenders
923 // global logger instance also writes all linked categories to the main appenders
924 if (logCategory.isNull() || logCategory == d->defaultCategory || linkedToGlobal)
925 {
926 if (!d->appenders.isEmpty())
927 {
928 foreach (AbstractAppender* appender, d->appenders)
929 appender->write(timeStamp, logLevel, file, line, function, logCategory, message);
930 wasWritten = true;
931 }
932 else
933 {
934 static bool noAppendersWarningShown = false;
935 if (!noAppendersWarningShown)
936 {
937 #if defined(Q_OS_ANDROID)
938 __android_ write(ANDROID_LOG_WARN, "Logger", "No appenders registered with logger");
939 #else
940 std::cerr << "No appenders registered with logger" << std::endl;
941 #endif
942 noAppendersWarningShown = true;
943 }
944 }
945 }
946
947 // local logger instances send category messages to the global instance
948 if (!logCategory.isNull() && !isGlobalInstance)
949 globalInstance()->write(timeStamp, logLevel, file, line, function, logCategory.toLatin1(), message, true);
950
951 if (!wasWritten && !fromLocalInstance)
952 {
953 // Fallback
954 #if defined(Q_OS_ANDROID)
955 QString result = QString(QLatin1String("<%2> %3")).arg(AbstractStringAppender::stripFunctionName(function)).arg(message);
956 __android_log_write(AndroidAppender::androidLogPriority(logLevel), "Logger", qPrintable(result));
957 #else
958 QString result = QString(QLatin1String("[%1] <%2> %3")).arg(levelToString(logLevel), -7)
959 .arg(AbstractStringAppender::stripFunctionName(function)).arg(message);
960 std::cerr << qPrintable(result) << std::endl;
961 #endif
962 }
963
964 if (logLevel == Logger::Fatal)
965 abort();
966 }
967
968
969 //! Writes the log record
970 /**
971 * Writes the log records with the supplied arguments to all the registered appenders.
972 *
973 * \note It is not recommended to call this function directly. Instead of this you can just call one of the macros
974 * (dTrace, dTrac, dInfo, dWarning, dError, dFatal) that will supply all the needed
975 * information to this function.
976 *
977 * \param timeStamp - the time stamp of the record
978 * \param logLevel - the log level of the record
979 * \param file - the name of the source file that requested the log record
980 * \param line - the line of the code of source file that requested the log record
981 * \param function - name of the function that requested the log record
982 * \param category - logging category (0 for default category)
983 * \param message - log message
984 *
985 * \note Recording of the log record using the Logger::Fatal log level will lead to calling the STL abort()
986 * function, which will interrupt the running of your software and begin the writing of the core dump.
987 *
988 * \sa LogLevel
989 * \sa dTrace, dDebug, dInfo, dWarning, dError, dFatal
990 * \sa AbstractAppender
991 */
992 void Logger::write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
993 const QString& message)
994 {
995 write(timeStamp, logLevel, file, line, function, category, message, /* fromLocalInstance = */ false);
996 }
997
998 /**
999 * This is the overloaded function provided for the convinience. It behaves similar to the above function.
1000 *
1001 * This function uses the current timestamp obtained with \c QDateTime::currentDateTime().
1002 *
1003 * \sa write()
1004 */
1005 void Logger::write(LogLevel logLevel, const char* file, int line, const char* function, const char* category,
1006 const QString& message)
1007 {
1008 write(QDateTime::currentDateTime(), logLevel, file, line, function, category, message);
1009 }
1010
1011
1012 /**
1013 * This is the overloaded function provided for the convinience. It behaves similar to the above function.
1014 *
1015 * This function doesn't accept any log message as argument. It returns the \c QDebug object that can be written
1016 * using the stream functions. For example, you may like to write:
1017 * \code
1018 * dDebug() << "This is the size" << size << "of the element" << elementName;
1019 * \endcode
1020 * instead of writing
1021 * \code
1022 * dDebug(QString(QLatin1String("This is the size %1x%2 of the element %3"))
1023 * .arg(size.x()).arg(size.y()).arg(elementName));
1024 * \endcode
1025 *
1026 * Please consider reading the Qt Reference Documentation for the description of the QDebug class usage syntax.
1027 *
1028 * \note This overload is definitely more pleasant to use than the first write() overload, but it behaves definitely
1029 * slower than all the above overloads.
1030 *
1031 * \sa write()
1032 */
1033 QDebug Logger::write(LogLevel logLevel, const char* file, int line, const char* function, const char* category)
1034 {
1035 Q_D(Logger);
1036
1037 d->logDevice->lock(logLevel, file, line, function, category);
1038 return QDebug(d->logDevice);
1039 }
1040
1041
1042 //! Writes the assertion
1043 /**
1044 * This function writes the assertion record using the write() function.
1045 *
1046 * The assertion record is always written using the Logger::Fatal log level which leads to the abortation of the
1047 * program and generation of the core dump (if supported).
1048 *
1049 * The message written to the appenders will be identical to the \c condition argument prefixed with the
1050 * <tt>ASSERT:</tt> notification.
1051 *
1052 * \note It is not recommended to call this function directly. Instead of this you can just call the LOG_ASSERT
1053 * macro that will supply all the needed information to this function.
1054 *
1055 * \sa LOG_ASSERT
1056 * \sa write()
1057 */
1058 void Logger::writeAssert(const char* file, int line, const char* function, const char* condition)
1059 {
1060 write(Logger::Fatal, file, line, function, 0, QString("ASSERT: \"%1\"").arg(condition));
1061 }
1062
1063
1064 Logger* loggerInstance()
1065 {
1066 return Logger::globalInstance();
1067 }
1068
1069
1070
1071 void LoggerTimingHelper::start(const char* msg, ...)
1072 {
1073 va_list va;
1074 va_start(va, msg);
1075 m_block = QString().vsprintf(msg, va);
1076 va_end(va);
1077
1078 m_time.start();
1079 }
1080
1081
1082 void LoggerTimingHelper::start(const QString& block)
1083 {
1084 m_block = block;
1085 m_time.start();
1086 }
1087
1088 LoggerTimingHelper::~LoggerTimingHelper()
1089 {
1090 QString message;
1091 if (m_block.isEmpty())
1092 message = QString(QLatin1String("Function %1 finished in ")).arg(AbstractStringAppender::stripFunctionName(m_function));
1093 else
1094 message = QString(QLatin1String("\"%1\" finished in ")).arg(m_block);
1095
1096 int elapsed = m_time.elapsed();
1097 if (elapsed >= 10000)
1098 message += QString(QLatin1String("%1 s.")).arg(elapsed / 1000);
1099 else
1100 message += QString(QLatin1String("%1 ms.")).arg(elapsed);
1101
1102 m_logger->write(m_logLevel, m_file, m_line, m_function, 0, message);
1103 }
1104
1105
1106 void CuteMessageLogger::write(const char* msg, ...) const
1107 {
1108 va_list va;
1109 va_start(va, msg);
1110 m_l->write(m_level, m_file, m_line, m_function, m_category, QString().vsprintf(msg, va));
1111 va_end(va);
1112 }
1113
1114
1115 void CuteMessageLogger::write(const QString& msg) const
1116 {
1117 m_l->write(m_level, m_file, m_line, m_function, m_category, msg);
1118 }
1119
1120
1121 QDebug CuteMessageLogger::write() const
1122 {
1123 return m_l->write(m_level, m_file, m_line, m_function, m_category);
1124 }
1125
1126 }}
+0
-209
dlog/Logger.h less more
0 /*
1 Copyright (c) 2012 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef LOGGER_H
14 #define LOGGER_H
15
16 // Qt
17 #include <QString>
18 #include <QDebug>
19 #include <QDateTime>
20
21 // Local
22 #include "CuteLogger_global.h"
23
24 namespace Dtk {
25 namespace Log {
26
27 class AbstractAppender;
28 class Logger;
29 CUTELOGGERSHARED_EXPORT Logger* loggerInstance();
30 #define logger loggerInstance()
31
32
33 #define dTrace CuteMessageLogger(loggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO).write
34 #define dDebug CuteMessageLogger(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO).write
35 #define dInfo CuteMessageLogger(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO).write
36 #define dWarning CuteMessageLogger(loggerInstance(), Logger::Warning, __FILE__, __LINE__, Q_FUNC_INFO).write
37 #define dError CuteMessageLogger(loggerInstance(), Logger::Error, __FILE__, __LINE__, Q_FUNC_INFO).write
38 #define dFatal CuteMessageLogger(loggerInstance(), Logger::Fatal, __FILE__, __LINE__, Q_FUNC_INFO).write
39
40 #define dCTrace(category) CuteMessageLogger(loggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
41 #define dCDebug(category) CuteMessageLogger(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
42 #define dCInfo(category) CuteMessageLogger(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
43 #define dCWarning(category) CuteMessageLogger(loggerInstance(), Logger::Warning, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
44 #define dCError(category) CuteMessageLogger(loggerInstance(), Logger::Error, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
45 #define dCFatal(category) CuteMessageLogger(loggerInstance(), Logger::Fatal, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
46
47 #define dTraceTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
48 #define dDebugTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
49 #define dInfoTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
50
51 #define dAssert(cond) ((!(cond)) ? loggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, #cond) : qt_noop())
52 #define dAssertX(cond, msg) ((!(cond)) ? loggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, msg) : qt_noop())
53
54 #define dCategory(category) \
55 private:\
56 Logger* loggerInstance()\
57 {\
58 static Logger customLoggerInstance(category);\
59 return &customLoggerInstance;\
60 }\
61
62 #define dGlobalCategory(category) \
63 private:\
64 Logger* loggerInstance()\
65 {\
66 static Logger customLoggerInstance(category);\
67 customLoggerInstance.logToGlobalInstance(category, true);\
68 return &customLoggerInstance;\
69 }\
70
71
72 class LoggerPrivate;
73 class CUTELOGGERSHARED_EXPORT Logger
74 {
75 Q_DISABLE_COPY(Logger)
76
77 public:
78 Logger();
79 Logger(const QString& defaultCategory);
80 ~Logger();
81
82 //! Describes the possible severity levels of the log records
83 enum LogLevel
84 {
85 Trace, //!< Trace level. Can be used for mostly unneeded records used for internal code tracing.
86 Debug, //!< Debug level. Useful for non-necessary records used for the debugging of the software.
87 Info, //!< Info level. Can be used for informational records, which may be interesting for not only developers.
88 Warning, //!< Warning. May be used to log some non-fatal warnings detected by your application.
89 Error, //!< Error. May be used for a big problems making your application work wrong but not crashing.
90 Fatal //!< Fatal. Used for unrecoverable errors, crashes the application right after the log record is written.
91 };
92
93 static QString levelToString(LogLevel logLevel);
94 static LogLevel levelFromString(const QString& s);
95
96 static Logger* globalInstance();
97
98 void registerAppender(AbstractAppender* appender);
99 void registerCategoryAppender(const QString& category, AbstractAppender* appender);
100
101 void logToGlobalInstance(const QString& category, bool logToGlobal = false);
102
103 void setDefaultCategory(const QString& category);
104 QString defaultCategory() const;
105
106 void write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
107 const QString& message);
108 void write(LogLevel logLevel, const char* file, int line, const char* function, const char* category, const QString& message);
109 QDebug write(LogLevel logLevel, const char* file, int line, const char* function, const char* category);
110
111 void writeAssert(const char* file, int line, const char* function, const char* condition);
112
113 private:
114 void write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
115 const QString& message, bool fromLocalInstance);
116 Q_DECLARE_PRIVATE(Logger)
117 LoggerPrivate* d_ptr;
118 };
119
120
121 class CUTELOGGERSHARED_EXPORT CuteMessageLogger
122 {
123 Q_DISABLE_COPY(CuteMessageLogger)
124
125 public:
126 Q_DECL_CONSTEXPR CuteMessageLogger(Logger* l, Logger::LogLevel level, const char* file, int line, const char* function)
127 : m_l(l),
128 m_level(level),
129 m_file(file),
130 m_line(line),
131 m_function(function),
132 m_category(0)
133 {}
134
135 Q_DECL_CONSTEXPR CuteMessageLogger(Logger* l, Logger::LogLevel level, const char* file, int line, const char* function, const char* category)
136 : m_l(l),
137 m_level(level),
138 m_file(file),
139 m_line(line),
140 m_function(function),
141 m_category(category)
142 {}
143
144 void write(const char* msg, ...) const
145 #if defined(Q_CC_GNU) && !defined(__INSURE__)
146 # if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
147 __attribute__ ((format (gnu_printf, 2, 3)))
148 # else
149 __attribute__ ((format (printf, 2, 3)))
150 # endif
151 #endif
152 ;
153
154 void write(const QString& msg) const;
155
156 QDebug write() const;
157
158 private:
159 Logger* m_l;
160 Logger::LogLevel m_level;
161 const char* m_file;
162 int m_line;
163 const char* m_function;
164 const char* m_category;
165 };
166
167
168 class CUTELOGGERSHARED_EXPORT LoggerTimingHelper
169 {
170 Q_DISABLE_COPY(LoggerTimingHelper)
171
172 public:
173 inline explicit LoggerTimingHelper(Logger* l, Logger::LogLevel logLevel, const char* file, int line,
174 const char* function)
175 : m_logger(l),
176 m_logLevel(logLevel),
177 m_file(file),
178 m_line(line),
179 m_function(function)
180 {}
181
182 void start(const char* msg, ...)
183 #if defined(Q_CC_GNU) && !defined(__INSURE__)
184 # if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
185 __attribute__ ((format (gnu_printf, 2, 3)))
186 # else
187 __attribute__ ((format (printf, 2, 3)))
188 # endif
189 #endif
190 ;
191
192 void start(const QString& msg = QString());
193
194 ~LoggerTimingHelper();
195
196 private:
197 Logger* m_logger;
198 QTime m_time;
199 Logger::LogLevel m_logLevel;
200 const char* m_file;
201 int m_line;
202 const char* m_function;
203 QString m_block;
204 };
205
206 }}
207
208 #endif // LOGGER_H
+0
-46
dlog/OutputDebugAppender.cpp less more
0 /*
1 Copyright (c) 2010 Karl-Heinz Reichel (khreichel at googlemail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 // Local
14 #include "OutputDebugAppender.h"
15
16 // STL
17 #include <windows.h>
18
19 namespace Dtk {
20 namespace Log {
21
22 /**
23 * \class OutputDebugAppender
24 *
25 * \brief Appender that writes the log records to the Microsoft Debug Log
26 */
27
28
29 //! Writes the log record to the windows debug log.
30 /**
31 * \sa AbstractStringAppender::format()
32 */
33 void OutputDebugAppender::append(const QDateTime& timeStamp,
34 Logger::LogLevel logLevel,
35 const char* file,
36 int line,
37 const char* function,
38 const QString& category,
39 const QString& message)
40 {
41 QString s = formattedString(timeStamp, logLevel, file, line, function, category, message);
42 OutputDebugStringW((LPCWSTR) s.utf16());
43 }
44
45 }}
+0
-33
dlog/OutputDebugAppender.h less more
0 /*
1 Copyright (c) 2010 Karl-Heinz Reichel (khreichel at googlemail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13
14 #ifndef OUTPUTDEBUGAPPENDER_H
15 #define OUTPUTDEBUGAPPENDER_H
16
17 #include "CuteLogger_global.h"
18 #include <AbstractStringAppender.h>
19
20 namespace Dtk {
21 namespace Log {
22
23 class CUTELOGGERSHARED_EXPORT OutputDebugAppender : public AbstractStringAppender
24 {
25 protected:
26 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
27 const char* function, const QString& category, const QString& message);
28 };
29
30 }}
31
32 #endif // OUTPUTDEBUGAPPENDER_H
+0
-69
dlog/README.md less more
0 # Deepin Tool Kit Log
1
2 DLog is the log module of deepin tool kit for Qt/C++
3
4 # Install
5
6 ````
7 mkdir build && cd build
8 qmake ..
9 sudo make install
10 ````
11
12 # Usage
13
14 Just add pkgconfig in .pro file
15
16 ````
17 unix {
18 CONFIG+=link_pkgconfig
19 PKGCONFIG+=dtklog
20 }
21 ````
22
23 # Example
24
25 ````
26 #include <QCoreApplication>
27
28 #include <DLog>
29
30 using namespace Dtk::Log;
31
32 int main(int argc, char* argv[])
33 {
34 QCoreApplication app(argc, argv);
35
36 /* 1 you can use standrd deepin application log format */
37 // 1.1 log to console
38 DLogManager::instance()->registerAppender(true);
39 dInfoTime();
40 /* 1.2 log to standrd deepin user cache path: ~/.cache/{organ}/{appname}/ */
41 // app.setOrganizationName("dtk-test"); // must set
42 // app.setApplicationName("dlog-example"); // must set
43 // dInfo()<< "LogFile:" << DLogManager::instance()->getlogFilePath();
44 // DLogManager::instance()->registerAppender(false);
45
46 /* 2 Register your own logger format;*/
47 // ConsoleAppender* consoleAppender = new ConsoleAppender;
48 // consoleAppender->setFormat("[%{type:-7}] <%{Function}> %{message}\n");
49 // logger->registerAppender(consoleAppender);
50
51 dInfo("Starting the application");
52 int result = 1;
53 dWarning() << "Something went wrong." << "Result code is" << result;
54 return result;
55 }
56 ````
57
58 You can get full example from:
59
60 [dlog-example](https://github.com/deepin-tool-kit/dtk-example/tree/master/dlog-example)
61
62 # Document
63
64 ````
65 doxygen -g dlog
66 doxygen -w html
67 firefox html/index
68 ````
+0
-252
dlog/RollingFileAppender.cpp less more
0 #include <QDateTime>
1 #include <QDir>
2 #include <QFileInfo>
3
4 #include "RollingFileAppender.h"
5
6 namespace Dtk {
7 namespace Log {
8
9 RollingFileAppender::RollingFileAppender(const QString& fileName)
10 : FileAppender(fileName),
11 m_logFilesLimit(0)
12 {}
13
14
15 void RollingFileAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
16 const char* function, const QString& category, const QString& message)
17 {
18 if (!m_rollOverTime.isNull() && QDateTime::currentDateTime() > m_rollOverTime)
19 rollOver();
20
21 FileAppender::append(timeStamp, logLevel, file, line, function, category, message);
22 }
23
24
25 RollingFileAppender::DatePattern RollingFileAppender::datePattern() const
26 {
27 QMutexLocker locker(&m_rollingMutex);
28 return m_frequency;
29 }
30
31
32 QString RollingFileAppender::datePatternString() const
33 {
34 QMutexLocker locker(&m_rollingMutex);
35 return m_datePatternString;
36 }
37
38
39 void RollingFileAppender::setDatePattern(DatePattern datePattern)
40 {
41 switch (datePattern)
42 {
43 case MinutelyRollover:
44 setDatePatternString(QLatin1String("'.'yyyy-MM-dd-hh-mm"));
45 break;
46 case HourlyRollover:
47 setDatePatternString(QLatin1String("'.'yyyy-MM-dd-hh"));
48 break;
49 case HalfDailyRollover:
50 setDatePatternString(QLatin1String("'.'yyyy-MM-dd-a"));
51 break;
52 case DailyRollover:
53 setDatePatternString(QLatin1String("'.'yyyy-MM-dd"));
54 break;
55 case WeeklyRollover:
56 setDatePatternString(QLatin1String("'.'yyyy-ww"));
57 break;
58 case MonthlyRollover:
59 setDatePatternString(QLatin1String("'.'yyyy-MM"));
60 break;
61 default:
62 Q_ASSERT_X(false, "DailyRollingFileAppender::setDatePattern()", "Invalid datePattern constant");
63 setDatePattern(DailyRollover);
64 };
65
66 QMutexLocker locker(&m_rollingMutex);
67 m_frequency = datePattern;
68
69 computeRollOverTime();
70 }
71
72
73 void RollingFileAppender::setDatePattern(const QString& datePattern)
74 {
75 setDatePatternString(datePattern);
76 computeFrequency();
77
78 computeRollOverTime();
79 }
80
81
82 void RollingFileAppender::setDatePatternString(const QString& datePatternString)
83 {
84 QMutexLocker locker(&m_rollingMutex);
85 m_datePatternString = datePatternString;
86 }
87
88
89 void RollingFileAppender::computeFrequency()
90 {
91 QMutexLocker locker(&m_rollingMutex);
92
93 const QDateTime startTime(QDate(1999, 1, 1), QTime(0, 0));
94 const QString startString = startTime.toString(m_datePatternString);
95
96 if (startString != startTime.addSecs(60).toString(m_datePatternString))
97 m_frequency = MinutelyRollover;
98 else if (startString != startTime.addSecs(60 * 60).toString(m_datePatternString))
99 m_frequency = HourlyRollover;
100 else if (startString != startTime.addSecs(60 * 60 * 12).toString(m_datePatternString))
101 m_frequency = HalfDailyRollover;
102 else if (startString != startTime.addDays(1).toString(m_datePatternString))
103 m_frequency = DailyRollover;
104 else if (startString != startTime.addDays(7).toString(m_datePatternString))
105 m_frequency = WeeklyRollover;
106 else if (startString != startTime.addMonths(1).toString(m_datePatternString))
107 m_frequency = MonthlyRollover;
108 else
109 {
110 Q_ASSERT_X(false, "DailyRollingFileAppender::computeFrequency", "The pattern '%1' does not specify a frequency");
111 return;
112 }
113 }
114
115
116 void RollingFileAppender::removeOldFiles()
117 {
118 if (m_logFilesLimit <= 1)
119 return;
120
121 QFileInfo fileInfo(fileName());
122 QDir logDirectory(fileInfo.absoluteDir());
123 logDirectory.setFilter(QDir::Files);
124 logDirectory.setNameFilters(QStringList() << fileInfo.fileName() + "*");
125 QFileInfoList logFiles = logDirectory.entryInfoList();
126
127 QMap<QDateTime, QString> fileDates;
128 for (int i = 0; i < logFiles.length(); ++i)
129 {
130 QString name = logFiles[i].fileName();
131 QString suffix = name.mid(name.indexOf(fileInfo.fileName()) + fileInfo.fileName().length());
132 QDateTime fileDateTime = QDateTime::fromString(suffix, datePatternString());
133
134 if (fileDateTime.isValid())
135 fileDates.insert(fileDateTime, logFiles[i].absoluteFilePath());
136 }
137
138 QList<QString> fileDateNames = fileDates.values();
139 for (int i = 0; i < fileDateNames.length() - m_logFilesLimit + 1; ++i)
140 QFile::remove(fileDateNames[i]);
141 }
142
143
144 void RollingFileAppender::computeRollOverTime()
145 {
146 Q_ASSERT_X(!m_datePatternString.isEmpty(), "DailyRollingFileAppender::computeRollOverTime()", "No active date pattern");
147
148 QDateTime now = QDateTime::currentDateTime();
149 QDate nowDate = now.date();
150 QTime nowTime = now.time();
151 QDateTime start;
152
153 switch (m_frequency)
154 {
155 case MinutelyRollover:
156 {
157 start = QDateTime(nowDate, QTime(nowTime.hour(), nowTime.minute(), 0, 0));
158 m_rollOverTime = start.addSecs(60);
159 }
160 break;
161 case HourlyRollover:
162 {
163 start = QDateTime(nowDate, QTime(nowTime.hour(), 0, 0, 0));
164 m_rollOverTime = start.addSecs(60*60);
165 }
166 break;
167 case HalfDailyRollover:
168 {
169 int hour = nowTime.hour();
170 if (hour >= 12)
171 hour = 12;
172 else
173 hour = 0;
174 start = QDateTime(nowDate, QTime(hour, 0, 0, 0));
175 m_rollOverTime = start.addSecs(60*60*12);
176 }
177 break;
178 case DailyRollover:
179 {
180 start = QDateTime(nowDate, QTime(0, 0, 0, 0));
181 m_rollOverTime = start.addDays(1);
182 }
183 break;
184 case WeeklyRollover:
185 {
186 // Qt numbers the week days 1..7. The week starts on Monday.
187 // Change it to being numbered 0..6, starting with Sunday.
188 int day = nowDate.dayOfWeek();
189 if (day == Qt::Sunday)
190 day = 0;
191 start = QDateTime(nowDate, QTime(0, 0, 0, 0)).addDays(-1 * day);
192 m_rollOverTime = start.addDays(7);
193 }
194 break;
195 case MonthlyRollover:
196 {
197 start = QDateTime(QDate(nowDate.year(), nowDate.month(), 1), QTime(0, 0, 0, 0));
198 m_rollOverTime = start.addMonths(1);
199 }
200 break;
201 default:
202 Q_ASSERT_X(false, "DailyRollingFileAppender::computeInterval()", "Invalid datePattern constant");
203 m_rollOverTime = QDateTime::fromTime_t(0);
204 }
205
206 m_rollOverSuffix = start.toString(m_datePatternString);
207 Q_ASSERT_X(now.toString(m_datePatternString) == m_rollOverSuffix,
208 "DailyRollingFileAppender::computeRollOverTime()", "File name changes within interval");
209 Q_ASSERT_X(m_rollOverSuffix != m_rollOverTime.toString(m_datePatternString),
210 "DailyRollingFileAppender::computeRollOverTime()", "File name does not change with rollover");
211 }
212
213
214 void RollingFileAppender::rollOver()
215 {
216 Q_ASSERT_X(!m_datePatternString.isEmpty(), "DailyRollingFileAppender::rollOver()", "No active date pattern");
217
218 QString rollOverSuffix = m_rollOverSuffix;
219 computeRollOverTime();
220 if (rollOverSuffix == m_rollOverSuffix)
221 return;
222
223 closeFile();
224
225 QString targetFileName = fileName() + rollOverSuffix;
226 QFile f(targetFileName);
227 if (f.exists() && !f.remove())
228 return;
229 f.setFileName(fileName());
230 if (!f.rename(targetFileName))
231 return;
232
233 openFile();
234 removeOldFiles();
235 }
236
237
238 void RollingFileAppender::setLogFilesLimit(int limit)
239 {
240 QMutexLocker locker(&m_rollingMutex);
241 m_logFilesLimit = limit;
242 }
243
244
245 int RollingFileAppender::logFilesLimit() const
246 {
247 QMutexLocker locker(&m_rollingMutex);
248 return m_logFilesLimit;
249 }
250
251 }}
+0
-82
dlog/RollingFileAppender.h less more
0 #ifndef ROLLINGFILEAPPENDER_H
1 #define ROLLINGFILEAPPENDER_H
2
3 #include <QDateTime>
4
5 #include <FileAppender.h>
6
7 namespace Dtk {
8 namespace Log {
9
10 /*!
11 * \brief The RollingFileAppender class extends FileAppender so that the underlying file is rolled over at a user chosen frequency.
12 *
13 * The class is based on Log4Qt.DailyRollingFileAppender class (http://log4qt.sourceforge.net/)
14 * and has the same date pattern format.
15 *
16 * For example, if the fileName is set to /foo/bar and the DatePattern set to the daily rollover ('.'yyyy-MM-dd'.log'), on 2014-02-16 at midnight,
17 * the logging file /foo/bar.log will be copied to /foo/bar.2014-02-16.log and logging for 2014-02-17 will continue in /foo/bar
18 * until it rolls over the next day.
19 *
20 * The logFilesLimit parameter is used to automatically delete the oldest log files in the directory during rollover
21 * (so no more than logFilesLimit recent log files exist in the directory at any moment).
22 * \sa setDatePattern(DatePattern), setLogFilesLimit(int)
23 */
24 class CUTELOGGERSHARED_EXPORT RollingFileAppender : public FileAppender
25 {
26 public:
27 /*!
28 * The enum DatePattern defines constants for date patterns.
29 * \sa setDatePattern(DatePattern)
30 */
31 enum DatePattern
32 {
33 /*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */
34 MinutelyRollover = 0,
35 /*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */
36 HourlyRollover,
37 /*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */
38 HalfDailyRollover,
39 /*! The daily date pattern string is "'.'yyyy-MM-dd". */
40 DailyRollover,
41 /*! The weekly date pattern string is "'.'yyyy-ww". */
42 WeeklyRollover,
43 /*! The monthly date pattern string is "'.'yyyy-MM". */
44 MonthlyRollover
45 };
46 Q_ENUMS(DatePattern)
47
48 RollingFileAppender(const QString& fileName = QString());
49
50 DatePattern datePattern() const;
51 void setDatePattern(DatePattern datePattern);
52 void setDatePattern(const QString& datePattern);
53
54 QString datePatternString() const;
55
56 void setLogFilesLimit(int limit);
57 int logFilesLimit() const;
58
59 protected:
60 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
61 const char* function, const QString& category, const QString& message);
62
63 private:
64 void rollOver();
65 void computeRollOverTime();
66 void computeFrequency();
67 void removeOldFiles();
68 void setDatePatternString(const QString& datePatternString);
69
70 QString m_datePatternString;
71 DatePattern m_frequency;
72
73 QDateTime m_rollOverTime;
74 QString m_rollOverSuffix;
75 int m_logFilesLimit;
76 mutable QMutex m_rollingMutex;
77 };
78
79 }}
80
81 #endif // ROLLINGFILEAPPENDER_H
+0
-25
dlog/cutelogger.pri less more
0 INCLUDEPATH += $$PWD
1
2 HEADERS += \
3 $$PWD/RollingFileAppender.h \
4 $$PWD/Logger.h \
5 $$PWD/FileAppender.h \
6 $$PWD/CuteLogger_global.h \
7 $$PWD/ConsoleAppender.h \
8 $$PWD/AbstractStringAppender.h \
9 $$PWD/AbstractAppender.h \
10 $$PWD/LogManager.h
11
12 SOURCES += \
13 $$PWD/RollingFileAppender.cpp \
14 $$PWD/Logger.cpp \
15 $$PWD/FileAppender.cpp \
16 $$PWD/ConsoleAppender.cpp \
17 $$PWD/AbstractStringAppender.cpp \
18 $$PWD/AbstractAppender.cpp \
19 $$PWD/LogManager.cpp
20
21 win32 {
22 SOURCES += $$PWD/OutputDebugAppender.cpp
23 HEADERS += $$PWD/OutputDebugAppender.h
24 }
+0
-20
dlog/dlog.pro less more
0 include($$PWD/../common/lib.pri)
1 include(cutelogger.pri)
2
3 QT -= gui
4
5 TARGET = dtklog
6
7 DEFINES += LIBDTKLOG_LIBRARY
8
9 HEADERS += \
10 DLog
11
12 includes.path = $${DTK_INCLUDEPATH}/DLog
13 includes.files += \
14 DLog \
15 $$system($$PWD/../common/trheader.sh $$PWD/DLog)
16
17 QMAKE_PKGCONFIG_NAME = DTK_LOG
18 QMAKE_PKGCONFIG_DESCRIPTION = Deepin Tool Kit Log Module
19 QMAKE_PKGCONFIG_INCDIR = $$includes.path
11 CONFIG += ordered
22
33 SUBDIRS += \
4 dlog \
4 dutil \
55 dwidget \
0 // Local
1 #include "AbstractAppender.h"
2
3 // Qt
4 #include <QMutexLocker>
5
6 DUTIL_BEGIN_NAMESPACE
7
8 /**
9 * \class AbstractAppender
10 *
11 * \brief The AbstractAppender class provides an abstract base class for writing a log entries.
12 *
13 * The AbstractAppender class is the base interface class for all log appenders that could be used with Logger.
14 *
15 * AbstractAppender provides a common implementation for the thread safe, mutex-protected logging of application
16 * messages, such as ConsoleAppender, FileAppender or something else. AbstractAppender is abstract and can not be
17 * instantiated, but you can use any of its subclasses or create a custom log appender at your choice.
18 *
19 * Appenders are the logical devices that is aimed to be attached to Logger object by calling
20 * Logger::registerAppender(). On each log record call from the application Logger object sequentially calls write()
21 * function on all the appenders registered in it.
22 *
23 * You can subclass AbstractAppender to implement a logging target of any kind you like. It may be the external logging
24 * subsystem (for example, syslog in *nix), XML file, SQL database entries, D-Bus messages or anything else you can
25 * imagine.
26 *
27 * For the simple non-structured plain text logging (for example, to a plain text file or to the console output) you may
28 * like to subclass the AbstractStringAppender instead of AbstractAppender, which will give you a more convinient way to
29 * control the format of the log output.
30 *
31 * \sa AbstractStringAppender
32 * \sa Logger::registerAppender()
33 */
34
35
36 //! Constructs a AbstractAppender object.
37 AbstractAppender::AbstractAppender()
38 : m_detailsLevel(Logger::Debug)
39 {}
40
41
42 //! Destructs the AbstractAppender object.
43 AbstractAppender::~AbstractAppender()
44 {}
45
46
47 //! Returns the current details level of appender.
48 /**
49 * Log records with a log level lower than a current detailsLevel() will be silently ignored by appender and would not
50 * be sent to its append() function.
51 *
52 * It provides additional logging flexibility, allowing you to set the different severity levels for different types
53 * of logs.
54 *
55 * \note This function is thread safe.
56 *
57 * \sa setDetailsLevel()
58 * \sa Logger::LogLevel
59 */
60 Logger::LogLevel AbstractAppender::detailsLevel() const
61 {
62 QMutexLocker locker(&m_detailsLevelMutex);
63 return m_detailsLevel;
64 }
65
66
67 //! Sets the current details level of appender.
68 /**
69 * Default details level is Logger::Debug
70 *
71 * \note This function is thread safe.
72 *
73 * \sa detailsLevel()
74 * \sa Logger::LogLevel
75 */
76 void AbstractAppender::setDetailsLevel(Logger::LogLevel level)
77 {
78 QMutexLocker locker(&m_detailsLevelMutex);
79 m_detailsLevel = level;
80 }
81
82
83
84 //! Sets the current details level of appender
85 /**
86 * This function is provided for convenience, it behaves like an above function.
87 *
88 * \sa detailsLevel()
89 * \sa Logger::LogLevel
90 */
91 void AbstractAppender::setDetailsLevel(const QString& level)
92 {
93 setDetailsLevel(Logger::levelFromString(level));
94 }
95
96
97 //! Tries to write the log record to this logger
98 /**
99 * This is the function called by Logger object to write a log message to the appender.
100 *
101 * \note This function is thread safe.
102 *
103 * \sa Logger::write()
104 * \sa detailsLevel()
105 */
106 void AbstractAppender::write(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
107 const char* function, const QString& category, const QString& message)
108 {
109 if (logLevel >= detailsLevel())
110 {
111 QMutexLocker locker(&m_writeMutex);
112 append(timeStamp, logLevel, file, line, function, category, message);
113 }
114 }
115
116
117 /**
118 * \fn virtual void AbstractAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file,
119 * int line, const char* function, const QString& message)
120 *
121 * \brief Writes the log record to the logger instance
122 *
123 * This function is called every time when user tries to write a message to this AbstractAppender instance using
124 * the write() function. Write function works as proxy and transfers only the messages with log level more or equal
125 * to the current logLevel().
126 *
127 * Overload this function when you are implementing a custom appender.
128 *
129 * \note This function is not needed to be thread safe because it is never called directly by Logger object. The
130 * write() function works as a proxy and protects this function from concurrent access.
131 *
132 * \sa Logger::write()
133 */
134
135 DUTIL_END_NAMESPACE
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef ABSTRACTAPPENDER_H
14 #define ABSTRACTAPPENDER_H
15
16 // Local
17 #include "CuteLogger_global.h"
18 #include <Logger.h>
19
20 // Qt
21 #include <QMutex>
22
23 DUTIL_BEGIN_NAMESPACE
24
25 class CUTELOGGERSHARED_EXPORT AbstractAppender
26 {
27 public:
28 AbstractAppender();
29 virtual ~AbstractAppender();
30
31 Logger::LogLevel detailsLevel() const;
32 void setDetailsLevel(Logger::LogLevel level);
33 void setDetailsLevel(const QString& level);
34
35 void write(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line, const char* function,
36 const QString& category, const QString& message);
37
38 protected:
39 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
40 const char* function, const QString& category, const QString& message) = 0;
41
42 private:
43 QMutex m_writeMutex;
44
45 Logger::LogLevel m_detailsLevel;
46 mutable QMutex m_detailsLevelMutex;
47 };
48
49 DUTIL_END_NAMESPACE
50
51 #endif // ABSTRACTAPPENDER_H
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) Nikolay Matyunin (matyunin.n at gmail dot com)
2
3 Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License version 2.1
7 as published by the Free Software Foundation and appearing in the file
8 LICENSE.LGPL included in the packaging of this file.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14 */
15 // Local
16 #include "AbstractStringAppender.h"
17
18 // Qt
19 #include <QReadLocker>
20 #include <QWriteLocker>
21 #include <QDateTime>
22 #include <QRegExp>
23 #include <QCoreApplication>
24 #include <QThread>
25
26 DUTIL_BEGIN_NAMESPACE
27
28 /**
29 * \class AbstractStringAppender
30 *
31 * \brief The AbstractStringAppender class provides a convinient base for appenders working with plain text formatted
32 * logs.
33 *
34 * AbstractSringAppender is the simple extension of the AbstractAppender class providing the convinient way to create
35 * custom log appenders working with a plain text formatted log targets.
36 *
37 * It have the formattedString() protected function that formats the logging arguments according to a format set with
38 * setFormat().
39 *
40 * This class can not be directly instantiated because it contains pure virtual function inherited from AbstractAppender
41 * class.
42 *
43 * For more detailed description of customizing the log output format see the documentation on the setFormat() function.
44 */
45
46
47 const char formattingMarker = '%';
48
49
50 //! Constructs a new string appender object
51 AbstractStringAppender::AbstractStringAppender()
52 : m_format(QLatin1String("%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n"))
53 {}
54
55
56 //! Returns the current log format string.
57 /**
58 * The default format is set to "%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n". You can set a different log record
59 * format using the setFormat() function.
60 *
61 * \sa setFormat(const QString&)
62 */
63 QString AbstractStringAppender::format() const
64 {
65 QReadLocker locker(&m_formatLock);
66 return m_format;
67 }
68
69
70 //! Sets the logging format for writing strings to the log target with this appender.
71 /**
72 * The string format seems to be very common to those developers who have used a standart sprintf function.
73 *
74 * Log output format is a simple QString with the special markers (starting with % sign) which will be replaced with
75 * it's internal meaning when writing a log record.
76 *
77 * Controlling marker begins with the percent sign (%) which is followed by the command inside {} brackets
78 * (the command describes, what will be put to log record instead of marker).
79 * Optional field width argument may be specified right after the command (through the colon symbol before the closing bracket)
80 * Some commands requires an additional formatting argument (in the second {} brackets).
81 *
82 * Field width argument works almost identically to the \c QString::arg() \c fieldWidth argument (and uses it
83 * internally). For example, \c "%{type:-7}" will be replaced with the left padded debug level of the message
84 * (\c "Debug ") or something. For the more detailed description of it you may consider to look to the Qt
85 * Reference Documentation.
86 *
87 * Supported marker commands are:
88 * \arg \c %{time} - timestamp. You may specify your custom timestamp format using the second {} brackets after the marker,
89 * timestamp format here will be similiar to those used in QDateTime::toString() function. For example,
90 * "%{time}{dd-MM-yyyy, HH:mm}" may be replaced with "17-12-2010, 20:17" depending on current date and time.
91 * The default format used here is "HH:mm:ss.zzz".
92 * \arg \c %{type} - Log level. Possible log levels are shown in the Logger::LogLevel enumerator.
93 * \arg \c %{Type} - Uppercased log level.
94 * \arg \c %{typeOne} - One letter log level.
95 * \arg \c %{TypeOne} - One uppercase letter log level.
96 * \arg \c %{File} - Full source file name (with path) of the file that requested log recording. Uses the \c __FILE__
97 * preprocessor macro.
98 * \arg \c %{file} - Short file name (with stripped path).
99 * \arg \c %{line} - Line number in the source file. Uses the \c __LINE__ preprocessor macro.
100 * \arg \c %{Function} - Name of function that called on of the LOG_* macros. Uses the \c Q_FUNC_INFO macro provided with
101 * Qt.
102 * \arg \c %{function} - Similiar to the %{Function}, but the function name is stripped using stripFunctionName
103 * \arg \c %{message} - The log message sent by the caller.
104 * \arg \c %{category} - The log category.
105 * \arg \c %{appname} - Application name (returned by QCoreApplication::applicationName() function).
106 * \arg \c %{pid} - Application pid (returned by QCoreApplication::applicationPid() function).
107 * \arg \c %{threadid} - ID of current thread.
108 * \arg \c %% - Convinient marker that is replaced with the single \c % mark.
109 *
110 * \note Format doesn't add \c '\\n' to the end of the format line. Please consider adding it manually.
111 *
112 * \sa format()
113 * \sa stripFunctionName()
114 * \sa Logger::LogLevel
115 */
116 void AbstractStringAppender::setFormat(const QString& format)
117 {
118 QWriteLocker locker(&m_formatLock);
119 m_format = format;
120 }
121
122
123 //! Strips the long function signature (as added by Q_FUNC_INFO macro)
124 /**
125 * The string processing drops the returning type, arguments and template parameters of function. It is definitely
126 * useful for enchancing the log output readability.
127 * \return stripped function name
128 */
129 QString AbstractStringAppender::stripFunctionName(const char* name)
130 {
131 return QString::fromLatin1(qCleanupFuncinfo(name));
132 }
133
134
135 // The function was backported from Qt5 sources (qlogging.h)
136 QByteArray AbstractStringAppender::qCleanupFuncinfo(const char* name)
137 {
138 QByteArray info(name);
139
140 // Strip the function info down to the base function name
141 // note that this throws away the template definitions,
142 // the parameter types (overloads) and any const/volatile qualifiers.
143 if (info.isEmpty())
144 return info;
145
146 int pos;
147
148 // skip trailing [with XXX] for templates (gcc)
149 pos = info.size() - 1;
150 if (info.endsWith(']')) {
151 while (--pos) {
152 if (info.at(pos) == '[')
153 info.truncate(pos);
154 }
155 }
156
157 bool hasLambda = false;
158 QRegExp lambdaRegex("::<lambda\\(.*\\)>");
159 int lambdaIndex = lambdaRegex.indexIn(QString::fromLatin1(info));
160 if (lambdaIndex != -1)
161 {
162 hasLambda = true;
163 info.remove(lambdaIndex, lambdaRegex.matchedLength());
164 }
165
166 // operator names with '(', ')', '<', '>' in it
167 static const char operator_call[] = "operator()";
168 static const char operator_lessThan[] = "operator<";
169 static const char operator_greaterThan[] = "operator>";
170 static const char operator_lessThanEqual[] = "operator<=";
171 static const char operator_greaterThanEqual[] = "operator>=";
172
173 // canonize operator names
174 info.replace("operator ", "operator");
175
176 // remove argument list
177 forever {
178 int parencount = 0;
179 pos = info.lastIndexOf(')');
180 if (pos == -1) {
181 // Don't know how to parse this function name
182 return info;
183 }
184
185 // find the beginning of the argument list
186 --pos;
187 ++parencount;
188 while (pos && parencount) {
189 if (info.at(pos) == ')')
190 ++parencount;
191 else if (info.at(pos) == '(')
192 --parencount;
193 --pos;
194 }
195 if (parencount != 0)
196 return info;
197
198 info.truncate(++pos);
199
200 if (info.at(pos - 1) == ')') {
201 if (info.indexOf(operator_call) == pos - (int)strlen(operator_call))
202 break;
203
204 // this function returns a pointer to a function
205 // and we matched the arguments of the return type's parameter list
206 // try again
207 info.remove(0, info.indexOf('('));
208 info.chop(1);
209 continue;
210 } else {
211 break;
212 }
213 }
214
215 if (hasLambda)
216 info.append("::lambda");
217
218 // find the beginning of the function name
219 int parencount = 0;
220 int templatecount = 0;
221 --pos;
222
223 // make sure special characters in operator names are kept
224 if (pos > -1) {
225 switch (info.at(pos)) {
226 case ')':
227 if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1)
228 pos -= 2;
229 break;
230 case '<':
231 if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1)
232 --pos;
233 break;
234 case '>':
235 if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1)
236 --pos;
237 break;
238 case '=': {
239 int operatorLength = (int)strlen(operator_lessThanEqual);
240 if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1)
241 pos -= 2;
242 else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1)
243 pos -= 2;
244 break;
245 }
246 default:
247 break;
248 }
249 }
250
251 while (pos > -1) {
252 if (parencount < 0 || templatecount < 0)
253 return info;
254
255 char c = info.at(pos);
256 if (c == ')')
257 ++parencount;
258 else if (c == '(')
259 --parencount;
260 else if (c == '>')
261 ++templatecount;
262 else if (c == '<')
263 --templatecount;
264 else if (c == ' ' && templatecount == 0 && parencount == 0)
265 break;
266
267 --pos;
268 }
269 info = info.mid(pos + 1);
270
271 // remove trailing '*', '&' that are part of the return argument
272 while ((info.at(0) == '*')
273 || (info.at(0) == '&'))
274 info = info.mid(1);
275
276 // we have the full function name now.
277 // clean up the templates
278 while ((pos = info.lastIndexOf('>')) != -1) {
279 if (!info.contains('<'))
280 break;
281
282 // find the matching close
283 int end = pos;
284 templatecount = 1;
285 --pos;
286 while (pos && templatecount) {
287 register char c = info.at(pos);
288 if (c == '>')
289 ++templatecount;
290 else if (c == '<')
291 --templatecount;
292 --pos;
293 }
294 ++pos;
295 info.remove(pos, end - pos + 1);
296 }
297
298 return info;
299 }
300
301
302 //! Returns the string to record to the logging target, formatted according to the format().
303 /**
304 * \sa format()
305 * \sa setFormat(const QString&)
306 */
307 QString AbstractStringAppender::formattedString(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file,
308 int line, const char* function, const QString& category, const QString& message) const
309 {
310 QString f = format();
311 const int size = f.size();
312
313 QString result;
314
315 int i = 0;
316 while (i < f.size())
317 {
318 QChar c = f.at(i);
319
320 // We will silently ignore the broken % marker at the end of string
321 if (c != QLatin1Char(formattingMarker) || (i + 2) >= size)
322 {
323 result.append(c);
324 }
325 else
326 {
327 i += 2;
328 QChar currentChar = f.at(i);
329 QString command;
330 int fieldWidth = 0;
331
332 if (currentChar.isLetter())
333 {
334 command.append(currentChar);
335 int j = 1;
336 while ((i + j) < size && f.at(i + j).isLetter())
337 {
338 command.append(f.at(i+j));
339 j++;
340 }
341
342 i+=j;
343 currentChar = f.at(i);
344
345 // Check for the padding instruction
346 if (currentChar == QLatin1Char(':'))
347 {
348 currentChar = f.at(++i);
349 if (currentChar.isDigit() || currentChar.category() == QChar::Punctuation_Dash)
350 {
351 int j = 1;
352 while ((i + j) < size && f.at(i + j).isDigit())
353 j++;
354 fieldWidth = f.mid(i, j).toInt();
355
356 i += j;
357 }
358 }
359 }
360
361 // Log record chunk to insert instead of formatting instruction
362 QString chunk;
363
364 // Time stamp
365 if (command == QLatin1String("time"))
366 {
367 if (f.at(i + 1) == QLatin1Char('{'))
368 {
369 int j = 1;
370 while ((i + 2 + j) < size && f.at(i + 2 + j) != QLatin1Char('}'))
371 j++;
372
373 if ((i + 2 + j) < size)
374 {
375 chunk = timeStamp.toString(f.mid(i + 2, j));
376
377 i += j;
378 i += 2;
379 }
380 }
381
382 if (chunk.isNull())
383 chunk = timeStamp.toString(QLatin1String("HH:mm:ss.zzz"));
384 }
385
386 // Log level
387 else if (command == QLatin1String("type"))
388 chunk = Logger::levelToString(logLevel);
389
390 // Uppercased log level
391 else if (command == QLatin1String("Type"))
392 chunk = Logger::levelToString(logLevel).toUpper();
393
394 // One letter log level
395 else if (command == QLatin1String("typeOne"))
396 chunk = Logger::levelToString(logLevel).left(1).toLower();
397
398 // One uppercase letter log level
399 else if (command == QLatin1String("TypeOne"))
400 chunk = Logger::levelToString(logLevel).left(1).toUpper();
401
402 // Filename
403 else if (command == QLatin1String("File"))
404 chunk = QLatin1String(file);
405
406 // Filename without a path
407 else if (command == QLatin1String("file"))
408 chunk = QString(QLatin1String(file)).section('/', -1);
409
410 // Source line number
411 else if (command == QLatin1String("line"))
412 chunk = QString::number(line);
413
414 // Function name, as returned by Q_FUNC_INFO
415 else if (command == QLatin1String("Function"))
416 chunk = QString::fromLatin1(function);
417
418 // Stripped function name
419 else if (command == QLatin1String("function"))
420 chunk = stripFunctionName(function);
421
422 // Log message
423 else if (command == QLatin1String("message"))
424 chunk = message;
425
426 else if (command == QLatin1String("category"))
427 chunk = category;
428
429 // Application pid
430 else if (command == QLatin1String("pid"))
431 chunk = QString::number(QCoreApplication::applicationPid());
432
433 // Appplication name
434 else if (command == QLatin1String("appname"))
435 chunk = QCoreApplication::applicationName();
436
437 // Thread ID (duplicates Qt5 threadid debbuging way)
438 else if (command == QLatin1String("threadid"))
439 chunk = QLatin1String("0x") + QString::number(qlonglong(QThread::currentThread()->currentThread()), 16);
440
441 // We simply replace the double formatting marker (%) with one
442 else if (command == QString(formattingMarker))
443 chunk = QLatin1Char(formattingMarker);
444
445 // Do not process any unknown commands
446 else
447 {
448 chunk = QString(formattingMarker);
449 chunk.append(command);
450 }
451
452 result.append(QString(QLatin1String("%1")).arg(chunk, fieldWidth));
453 }
454
455 ++i;
456 }
457
458 return result;
459 }
460
461 DUTIL_END_NAMESPACE
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef ABSTRACTSTRINGAPPENDER_H
14 #define ABSTRACTSTRINGAPPENDER_H
15
16 // Local
17 #include "CuteLogger_global.h"
18 #include <AbstractAppender.h>
19
20 // Qt
21 #include <QReadWriteLock>
22
23 DUTIL_BEGIN_NAMESPACE
24
25 class CUTELOGGERSHARED_EXPORT AbstractStringAppender : public AbstractAppender
26 {
27 public:
28 AbstractStringAppender();
29
30 virtual QString format() const;
31 void setFormat(const QString&);
32
33 static QString stripFunctionName(const char*);
34
35 protected:
36 QString formattedString(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
37 const char* function, const QString& category, const QString& message) const;
38
39 private:
40 static QByteArray qCleanupFuncinfo(const char*);
41
42 QString m_format;
43 mutable QReadWriteLock m_formatLock;
44 };
45
46 DUTIL_END_NAMESPACE
47
48 #endif // ABSTRACTSTRINGAPPENDER_H
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 // Local
14 #include "ConsoleAppender.h"
15
16 // STL
17 #include <iostream>
18
19 DUTIL_BEGIN_NAMESPACE
20
21 /**
22 * \class ConsoleAppender
23 *
24 * \brief ConsoleAppender is the simple appender that writes the log records to the std::cerr output stream.
25 *
26 * ConsoleAppender uses "[%{type:-7}] <%{function}> %{message}\n" as a default output format. It is similar to the
27 * AbstractStringAppender but doesn't show a timestamp.
28 *
29 * You can modify ConsoleAppender output format without modifying your code by using \c QT_MESSAGE_PATTERN environment
30 * variable. If you need your application to ignore this environment variable you can call
31 * ConsoleAppender::ignoreEnvironmentPattern(true)
32 */
33
34
35 ConsoleAppender::ConsoleAppender()
36 : AbstractStringAppender(),
37 m_ignoreEnvPattern(false)
38 {
39 setFormat("[%{type:-7}] <%{function}> %{message}\n");
40 }
41
42
43 QString ConsoleAppender::format() const
44 {
45 const QString envPattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
46 return (m_ignoreEnvPattern || envPattern.isEmpty()) ? AbstractStringAppender::format() : (envPattern + "\n");
47 }
48
49
50 void ConsoleAppender::ignoreEnvironmentPattern(bool ignore)
51 {
52 m_ignoreEnvPattern = ignore;
53 }
54
55
56 //! Writes the log record to the std::cerr stream.
57 /**
58 * \sa AbstractStringAppender::format()
59 */
60 void ConsoleAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
61 const char* function, const QString& category, const QString& message)
62 {
63 std::cerr << qPrintable(formattedString(timeStamp, logLevel, file, line, function, category, message));
64 }
65
66 DUTIL_END_NAMESPACE
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef CONSOLEAPPENDER_H
14 #define CONSOLEAPPENDER_H
15
16 #include "CuteLogger_global.h"
17 #include <AbstractStringAppender.h>
18
19 DUTIL_BEGIN_NAMESPACE
20
21 class CUTELOGGERSHARED_EXPORT ConsoleAppender : public AbstractStringAppender
22 {
23 public:
24 ConsoleAppender();
25 virtual QString format() const;
26 void ignoreEnvironmentPattern(bool ignore);
27
28 protected:
29 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
30 const char* function, const QString& category, const QString& message);
31
32 private:
33 bool m_ignoreEnvPattern;
34 };
35
36 DUTIL_END_NAMESPACE
37
38 #endif // CONSOLEAPPENDER_H
0 #ifndef CUTELOGGER_GLOBAL_H
1 #define CUTELOGGER_GLOBAL_H
2
3 #include <QtCore/qglobal.h>
4
5 #ifndef DTK_NAMESPACE
6 # define DTK_NAMESPACE Dtk
7 #endif
8
9 #define DUTIL_NAMESPACE Util
10 #define DTK_UTIL_NAMESPACE DTK_NAMESPACE::DUTIL_NAMESPACE
11
12 #if !defined(DUTIL_NAMESPACE)
13 # define DUTIL_BEGIN_NAMESPACE
14 # define DUTIL_END_NAMESPACE
15 # define DUTIL_USE_NAMESPACE
16 #else
17 # define DUTIL_BEGIN_NAMESPACE namespace DTK_NAMESPACE { namespace DUTIL_NAMESPACE {
18 # define DUTIL_END_NAMESPACE }}
19 # define DUTIL_USE_NAMESPACE using namespace DTK_UTIL_NAMESPACE;
20 #endif
21
22 #if defined(CUTELOGGER_LIBRARY)
23 # define CUTELOGGERSHARED_EXPORT Q_DECL_EXPORT
24 #else
25 #if defined(Q_OS_WIN32)
26 # define CUTELOGGERSHARED_EXPORT
27 #else
28 # define CUTELOGGERSHARED_EXPORT Q_DECL_IMPORT
29 #endif
30 #endif
31
32 #endif // CUTELOGGER_GLOBAL_H
0 #include "CuteLogger_global.h"
1 #include "RollingFileAppender.h"
2 #include "Logger.h"
3 #include "LogManager.h"
4 #include "FileAppender.h"
5 #include "ConsoleAppender.h"
6 #include "AbstractStringAppender.h"
7 #include "AbstractAppender.h"
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 // Local
14 #include "FileAppender.h"
15
16 // STL
17 #include <iostream>
18
19 DUTIL_BEGIN_NAMESPACE
20
21 /**
22 * \class FileAppender
23 *
24 * \brief Simple appender that writes the log records to the plain text file.
25 */
26
27
28 //! Constructs the new file appender assigned to file with the given name.
29 FileAppender::FileAppender(const QString& fileName)
30 {
31 setFileName(fileName);
32 }
33
34
35 FileAppender::~FileAppender()
36 {
37 closeFile();
38 }
39
40
41 //! Returns the name set by setFileName() or to the FileAppender constructor.
42 /**
43 * \sa setFileName()
44 */
45 QString FileAppender::fileName() const
46 {
47 QMutexLocker locker(&m_logFileMutex);
48 return m_logFile.fileName();
49 }
50
51
52 //! Sets the name of the file. The name can have no path, a relative path, or an absolute path.
53 /**
54 * \sa fileName()
55 */
56 void FileAppender::setFileName(const QString& s)
57 {
58 QMutexLocker locker(&m_logFileMutex);
59 if (m_logFile.isOpen())
60 m_logFile.close();
61
62 m_logFile.setFileName(s);
63 }
64
65
66 bool FileAppender::openFile()
67 {
68 bool isOpen = m_logFile.isOpen();
69 if (!isOpen)
70 {
71 isOpen = m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
72 if (isOpen)
73 m_logStream.setDevice(&m_logFile);
74 else
75 std::cerr << "<FileAppender::append> Cannot open the log file " << qPrintable(m_logFile.fileName()) << std::endl;
76 }
77 return isOpen;
78 }
79
80
81 //! Write the log record to the file.
82 /**
83 * \sa fileName()
84 * \sa AbstractStringAppender::format()
85 */
86 void FileAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
87 const char* function, const QString& category, const QString& message)
88 {
89 QMutexLocker locker(&m_logFileMutex);
90
91 if (openFile())
92 {
93 m_logStream << formattedString(timeStamp, logLevel, file, line, function, category, message);
94 m_logStream.flush();
95 m_logFile.flush();
96 }
97 }
98
99
100 void FileAppender::closeFile()
101 {
102 QMutexLocker locker(&m_logFileMutex);
103 m_logFile.close();
104 }
105
106 DUTIL_END_NAMESPACE
0 /*
1 Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef FILEAPPENDER_H
14 #define FILEAPPENDER_H
15
16 // Logger
17 #include "CuteLogger_global.h"
18 #include <AbstractStringAppender.h>
19
20 // Qt
21 #include <QFile>
22 #include <QTextStream>
23
24 DUTIL_BEGIN_NAMESPACE
25
26 class CUTELOGGERSHARED_EXPORT FileAppender : public AbstractStringAppender
27 {
28 public:
29 FileAppender(const QString& fileName = QString());
30 ~FileAppender();
31
32 QString fileName() const;
33 void setFileName(const QString&);
34
35 protected:
36 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
37 const char* function, const QString& category, const QString& message);
38 bool openFile();
39 void closeFile();
40
41 private:
42 QFile m_logFile;
43 QTextStream m_logStream;
44 mutable QMutex m_logFileMutex;
45 };
46
47 DUTIL_END_NAMESPACE
48
49 #endif // FILEAPPENDER_H
0 GNU GENERAL PUBLIC LICENSE
1 Version 3, 29 June 2007
2
3 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
4 Everyone is permitted to copy and distribute verbatim copies
5 of this license document, but changing it is not allowed.
6
7 Preamble
8
9 The GNU General Public License is a free, copyleft license for
10 software and other kinds of works.
11
12 The licenses for most software and other practical works are designed
13 to take away your freedom to share and change the works. By contrast,
14 the GNU General Public License is intended to guarantee your freedom to
15 share and change all versions of a program--to make sure it remains free
16 software for all its users. We, the Free Software Foundation, use the
17 GNU General Public License for most of our software; it applies also to
18 any other work released this way by its authors. You can apply it to
19 your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22 price. Our General Public Licenses are designed to make sure that you
23 have the freedom to distribute copies of free software (and charge for
24 them if you wish), that you receive source code or can get it if you
25 want it, that you can change the software or use pieces of it in new
26 free programs, and that you know you can do these things.
27
28 To protect your rights, we need to prevent others from denying you
29 these rights or asking you to surrender the rights. Therefore, you have
30 certain responsibilities if you distribute copies of the software, or if
31 you modify it: responsibilities to respect the freedom of others.
32
33 For example, if you distribute copies of such a program, whether
34 gratis or for a fee, you must pass on to the recipients the same
35 freedoms that you received. You must make sure that they, too, receive
36 or can get the source code. And you must show them these terms so they
37 know their rights.
38
39 Developers that use the GNU GPL protect your rights with two steps:
40 (1) assert copyright on the software, and (2) offer you this License
41 giving you legal permission to copy, distribute and/or modify it.
42
43 For the developers' and authors' protection, the GPL clearly explains
44 that there is no warranty for this free software. For both users' and
45 authors' sake, the GPL requires that modified versions be marked as
46 changed, so that their problems will not be attributed erroneously to
47 authors of previous versions.
48
49 Some devices are designed to deny users access to install or run
50 modified versions of the software inside them, although the manufacturer
51 can do so. This is fundamentally incompatible with the aim of
52 protecting users' freedom to change the software. The systematic
53 pattern of such abuse occurs in the area of products for individuals to
54 use, which is precisely where it is most unacceptable. Therefore, we
55 have designed this version of the GPL to prohibit the practice for those
56 products. If such problems arise substantially in other domains, we
57 stand ready to extend this provision to those domains in future versions
58 of the GPL, as needed to protect the freedom of users.
59
60 Finally, every program is threatened constantly by software patents.
61 States should not allow patents to restrict development and use of
62 software on general-purpose computers, but in those that do, we wish to
63 avoid the special danger that patents applied to a free program could
64 make it effectively proprietary. To prevent this, the GPL assures that
65 patents cannot be used to render the program non-free.
66
67 The precise terms and conditions for copying, distribution and
68 modification follow.
69
70 TERMS AND CONDITIONS
71
72 0. Definitions.
73
74 "This License" refers to version 3 of the GNU General Public License.
75
76 "Copyright" also means copyright-like laws that apply to other kinds of
77 works, such as semiconductor masks.
78
79 "The Program" refers to any copyrightable work licensed under this
80 License. Each licensee is addressed as "you". "Licensees" and
81 "recipients" may be individuals or organizations.
82
83 To "modify" a work means to copy from or adapt all or part of the work
84 in a fashion requiring copyright permission, other than the making of an
85 exact copy. The resulting work is called a "modified version" of the
86 earlier work or a work "based on" the earlier work.
87
88 A "covered work" means either the unmodified Program or a work based
89 on the Program.
90
91 To "propagate" a work means to do anything with it that, without
92 permission, would make you directly or secondarily liable for
93 infringement under applicable copyright law, except executing it on a
94 computer or modifying a private copy. Propagation includes copying,
95 distribution (with or without modification), making available to the
96 public, and in some countries other activities as well.
97
98 To "convey" a work means any kind of propagation that enables other
99 parties to make or receive copies. Mere interaction with a user through
100 a computer network, with no transfer of a copy, is not conveying.
101
102 An interactive user interface displays "Appropriate Legal Notices"
103 to the extent that it includes a convenient and prominently visible
104 feature that (1) displays an appropriate copyright notice, and (2)
105 tells the user that there is no warranty for the work (except to the
106 extent that warranties are provided), that licensees may convey the
107 work under this License, and how to view a copy of this License. If
108 the interface presents a list of user commands or options, such as a
109 menu, a prominent item in the list meets this criterion.
110
111 1. Source Code.
112
113 The "source code" for a work means the preferred form of the work
114 for making modifications to it. "Object code" means any non-source
115 form of a work.
116
117 A "Standard Interface" means an interface that either is an official
118 standard defined by a recognized standards body, or, in the case of
119 interfaces specified for a particular programming language, one that
120 is widely used among developers working in that language.
121
122 The "System Libraries" of an executable work include anything, other
123 than the work as a whole, that (a) is included in the normal form of
124 packaging a Major Component, but which is not part of that Major
125 Component, and (b) serves only to enable use of the work with that
126 Major Component, or to implement a Standard Interface for which an
127 implementation is available to the public in source code form. A
128 "Major Component", in this context, means a major essential component
129 (kernel, window system, and so on) of the specific operating system
130 (if any) on which the executable work runs, or a compiler used to
131 produce the work, or an object code interpreter used to run it.
132
133 The "Corresponding Source" for a work in object code form means all
134 the source code needed to generate, install, and (for an executable
135 work) run the object code and to modify the work, including scripts to
136 control those activities. However, it does not include the work's
137 System Libraries, or general-purpose tools or generally available free
138 programs which are used unmodified in performing those activities but
139 which are not part of the work. For example, Corresponding Source
140 includes interface definition files associated with source files for
141 the work, and the source code for shared libraries and dynamically
142 linked subprograms that the work is specifically designed to require,
143 such as by intimate data communication or control flow between those
144 subprograms and other parts of the work.
145
146 The Corresponding Source need not include anything that users
147 can regenerate automatically from other parts of the Corresponding
148 Source.
149
150 The Corresponding Source for a work in source code form is that
151 same work.
152
153 2. Basic Permissions.
154
155 All rights granted under this License are granted for the term of
156 copyright on the Program, and are irrevocable provided the stated
157 conditions are met. This License explicitly affirms your unlimited
158 permission to run the unmodified Program. The output from running a
159 covered work is covered by this License only if the output, given its
160 content, constitutes a covered work. This License acknowledges your
161 rights of fair use or other equivalent, as provided by copyright law.
162
163 You may make, run and propagate covered works that you do not
164 convey, without conditions so long as your license otherwise remains
165 in force. You may convey covered works to others for the sole purpose
166 of having them make modifications exclusively for you, or provide you
167 with facilities for running those works, provided that you comply with
168 the terms of this License in conveying all material for which you do
169 not control copyright. Those thus making or running the covered works
170 for you must do so exclusively on your behalf, under your direction
171 and control, on terms that prohibit them from making any copies of
172 your copyrighted material outside their relationship with you.
173
174 Conveying under any other circumstances is permitted solely under
175 the conditions stated below. Sublicensing is not allowed; section 10
176 makes it unnecessary.
177
178 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
179
180 No covered work shall be deemed part of an effective technological
181 measure under any applicable law fulfilling obligations under article
182 11 of the WIPO copyright treaty adopted on 20 December 1996, or
183 similar laws prohibiting or restricting circumvention of such
184 measures.
185
186 When you convey a covered work, you waive any legal power to forbid
187 circumvention of technological measures to the extent such circumvention
188 is effected by exercising rights under this License with respect to
189 the covered work, and you disclaim any intention to limit operation or
190 modification of the work as a means of enforcing, against the work's
191 users, your or third parties' legal rights to forbid circumvention of
192 technological measures.
193
194 4. Conveying Verbatim Copies.
195
196 You may convey verbatim copies of the Program's source code as you
197 receive it, in any medium, provided that you conspicuously and
198 appropriately publish on each copy an appropriate copyright notice;
199 keep intact all notices stating that this License and any
200 non-permissive terms added in accord with section 7 apply to the code;
201 keep intact all notices of the absence of any warranty; and give all
202 recipients a copy of this License along with the Program.
203
204 You may charge any price or no price for each copy that you convey,
205 and you may offer support or warranty protection for a fee.
206
207 5. Conveying Modified Source Versions.
208
209 You may convey a work based on the Program, or the modifications to
210 produce it from the Program, in the form of source code under the
211 terms of section 4, provided that you also meet all of these conditions:
212
213 a) The work must carry prominent notices stating that you modified
214 it, and giving a relevant date.
215
216 b) The work must carry prominent notices stating that it is
217 released under this License and any conditions added under section
218 7. This requirement modifies the requirement in section 4 to
219 "keep intact all notices".
220
221 c) You must license the entire work, as a whole, under this
222 License to anyone who comes into possession of a copy. This
223 License will therefore apply, along with any applicable section 7
224 additional terms, to the whole of the work, and all its parts,
225 regardless of how they are packaged. This License gives no
226 permission to license the work in any other way, but it does not
227 invalidate such permission if you have separately received it.
228
229 d) If the work has interactive user interfaces, each must display
230 Appropriate Legal Notices; however, if the Program has interactive
231 interfaces that do not display Appropriate Legal Notices, your
232 work need not make them do so.
233
234 A compilation of a covered work with other separate and independent
235 works, which are not by their nature extensions of the covered work,
236 and which are not combined with it such as to form a larger program,
237 in or on a volume of a storage or distribution medium, is called an
238 "aggregate" if the compilation and its resulting copyright are not
239 used to limit the access or legal rights of the compilation's users
240 beyond what the individual works permit. Inclusion of a covered work
241 in an aggregate does not cause this License to apply to the other
242 parts of the aggregate.
243
244 6. Conveying Non-Source Forms.
245
246 You may convey a covered work in object code form under the terms
247 of sections 4 and 5, provided that you also convey the
248 machine-readable Corresponding Source under the terms of this License,
249 in one of these ways:
250
251 a) Convey the object code in, or embodied in, a physical product
252 (including a physical distribution medium), accompanied by the
253 Corresponding Source fixed on a durable physical medium
254 customarily used for software interchange.
255
256 b) Convey the object code in, or embodied in, a physical product
257 (including a physical distribution medium), accompanied by a
258 written offer, valid for at least three years and valid for as
259 long as you offer spare parts or customer support for that product
260 model, to give anyone who possesses the object code either (1) a
261 copy of the Corresponding Source for all the software in the
262 product that is covered by this License, on a durable physical
263 medium customarily used for software interchange, for a price no
264 more than your reasonable cost of physically performing this
265 conveying of source, or (2) access to copy the
266 Corresponding Source from a network server at no charge.
267
268 c) Convey individual copies of the object code with a copy of the
269 written offer to provide the Corresponding Source. This
270 alternative is allowed only occasionally and noncommercially, and
271 only if you received the object code with such an offer, in accord
272 with subsection 6b.
273
274 d) Convey the object code by offering access from a designated
275 place (gratis or for a charge), and offer equivalent access to the
276 Corresponding Source in the same way through the same place at no
277 further charge. You need not require recipients to copy the
278 Corresponding Source along with the object code. If the place to
279 copy the object code is a network server, the Corresponding Source
280 may be on a different server (operated by you or a third party)
281 that supports equivalent copying facilities, provided you maintain
282 clear directions next to the object code saying where to find the
283 Corresponding Source. Regardless of what server hosts the
284 Corresponding Source, you remain obligated to ensure that it is
285 available for as long as needed to satisfy these requirements.
286
287 e) Convey the object code using peer-to-peer transmission, provided
288 you inform other peers where the object code and Corresponding
289 Source of the work are being offered to the general public at no
290 charge under subsection 6d.
291
292 A separable portion of the object code, whose source code is excluded
293 from the Corresponding Source as a System Library, need not be
294 included in conveying the object code work.
295
296 A "User Product" is either (1) a "consumer product", which means any
297 tangible personal property which is normally used for personal, family,
298 or household purposes, or (2) anything designed or sold for incorporation
299 into a dwelling. In determining whether a product is a consumer product,
300 doubtful cases shall be resolved in favor of coverage. For a particular
301 product received by a particular user, "normally used" refers to a
302 typical or common use of that class of product, regardless of the status
303 of the particular user or of the way in which the particular user
304 actually uses, or expects or is expected to use, the product. A product
305 is a consumer product regardless of whether the product has substantial
306 commercial, industrial or non-consumer uses, unless such uses represent
307 the only significant mode of use of the product.
308
309 "Installation Information" for a User Product means any methods,
310 procedures, authorization keys, or other information required to install
311 and execute modified versions of a covered work in that User Product from
312 a modified version of its Corresponding Source. The information must
313 suffice to ensure that the continued functioning of the modified object
314 code is in no case prevented or interfered with solely because
315 modification has been made.
316
317 If you convey an object code work under this section in, or with, or
318 specifically for use in, a User Product, and the conveying occurs as
319 part of a transaction in which the right of possession and use of the
320 User Product is transferred to the recipient in perpetuity or for a
321 fixed term (regardless of how the transaction is characterized), the
322 Corresponding Source conveyed under this section must be accompanied
323 by the Installation Information. But this requirement does not apply
324 if neither you nor any third party retains the ability to install
325 modified object code on the User Product (for example, the work has
326 been installed in ROM).
327
328 The requirement to provide Installation Information does not include a
329 requirement to continue to provide support service, warranty, or updates
330 for a work that has been modified or installed by the recipient, or for
331 the User Product in which it has been modified or installed. Access to a
332 network may be denied when the modification itself materially and
333 adversely affects the operation of the network or violates the rules and
334 protocols for communication across the network.
335
336 Corresponding Source conveyed, and Installation Information provided,
337 in accord with this section must be in a format that is publicly
338 documented (and with an implementation available to the public in
339 source code form), and must require no special password or key for
340 unpacking, reading or copying.
341
342 7. Additional Terms.
343
344 "Additional permissions" are terms that supplement the terms of this
345 License by making exceptions from one or more of its conditions.
346 Additional permissions that are applicable to the entire Program shall
347 be treated as though they were included in this License, to the extent
348 that they are valid under applicable law. If additional permissions
349 apply only to part of the Program, that part may be used separately
350 under those permissions, but the entire Program remains governed by
351 this License without regard to the additional permissions.
352
353 When you convey a copy of a covered work, you may at your option
354 remove any additional permissions from that copy, or from any part of
355 it. (Additional permissions may be written to require their own
356 removal in certain cases when you modify the work.) You may place
357 additional permissions on material, added by you to a covered work,
358 for which you have or can give appropriate copyright permission.
359
360 Notwithstanding any other provision of this License, for material you
361 add to a covered work, you may (if authorized by the copyright holders of
362 that material) supplement the terms of this License with terms:
363
364 a) Disclaiming warranty or limiting liability differently from the
365 terms of sections 15 and 16 of this License; or
366
367 b) Requiring preservation of specified reasonable legal notices or
368 author attributions in that material or in the Appropriate Legal
369 Notices displayed by works containing it; or
370
371 c) Prohibiting misrepresentation of the origin of that material, or
372 requiring that modified versions of such material be marked in
373 reasonable ways as different from the original version; or
374
375 d) Limiting the use for publicity purposes of names of licensors or
376 authors of the material; or
377
378 e) Declining to grant rights under trademark law for use of some
379 trade names, trademarks, or service marks; or
380
381 f) Requiring indemnification of licensors and authors of that
382 material by anyone who conveys the material (or modified versions of
383 it) with contractual assumptions of liability to the recipient, for
384 any liability that these contractual assumptions directly impose on
385 those licensors and authors.
386
387 All other non-permissive additional terms are considered "further
388 restrictions" within the meaning of section 10. If the Program as you
389 received it, or any part of it, contains a notice stating that it is
390 governed by this License along with a term that is a further
391 restriction, you may remove that term. If a license document contains
392 a further restriction but permits relicensing or conveying under this
393 License, you may add to a covered work material governed by the terms
394 of that license document, provided that the further restriction does
395 not survive such relicensing or conveying.
396
397 If you add terms to a covered work in accord with this section, you
398 must place, in the relevant source files, a statement of the
399 additional terms that apply to those files, or a notice indicating
400 where to find the applicable terms.
401
402 Additional terms, permissive or non-permissive, may be stated in the
403 form of a separately written license, or stated as exceptions;
404 the above requirements apply either way.
405
406 8. Termination.
407
408 You may not propagate or modify a covered work except as expressly
409 provided under this License. Any attempt otherwise to propagate or
410 modify it is void, and will automatically terminate your rights under
411 this License (including any patent licenses granted under the third
412 paragraph of section 11).
413
414 However, if you cease all violation of this License, then your
415 license from a particular copyright holder is reinstated (a)
416 provisionally, unless and until the copyright holder explicitly and
417 finally terminates your license, and (b) permanently, if the copyright
418 holder fails to notify you of the violation by some reasonable means
419 prior to 60 days after the cessation.
420
421 Moreover, your license from a particular copyright holder is
422 reinstated permanently if the copyright holder notifies you of the
423 violation by some reasonable means, this is the first time you have
424 received notice of violation of this License (for any work) from that
425 copyright holder, and you cure the violation prior to 30 days after
426 your receipt of the notice.
427
428 Termination of your rights under this section does not terminate the
429 licenses of parties who have received copies or rights from you under
430 this License. If your rights have been terminated and not permanently
431 reinstated, you do not qualify to receive new licenses for the same
432 material under section 10.
433
434 9. Acceptance Not Required for Having Copies.
435
436 You are not required to accept this License in order to receive or
437 run a copy of the Program. Ancillary propagation of a covered work
438 occurring solely as a consequence of using peer-to-peer transmission
439 to receive a copy likewise does not require acceptance. However,
440 nothing other than this License grants you permission to propagate or
441 modify any covered work. These actions infringe copyright if you do
442 not accept this License. Therefore, by modifying or propagating a
443 covered work, you indicate your acceptance of this License to do so.
444
445 10. Automatic Licensing of Downstream Recipients.
446
447 Each time you convey a covered work, the recipient automatically
448 receives a license from the original licensors, to run, modify and
449 propagate that work, subject to this License. You are not responsible
450 for enforcing compliance by third parties with this License.
451
452 An "entity transaction" is a transaction transferring control of an
453 organization, or substantially all assets of one, or subdividing an
454 organization, or merging organizations. If propagation of a covered
455 work results from an entity transaction, each party to that
456 transaction who receives a copy of the work also receives whatever
457 licenses to the work the party's predecessor in interest had or could
458 give under the previous paragraph, plus a right to possession of the
459 Corresponding Source of the work from the predecessor in interest, if
460 the predecessor has it or can get it with reasonable efforts.
461
462 You may not impose any further restrictions on the exercise of the
463 rights granted or affirmed under this License. For example, you may
464 not impose a license fee, royalty, or other charge for exercise of
465 rights granted under this License, and you may not initiate litigation
466 (including a cross-claim or counterclaim in a lawsuit) alleging that
467 any patent claim is infringed by making, using, selling, offering for
468 sale, or importing the Program or any portion of it.
469
470 11. Patents.
471
472 A "contributor" is a copyright holder who authorizes use under this
473 License of the Program or a work on which the Program is based. The
474 work thus licensed is called the contributor's "contributor version".
475
476 A contributor's "essential patent claims" are all patent claims
477 owned or controlled by the contributor, whether already acquired or
478 hereafter acquired, that would be infringed by some manner, permitted
479 by this License, of making, using, or selling its contributor version,
480 but do not include claims that would be infringed only as a
481 consequence of further modification of the contributor version. For
482 purposes of this definition, "control" includes the right to grant
483 patent sublicenses in a manner consistent with the requirements of
484 this License.
485
486 Each contributor grants you a non-exclusive, worldwide, royalty-free
487 patent license under the contributor's essential patent claims, to
488 make, use, sell, offer for sale, import and otherwise run, modify and
489 propagate the contents of its contributor version.
490
491 In the following three paragraphs, a "patent license" is any express
492 agreement or commitment, however denominated, not to enforce a patent
493 (such as an express permission to practice a patent or covenant not to
494 sue for patent infringement). To "grant" such a patent license to a
495 party means to make such an agreement or commitment not to enforce a
496 patent against the party.
497
498 If you convey a covered work, knowingly relying on a patent license,
499 and the Corresponding Source of the work is not available for anyone
500 to copy, free of charge and under the terms of this License, through a
501 publicly available network server or other readily accessible means,
502 then you must either (1) cause the Corresponding Source to be so
503 available, or (2) arrange to deprive yourself of the benefit of the
504 patent license for this particular work, or (3) arrange, in a manner
505 consistent with the requirements of this License, to extend the patent
506 license to downstream recipients. "Knowingly relying" means you have
507 actual knowledge that, but for the patent license, your conveying the
508 covered work in a country, or your recipient's use of the covered work
509 in a country, would infringe one or more identifiable patents in that
510 country that you have reason to believe are valid.
511
512 If, pursuant to or in connection with a single transaction or
513 arrangement, you convey, or propagate by procuring conveyance of, a
514 covered work, and grant a patent license to some of the parties
515 receiving the covered work authorizing them to use, propagate, modify
516 or convey a specific copy of the covered work, then the patent license
517 you grant is automatically extended to all recipients of the covered
518 work and works based on it.
519
520 A patent license is "discriminatory" if it does not include within
521 the scope of its coverage, prohibits the exercise of, or is
522 conditioned on the non-exercise of one or more of the rights that are
523 specifically granted under this License. You may not convey a covered
524 work if you are a party to an arrangement with a third party that is
525 in the business of distributing software, under which you make payment
526 to the third party based on the extent of your activity of conveying
527 the work, and under which the third party grants, to any of the
528 parties who would receive the covered work from you, a discriminatory
529 patent license (a) in connection with copies of the covered work
530 conveyed by you (or copies made from those copies), or (b) primarily
531 for and in connection with specific products or compilations that
532 contain the covered work, unless you entered into that arrangement,
533 or that patent license was granted, prior to 28 March 2007.
534
535 Nothing in this License shall be construed as excluding or limiting
536 any implied license or other defenses to infringement that may
537 otherwise be available to you under applicable patent law.
538
539 12. No Surrender of Others' Freedom.
540
541 If conditions are imposed on you (whether by court order, agreement or
542 otherwise) that contradict the conditions of this License, they do not
543 excuse you from the conditions of this License. If you cannot convey a
544 covered work so as to satisfy simultaneously your obligations under this
545 License and any other pertinent obligations, then as a consequence you may
546 not convey it at all. For example, if you agree to terms that obligate you
547 to collect a royalty for further conveying from those to whom you convey
548 the Program, the only way you could satisfy both those terms and this
549 License would be to refrain entirely from conveying the Program.
550
551 13. Use with the GNU Affero General Public License.
552
553 Notwithstanding any other provision of this License, you have
554 permission to link or combine any covered work with a work licensed
555 under version 3 of the GNU Affero General Public License into a single
556 combined work, and to convey the resulting work. The terms of this
557 License will continue to apply to the part which is the covered work,
558 but the special requirements of the GNU Affero General Public License,
559 section 13, concerning interaction through a network will apply to the
560 combination as such.
561
562 14. Revised Versions of this License.
563
564 The Free Software Foundation may publish revised and/or new versions of
565 the GNU General Public License from time to time. Such new versions will
566 be similar in spirit to the present version, but may differ in detail to
567 address new problems or concerns.
568
569 Each version is given a distinguishing version number. If the
570 Program specifies that a certain numbered version of the GNU General
571 Public License "or any later version" applies to it, you have the
572 option of following the terms and conditions either of that numbered
573 version or of any later version published by the Free Software
574 Foundation. If the Program does not specify a version number of the
575 GNU General Public License, you may choose any version ever published
576 by the Free Software Foundation.
577
578 If the Program specifies that a proxy can decide which future
579 versions of the GNU General Public License can be used, that proxy's
580 public statement of acceptance of a version permanently authorizes you
581 to choose that version for the Program.
582
583 Later license versions may give you additional or different
584 permissions. However, no additional obligations are imposed on any
585 author or copyright holder as a result of your choosing to follow a
586 later version.
587
588 15. Disclaimer of Warranty.
589
590 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
591 APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
592 HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
593 OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
594 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
595 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
596 IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
597 ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
598
599 16. Limitation of Liability.
600
601 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
602 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
603 THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
604 GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
605 USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
606 DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
607 PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
608 EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
609 SUCH DAMAGES.
610
611 17. Interpretation of Sections 15 and 16.
612
613 If the disclaimer of warranty and limitation of liability provided
614 above cannot be given local legal effect according to their terms,
615 reviewing courts shall apply local law that most closely approximates
616 an absolute waiver of all civil liability in connection with the
617 Program, unless a warranty or assumption of liability accompanies a
618 copy of the Program in return for a fee.
619
620 END OF TERMS AND CONDITIONS
621
622 How to Apply These Terms to Your New Programs
623
624 If you develop a new program, and you want it to be of the greatest
625 possible use to the public, the best way to achieve this is to make it
626 free software which everyone can redistribute and change under these terms.
627
628 To do so, attach the following notices to the program. It is safest
629 to attach them to the start of each source file to most effectively
630 state the exclusion of warranty; and each file should have at least
631 the "copyright" line and a pointer to where the full notice is found.
632
633 {one line to give the program's name and a brief idea of what it does.}
634 Copyright (C) {year} {name of author}
635
636 This program is free software: you can redistribute it and/or modify
637 it under the terms of the GNU General Public License as published by
638 the Free Software Foundation, either version 3 of the License, or
639 (at your option) any later version.
640
641 This program is distributed in the hope that it will be useful,
642 but WITHOUT ANY WARRANTY; without even the implied warranty of
643 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
644 GNU General Public License for more details.
645
646 You should have received a copy of the GNU General Public License
647 along with this program. If not, see <http://www.gnu.org/licenses/>.
648
649 Also add information on how to contact you by electronic and paper mail.
650
651 If the program does terminal interaction, make it output a short
652 notice like this when it starts in an interactive mode:
653
654 {project} Copyright (C) {year} {fullname}
655 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
656 This is free software, and you are welcome to redistribute it
657 under certain conditions; type `show c' for details.
658
659 The hypothetical commands `show w' and `show c' should show the appropriate
660 parts of the General Public License. Of course, your program's commands
661 might be different; for a GUI interface, you would use an "about box".
662
663 You should also get your employer (if you work as a programmer) or school,
664 if any, to sign a "copyright disclaimer" for the program, if necessary.
665 For more information on this, and how to apply and follow the GNU GPL, see
666 <http://www.gnu.org/licenses/>.
667
668 The GNU General Public License does not permit incorporating your program
669 into proprietary programs. If your program is a subroutine library, you
670 may consider it more useful to permit linking proprietary applications with
671 the library. If this is what you want to do, use the GNU Lesser General
672 Public License instead of this License. But first, please read
673 <http://www.gnu.org/philosophy/why-not-lgpl.html>.
0 #include "LogManager.h"
1 #include <Logger.h>
2 #include <ConsoleAppender.h>
3 #include <RollingFileAppender.h>
4
5 DUTIL_BEGIN_NAMESPACE
6
7 /**
8 * \class DLogManager
9 *
10 * \brief DLogManager is the deepin user application log manager
11 */
12
13 DLogManager::DLogManager()
14 {
15 QString cachePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).at(0);
16 if (!QDir(cachePath).exists()){
17 QDir(cachePath).mkpath(cachePath);
18 }
19 m_logPath = joinPath(cachePath, QString("%1.log").arg(qApp->applicationName()));
20 m_format = "%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [%{file:-20} %{function:-35} %{line}] %{message}\n";
21 }
22
23 void DLogManager::initConsoleAppender(){
24 m_consoleAppender = new ConsoleAppender;
25 m_consoleAppender->setFormat(m_format);
26 logger->registerAppender(m_consoleAppender);
27 }
28
29 void DLogManager::initRollingFileAppender(){
30 m_rollingFileAppender = new RollingFileAppender(m_logPath);
31 m_rollingFileAppender->setFormat(m_format);
32 m_rollingFileAppender->setLogFilesLimit(5);
33 m_rollingFileAppender->setDatePattern(RollingFileAppender::DailyRollover);
34 logger->registerAppender(m_rollingFileAppender);
35 }
36
37 //! Registers the appender to write the log records to the Console
38 /**
39 * \sa registerFileAppender
40 */
41 void DLogManager::registerConsoleAppender(){
42 DLogManager::instance()->initConsoleAppender();
43 }
44
45 //! Registers the appender to write the log records to the file
46 /**
47 * \sa getlogFilePath
48 * \sa registerConsoleAppender
49 */
50 void DLogManager::registerFileAppender() {
51 DLogManager::instance()->initRollingFileAppender();
52 }
53
54 //! Return the path file log storage
55 /**
56 * \sa registerFileAppender
57 */
58 QString DLogManager::getlogFilePath(){
59 return DLogManager::instance()->m_logPath;
60 }
61
62 QString DLogManager::joinPath(const QString &path, const QString &fileName){
63 QString separator(QDir::separator());
64 return QString("%1%2%3").arg(path, separator, fileName);
65 }
66
67 DLogManager::~DLogManager()
68 {
69
70 }
71
72 DUTIL_END_NAMESPACE
0 #ifndef LOGMANAGER_H
1 #define LOGMANAGER_H
2
3 #include <QtCore>
4
5 #include "CuteLogger_global.h"
6
7 DUTIL_BEGIN_NAMESPACE
8
9 class ConsoleAppender;
10 class RollingFileAppender;
11
12 class DLogManager
13 {
14 public:
15 static void registerConsoleAppender();
16 static void registerFileAppender();
17 static QString getlogFilePath();
18
19 signals:
20
21 public slots:
22
23 private:
24 QString m_format;
25 QString m_logPath;
26 ConsoleAppender* m_consoleAppender;
27 RollingFileAppender* m_rollingFileAppender;
28
29 void initConsoleAppender();
30 void initRollingFileAppender();
31 QString joinPath(const QString& path, const QString& fileName);
32
33 inline static DLogManager* instance(){
34 static DLogManager instance;
35 return &instance;
36 }
37 explicit DLogManager();
38 ~DLogManager();
39 DLogManager(const DLogManager &);
40 DLogManager & operator = (const DLogManager &);
41 };
42
43 DUTIL_END_NAMESPACE
44
45 #endif // LOGMANAGER_H
0 /*
1 Copyright (c) 2012 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 // Local
14 #include "Logger.h"
15 #include "AbstractAppender.h"
16 #include "AbstractStringAppender.h"
17
18 // Qt
19 #include <QCoreApplication>
20 #include <QReadWriteLock>
21 #include <QSemaphore>
22 #include <QDateTime>
23 #include <QIODevice>
24 #include <QTextCodec>
25
26 #if defined(Q_OS_ANDROID)
27 # include <android/log.h>
28 # include <AndroidAppender.h>
29 #endif
30
31 // STL
32 #include <iostream>
33
34 DUTIL_BEGIN_NAMESPACE
35
36 /**
37 * \file Logger.h
38 * \brief A file containing the description of Logger class and and additional useful macros for logging
39 */
40
41
42 /**
43 * \mainpage
44 *
45 * Logger is a simple way to write the history of your application lifecycle to any target logging device (which is
46 * called Appender and may write to any target you will implement with it: console, text file, XML or something - you
47 * choose) and to map logging message to a class, function, source file and line of code which it is called from.
48 *
49 * Some simple appenders (which may be considered an examples) are provided with the Logger itself: see ConsoleAppender
50 * and FileAppender documentation.
51 *
52 * It supports using it in a multithreaded applications, so all of its functions are thread safe.
53 *
54 * Simple usage example:
55 * \code
56 * #include <QCoreApplication>
57 *
58 * #include <DLog>
59 *
60 * using namespace Dtk::Log;
61 *
62 * int main(int argc, char* argv[])
63 * {
64 * QCoreApplication app(argc, argv);
65 *
66 * // 1 you can use standrd deepin application log format
67 * // 1.1 log to console
68 * DLogManager::registerConsoleAppender();
69 *
70 * // 1.2 log to standrd deepin user cache path: ~/.cache/{organ}/{appname}/
71 * // app.setOrganizationName("dtk-test"); // must set
72 * // app.setApplicationName("dlog-example"); // must set
73 * // dInfo()<< "LogFile:" << DLogManager::getlogFilePath();
74 * // DLogManager::registerFileAppender();
75 *
76 * // 1.3 log to stdout and file
77 * // DLogManager::registerFileAppender();
78 * // DLogManager::registerConsoleAppender();
79 *
80 * // 2 Register your own logger format;
81 * // ConsoleAppender* consoleAppender = new ConsoleAppender;
82 * // consoleAppender->setFormat("[%{type:-7}] <%{Function}> %{message}\n");
83 * // logger->registerAppender(consoleAppender);
84 *
85 * dInfo("Starting the application");
86 * int result = 1;
87 * dWarning() << "Something went wrong." << "Result code is" << result;
88 * return result;
89 * }
90 * \endcode
91 *
92 * Logger internally uses the lazy-initialized singleton object and needs no definite initialization, but you may
93 * consider registering a log appender before calling any log recording functions or macros.
94 *
95 * The library design of Logger allows you to simply mass-replace all occurrences of qDebug and similar calls with
96 * similar Logger macros (e.g. dDebug())
97 *
98 * \note Logger uses a singleton global instance which lives through all the application life cycle and self-destroys
99 * destruction of the QCoreApplication (or QApplication) instance. It needs a QCoreApplication instance to be
100 * created before any of the Logger's functions are called.
101 *
102 * \sa logger
103 * \sa dTrace, dDebug, dInfo, dWarning, dError, dFatal
104 * \sa dCTrace, dCDebug, dCInfo, dCWarning, dCError, dCFatal
105 * \sa dAssert
106 * \sa dTraceTime, dDebugTime, dInfoTime
107 * \sa AbstractAppender
108 */
109
110
111 /**
112 * \def logger
113 *
114 * \brief Macro returning the current instance of Logger object
115 *
116 * If you haven't created a local Logger object it returns the same value as the Logger::globalInstance() functions.
117 * This macro is a recommended way to get an access to the Logger instance used in current class.
118 *
119 * Example:
120 * \code
121 * ConsoleAppender* consoleAppender = new ConsoleAppender;
122 * logger->registerAppender(consoleAppender);
123 * \endcode
124 *
125 * \sa Dtk::Logger::globalInstance()
126 */
127
128
129 /**
130 * \def dTrace
131 *
132 * \brief Writes the trace log record
133 *
134 * This macro is the convinient way to call Logger::write(). It uses the common preprocessor macros \c __FILE__,
135 * \c __LINE__ and the standart Qt \c Q_FUNC_INFO macros to automatically determine the needed parameters to call
136 * Logger::write().
137 *
138 * \note This and other (dInfo() etc...) macros uses the variadic macro arguments to give convinient usage form for
139 * the different versions of Logger::write() (using the QString or const char* argument or returning the QDebug class
140 * instance). Not all compilers will support this. Please, consider reviewing your compiler documentation to ensure
141 * it support __VA_ARGS__ macro.
142 *
143 * \sa Dtk::Logger::LogLevel
144 * \sa Dtk::Logger::write()
145 */
146
147
148 /**
149 * \def dDebug
150 *
151 * \brief Writes the debug log record
152 *
153 * This macro records the debug log record using the Logger::write() function. It works similar to the dTrace()
154 * macro.
155 *
156 * \sa dTrace()
157 * \sa Dtk::Logger::LogLevel
158 * \sa Dtk::Logger::write()
159 */
160
161
162 /**
163 * \def dInfo
164 *
165 * \brief Writes the info log record
166 *
167 * This macro records the info log record using the Logger::write() function. It works similar to the dTrace()
168 * macro.
169 *
170 * \sa dTrace()
171 * \sa Dtk::Logger::LogLevel
172 * \sa Dtk::Logger::write()
173 */
174
175
176 /**
177 * \def dWarning
178 *
179 * \brief Write the warning log record
180 *
181 * This macro records the warning log record using the Logger::write() function. It works similar to the dTrace()
182 * macro.
183 *
184 * \sa dTrace()
185 * \sa Dtk::Logger::LogLevel
186 * \sa Dtk::Logger::write()
187 */
188
189
190 /**
191 * \def dError
192 *
193 * \brief Write the error log record
194 * This macro records the error log record using the Logger::write() function. It works similar to the dTrace()
195 * macro.
196 *
197 * \sa dTrace()
198 * \sa Dtk::Logger::LogLevel
199 * \sa Dtk::Logger::write()
200 */
201
202
203 /**
204 * \def dFatal
205 *
206 * \brief Write the fatal log record
207 *
208 * This macro records the fatal log record using the Logger::write() function. It works similar to the dTrace()
209 * macro.
210 *
211 * \note Recording of the log record using the Logger::Fatal log level will lead to calling the STL abort()
212 * function, which will interrupt the running of your software and begin the writing of the core dump.
213 *
214 * \sa dTrace()
215 * \sa Dtk::Logger::LogLevel
216 * \sa Dtk::Logger::write()
217 */
218
219
220 /**
221 * \def dCTrace(category)
222 *
223 * \brief Writes the trace log record to the specific category
224 *
225 * This macro is the similar to the dTrace() macro, but has a category parameter
226 * to write only to the category appenders (registered using Logger::registerCategoryAppender() method).
227 *
228 * \param category category name string
229 *
230 * \sa dTrace()
231 * \sa Dtk::Logger::LogLevel
232 * \sa Dtk::Logger::registerCategoryAppender()
233 * \sa Dtk::Logger::write()
234 * \sa dCategory(), dGlobalCategory()
235 */
236
237
238 /**
239 * \def dCDebug
240 *
241 * \brief Writes the debug log record to the specific category
242 *
243 * This macro records the debug log record using the Logger::write() function. It works similar to the dCTrace()
244 * macro.
245 *
246 * \sa dCTrace()
247 */
248
249
250 /**
251 * \def dCInfo
252 *
253 * \brief Writes the info log record to the specific category
254 *
255 * This macro records the info log record using the Logger::write() function. It works similar to the dCTrace()
256 * macro.
257 *
258 * \sa dCTrace()
259 */
260
261
262 /**
263 * \def dCWarning
264 *
265 * \brief Writes the warning log record to the specific category
266 *
267 * This macro records the warning log record using the Logger::write() function. It works similar to the dCTrace()
268 * macro.
269 *
270 * \sa dCTrace()
271 */
272
273
274 /**
275 * \def dCError
276 *
277 * \brief Writes the error log record to the specific category
278 *
279 * This macro records the error log record using the Logger::write() function. It works similar to the dCTrace()
280 * macro.
281 *
282 * \sa dCTrace()
283 */
284
285
286 /**
287 * \def dCFatal
288 *
289 * \brief Write the fatal log record to the specific category
290 *
291 * This macro records the fatal log record using the Logger::write() function. It works similar to the dCTrace()
292 * macro.
293 *
294 * \note Recording of the log record using the Logger::Fatal log level will lead to calling the STL abort()
295 * function, which will interrupt the running of your software and begin the writing of the core dump.
296 *
297 * \sa dCTrace()
298 */
299
300
301 /**
302 * \def dCategory(category)
303 *
304 * \brief Create logger instance inside your custom class to log all messages to the specified category
305 *
306 * This macro is used to pass all log messages inside your custom class to the specific category.
307 * You must include this macro inside your class declaration (similarly to the Q_OBJECT macro).
308 * Internally, this macro redefines loggerInstance() function, creates the local Logger object inside your class and
309 * sets the default category to the specified parameter.
310 *
311 * Thus, any call to loggerInstance() (for example, inside dTrace() macro) will return the local Logger object,
312 * so any logging message will be directed to the default category.
313 *
314 * \note This macro does not register any appender to the newly created logger instance. You should register
315 * logger appenders manually, inside your class.
316 *
317 * Usage example:
318 * \code
319 * class CustomClass : public QObject
320 * {
321 * Q_OBJECT
322 * dCategory("custom_category")
323 * ...
324 * };
325 *
326 * CustomClass::CustomClass(QObject* parent) : QObject(parent)
327 * {
328 * logger->registerAppender(new FileAppender("custom_category_log"));
329 * dTrace() << "Trace to the custom category log";
330 * }
331 * \endcode
332 *
333 * \sa Dtk::Logger::write()
334 * \sa dTrace
335 * \sa Dtk::Logger::registerCategoryAppender()
336 * \sa Dtk::Logger::setDefaultCategory()
337 * \sa dGlobalCategory
338 */
339
340
341 /**
342 * \def dGlobalCategory(category)
343 *
344 * \brief Create logger instance inside your custom class to log all messages both to the specified category and to
345 * the global logger instance.
346 *
347 * This macro is similar to dCategory(), but also passes all log messages to the global logger instance appenders.
348 * It is equal to defining the local category logger using dCategory macro and calling:
349 * \code logger->logToGlobalInstance(logger->defaultCategory(), true); \endcode
350 *
351 * \sa dCategory
352 * \sa Dtk::Logger::logToGlobalInstance()
353 * \sa Dtk::Logger::defaultCategory()
354 * \sa Dtk::Logger::registerCategoryAppender()
355 * \sa Dtk::Logger::write()
356 */
357
358
359
360 /**
361 * \def dAssert
362 *
363 * \brief Check the assertion
364 *
365 * This macro is a convinient and recommended to use way to call Logger::writeAssert() function. It uses the
366 * preprocessor macros (as the dDebug() does) to fill the necessary arguments of the Logger::writeAssert() call. It
367 * also uses undocumented but rather mature and stable \c qt_noop() function (which does nothing) when the assertion
368 * is true.
369 *
370 * Example:
371 * \code
372 * bool b = checkSomething();
373 * ...
374 * dAssert(b == true);
375 * \endcode
376 *
377 * \sa Dtk::Logger::writeAssert()
378 */
379
380
381 /**
382 * \def dTraceTime
383 *
384 * \brief Logs the processing time of current function / code block
385 *
386 * This macro automagically measures the function or code of block execution time and outputs it as a Logger::Trace
387 * level log record.
388 *
389 * Example:
390 * \code
391 * int foo()
392 * {
393 * dTraceTime();
394 * ... // Do some long operations
395 * return 0;
396 * } // Outputs: Function foo finished in <time> ms.
397 * \endcode
398 *
399 * If you are measuring a code of block execution time you may also add a name of block to the macro:
400 * \code
401 * int bar(bool doFoo)
402 * {
403 * dTraceTime();
404 *
405 * if (doFoo)
406 * {
407 * dTraceTime("Foo");
408 * ...
409 * }
410 *
411 * ...
412 * }
413 * // Outputs:
414 * // "Foo" finished in <time1> ms.
415 * // Function bar finished in <time2> ms.
416 * \endcode
417 *
418 * \note Macro switches to logging the seconds instead of milliseconds when the execution time reaches 10000 ms.
419 * \sa dDebugTime, dInfoTime
420 */
421
422
423 /**
424 * \def dDebugTime
425 *
426 * \brief Logs the processing time of current function / code block
427 *
428 * This macro automagically measures the function or code of block execution time and outputs it as a Logger::Debug
429 * level log record. It works similar to dTraceTime() macro.
430 *
431 * \sa dTraceTime
432 */
433
434
435 /**
436 * \def dInfoTime
437 *
438 * \brief Logs the processing time of current function / code block
439 *
440 * This macro automagically measures the function or code of block execution time and outputs it as a Logger::Info
441 * level log record. It works similar to dTraceTime() macro.
442 *
443 * \sa dTraceTime
444 */
445
446
447 /**
448 * \class Logger
449 *
450 * \brief Very simple but rather powerful component which may be used for logging your application activities.
451 *
452 * Global logger instance created on a first access to it (e.g. registering appenders, calling a dDebug() macro
453 * etc.) registers itself as a Qt default message handler and captures all the qDebug/dWarning/qCritical output.
454 *
455 * \note Qt 4 qDebug set of macro doesn't support capturing source function name, file name or line number so we
456 * recommend to use dDebug() and other Logger macros instead.
457 *
458 * \sa logger
459 * \sa [DLogger Documentation](index.html)
460 */
461
462 class LogDevice : public QIODevice
463 {
464 public:
465 LogDevice(Logger* l)
466 : m_logger(l),
467 m_semaphore(1)
468 {}
469
470 void lock(Logger::LogLevel logLevel, const char* file, int line, const char* function, const char* category)
471 {
472 m_semaphore.acquire();
473
474 if (!isOpen())
475 open(QIODevice::WriteOnly);
476
477 m_logLevel = logLevel;
478 m_file = file;
479 m_line = line;
480 m_function = function;
481 m_category = category;
482 }
483
484 protected:
485 qint64 readData(char*, qint64)
486 {
487 return 0;
488 }
489
490 qint64 writeData(const char* data, qint64 maxSize)
491 {
492 if (maxSize > 0)
493 m_logger->write(m_logLevel, m_file, m_line, m_function, m_category, QString::fromLocal8Bit(QByteArray(data, maxSize)));
494
495 m_semaphore.release();
496 return maxSize;
497 }
498
499 private:
500 Logger* m_logger;
501 QSemaphore m_semaphore;
502 Logger::LogLevel m_logLevel;
503 const char* m_file;
504 int m_line;
505 const char* m_function;
506 const char* m_category;
507 };
508
509
510 // Forward declarations
511 static void cleanupLoggerGlobalInstance();
512
513 #if QT_VERSION >= 0x050000
514 static void qtLoggerMessageHandler(QtMsgType, const QMessageLogContext& context, const QString& msg);
515 #else
516 static void qtLoggerMessageHandler(QtMsgType type, const char* msg);
517 #endif
518
519 /**
520 * \internal
521 *
522 * LoggerPrivate class implements the Singleton pattern in a thread-safe way. It contains a static pointer to the
523 * global logger instance protected by QReadWriteLock
524 */
525 class LoggerPrivate
526 {
527 public:
528 static Logger* globalInstance;
529 static QReadWriteLock globalInstanceLock;
530
531 QList<AbstractAppender*> appenders;
532 QMutex loggerMutex;
533
534 QMap<QString, bool> categories;
535 QMultiMap<QString, AbstractAppender*> categoryAppenders;
536 QString defaultCategory;
537
538 LogDevice* logDevice;
539 };
540
541
542 // Static fields initialization
543 Logger* LoggerPrivate::globalInstance = 0;
544 QReadWriteLock LoggerPrivate::globalInstanceLock;
545
546
547 static void cleanupLoggerGlobalInstance()
548 {
549 QWriteLocker locker(&LoggerPrivate::globalInstanceLock);
550
551 delete LoggerPrivate::globalInstance;
552 LoggerPrivate::globalInstance = 0;
553 }
554
555
556 #if QT_VERSION >= 0x050000
557 static void qtLoggerMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
558 {
559 Logger::LogLevel level;
560 switch (type)
561 {
562 case QtDebugMsg:
563 level = Logger::Debug;
564 break;
565 case QtInfoMsg:
566 level = Logger::Info;
567 break;
568 case QtWarningMsg:
569 level = Logger::Warning;
570 break;
571 case QtCriticalMsg:
572 level = Logger::Error;
573 break;
574 case QtFatalMsg:
575 level = Logger::Fatal;
576 break;
577 default:
578 level = Logger::Warning;
579 break;
580 }
581
582 bool isDefaultCategory = QString::fromLatin1(context.category) == "default";
583 Logger::globalInstance()->write(level, context.file, context.line, context.function, isDefaultCategory ? 0 : context.category, msg);
584 }
585
586 #else
587
588 static void qtLoggerMessageHandler(QtMsgType type, const char* msg)
589 {
590 switch (type)
591 {
592 case QtDebugMsg:
593 loggerInstance()->write(Logger::Debug, "", 0, "qDebug", 0, msg);
594 break;
595 case QtWarningMsg:
596 loggerInstance()->write(Logger::Warning, "", 0, "qDebug", 0, msg);
597 break;
598 case QtCriticalMsg:
599 loggerInstance()->write(Logger::Error, "", 0, "qDebug", 0, msg);
600 break;
601 case QtFatalMsg:
602 loggerInstance()->write(Logger::Fatal, "", 0, "qDebug", 0, msg);
603 break;
604 }
605 }
606 #endif
607
608
609 //! Construct the instance of Logger
610 /**
611 * If you're only using one global instance of logger you wouldn't probably need to use this constructor manually.
612 * Consider using [logger](@ref logger) macro instead to access the logger instance
613 */
614 Logger::Logger()
615 : d_ptr(new LoggerPrivate)
616 {
617 Q_D(Logger);
618
619 d->logDevice = new LogDevice(this);
620 }
621
622
623 //! Construct the instance of Logger and set logger default category
624 /**
625 * If you're only using one global instance of logger you wouldn't probably need to use this constructor manually.
626 * Consider using [logger](@ref logger) macro instead to access the logger instance and call
627 * [setDefaultCategory](@ref setDefaultCategory) method.
628 *
629 * \sa Logger()
630 * \sa setDefaultCategory()
631 */
632 Logger::Logger(const QString& defaultCategory)
633 : d_ptr(new LoggerPrivate)
634 {
635 Q_D(Logger);
636 d->logDevice = new LogDevice(this);
637
638 setDefaultCategory(defaultCategory);
639 }
640
641
642 //! Destroy the instance of Logger
643 /**
644 * You probably wouldn't need to use this function directly. Global instance of logger will be destroyed automatically
645 * at the end of your QCoreApplication execution
646 */
647 Logger::~Logger()
648 {
649 Q_D(Logger);
650
651 // Cleanup appenders
652 QMutexLocker appendersLocker(&d->loggerMutex);
653 qDeleteAll(d->appenders);
654 qDeleteAll(d->categoryAppenders);
655
656 // Cleanup device
657 delete d->logDevice;
658 appendersLocker.unlock();
659
660 delete d_ptr;
661 }
662
663
664 //! Converts the LogLevel enum value to its string representation
665 /**
666 * \param logLevel Log level to convert
667 *
668 * \sa LogLevel
669 * \sa levelFromString()
670 */
671 QString Logger::levelToString(Logger::LogLevel logLevel)
672 {
673 switch (logLevel)
674 {
675 case Trace:
676 return QLatin1String("Trace");
677 case Debug:
678 return QLatin1String("Debug");
679 case Info:
680 return QLatin1String("Info");
681 case Warning:
682 return QLatin1String("Warning");
683 case Error:
684 return QLatin1String("Error");
685 case Fatal:
686 return QLatin1String("Fatal");
687 }
688
689 return QString();
690 }
691
692
693 //! Converts the LogLevel string representation to enum value
694 /**
695 * Comparation of the strings is case independent. If the log level string provided cannot be understood
696 * Logger::Debug is returned.
697 *
698 * \param s String to be decoded
699 *
700 * \sa LogLevel
701 * \sa levelToString()
702 */
703 Logger::LogLevel Logger::levelFromString(const QString& s)
704 {
705 QString str = s.trimmed().toLower();
706
707 LogLevel result = Debug;
708
709 if (str == QLatin1String("trace"))
710 result = Trace;
711 else if (str == QLatin1String("debug"))
712 result = Debug;
713 else if (str == QLatin1String("info"))
714 result = Info;
715 else if (str == QLatin1String("warning"))
716 result = Warning;
717 else if (str == QLatin1String("error"))
718 result = Error;
719 else if (str == QLatin1String("fatal"))
720 result = Fatal;
721
722 return result;
723 }
724
725
726 //! Returns the global instance of Logger
727 /**
728 * In a most cases you shouldn't use this function directly. Consider using [logger](@ref logger) macro instead.
729 *
730 * \sa logger
731 */
732 Logger* Logger::globalInstance()
733 {
734 Logger* result = 0;
735 {
736 QReadLocker locker(&LoggerPrivate::globalInstanceLock);
737 result = LoggerPrivate::globalInstance;
738 }
739
740 if (!result)
741 {
742 QWriteLocker locker(&LoggerPrivate::globalInstanceLock);
743 LoggerPrivate::globalInstance = new Logger;
744
745 #if QT_VERSION >= 0x050000
746 qInstallMessageHandler(qtLoggerMessageHandler);
747 #else
748 qInstallMsgHandler(qtLoggerMessageHandler);
749 #endif
750 qAddPostRoutine(cleanupLoggerGlobalInstance);
751 result = LoggerPrivate::globalInstance;
752 }
753
754 return result;
755 }
756
757
758 //! Registers the appender to write the log records to
759 /**
760 * On the log writing call (using one of the macros or the write() function) Logger traverses through the list of
761 * the appenders and writes a log records to the each of them. Please, look through the AbstractAppender
762 * documentation to understand the concept of appenders.
763 *
764 * If no appenders was added to Logger, it falls back to logging into the \c std::cerr STL stream.
765 *
766 * \param appender Appender to register in the Logger
767 *
768 * \note Logger takes ownership on the appender and it will delete it on the application exit. According to this,
769 * appenders must be created on heap to prevent double destruction of the appender.
770 *
771 * \sa registerCategoryAppender
772 * \sa AbstractAppender
773 */
774 void Logger::registerAppender(AbstractAppender* appender)
775 {
776 Q_D(Logger);
777
778 QMutexLocker locker(&d->loggerMutex);
779
780 if (!d->appenders.contains(appender))
781 d->appenders.append(appender);
782 else
783 std::cerr << "Trying to register appender that was already registered" << std::endl;
784 }
785
786 //! Registers the appender to write the log records to the specific category
787 /**
788 * Calling this method, you can link some appender with the named category.
789 * On the log writing call to the specific category (calling write() with category parameter directly,
790 * writing to the default category, or using special dCDebug(), dCWarning() etc. macros),
791 * Logger writes the log message only to the list of registered category appenders.
792 *
793 * You can call logToGlobalInstance() to pass all category log messages to the global logger instance appenders
794 * (registered using registerAppender()).
795 * If no category appenders with specific name was registered to the Logger,
796 * it falls back to logging into the \c std::cerr STL stream, both with simple warning message.
797 *
798 * \param category Category name
799 * \param appender Appender to register in the Logger
800 *
801 * \note Logger takes ownership on the appender and it will delete it on the application exit. According to this,
802 * appenders must be created on heap to prevent double destruction of the appender.
803 *
804 * \sa registerAppender
805 * \sa dCTrace(), dCDebug(), dCInfo(), dCWarning(), dCError(), dCFatal()
806 * \sa dCategory(), dGlobalCategory()
807 * \sa logToGlobalInstance
808 * \sa setDefaultCategory
809 */
810 void Logger::registerCategoryAppender(const QString& category, AbstractAppender* appender)
811 {
812 Q_D(Logger);
813
814 QMutexLocker locker(&d->loggerMutex);
815
816 if (!d->categoryAppenders.values().contains(appender))
817 d->categoryAppenders.insert(category, appender);
818 else
819 std::cerr << "Trying to register appender that was already registered" << std::endl;
820 }
821
822 //! Sets default logging category
823 /**
824 * All log messages to this category appenders will also be written to general logger instance appenders (registered
825 * using [registerAppender](@ref registerAppender) method), and vice versa.
826 * In particular, any calls to the dDebug() macro will be treated as category logging,
827 * so you needn't to specify category name using dCDebug() macro.
828 *
829 * To unset the default category, pass a null string as a parameter.
830 *
831 * \param category Category name
832 *
833 * \note "category" format marker will be set to the category name for all of these messages
834 * (see [AbstractStringAppender::setFormat](@ref AbstractStringAppender::setFormat)).
835 *
836 * \sa defaultCategory()
837 * \sa registerCategoryAppender()
838 * \sa logToGlobalInstance()
839 */
840 void Logger::setDefaultCategory(const QString& category)
841 {
842 Q_D(Logger);
843
844 QMutexLocker locker(&d->loggerMutex);
845
846 d->defaultCategory = category;
847 }
848
849 //! Returns default logging category name
850 /**
851 * \sa setDefaultCategory
852 */
853 QString Logger::defaultCategory() const
854 {
855 Q_D(const Logger);
856 return d->defaultCategory;
857 }
858
859 //! Links some logging category with the global logger instance appenders.
860 /**
861 * If set to true, all log messages to the specified category appenders will also be written to the global logger instance appenders,
862 * registered using registerAppender().
863 *
864 * By default, all messages to the specific category are written only to the specific category appenders
865 * (registered using registerCategoryAppender()).
866 *
867 * \param category Category name
868 * \param logToGlobal Link or onlink the category from global logger instance appender
869 *
870 * \sa globalInstance
871 * \sa registerAppender
872 * \sa registerCategoryAppender
873 */
874 void Logger::logToGlobalInstance(const QString& category, bool logToGlobal)
875 {
876 Q_D(Logger);
877
878 if (this == globalInstance())
879 {
880 QMutexLocker locker(&d->loggerMutex);
881 d->categories.insert(category, logToGlobal);
882 }
883 else
884 {
885 globalInstance()->logToGlobalInstance(category, logToGlobal);
886 }
887 }
888
889
890 void Logger::write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
891 const QString& message, bool fromLocalInstance)
892 {
893 Q_D(Logger);
894
895 QMutexLocker locker(&d->loggerMutex);
896
897 QString logCategory = QString::fromLatin1(category);
898 if (logCategory.isNull() && !d->defaultCategory.isNull())
899 logCategory = d->defaultCategory;
900
901 bool wasWritten = false;
902 bool isGlobalInstance = this == globalInstance();
903 bool linkedToGlobal = isGlobalInstance && d->categories.value(logCategory, false);
904
905 if (!logCategory.isNull())
906 {
907 QList<AbstractAppender*> appenders = d->categoryAppenders.values(logCategory);
908 if (appenders.length() == 0)
909 {
910 if (logCategory != d->defaultCategory && !linkedToGlobal && !fromLocalInstance)
911 std::cerr << "No appenders assotiated with category " << qPrintable(logCategory) << std::endl;
912 }
913 else
914 {
915 foreach (AbstractAppender* appender, appenders)
916 appender->write(timeStamp, logLevel, file, line, function, logCategory, message);
917 wasWritten = true;
918 }
919 }
920
921 // the default category is linked to the main logger appenders
922 // global logger instance also writes all linked categories to the main appenders
923 if (logCategory.isNull() || logCategory == d->defaultCategory || linkedToGlobal)
924 {
925 if (!d->appenders.isEmpty())
926 {
927 foreach (AbstractAppender* appender, d->appenders)
928 appender->write(timeStamp, logLevel, file, line, function, logCategory, message);
929 wasWritten = true;
930 }
931 else
932 {
933 static bool noAppendersWarningShown = false;
934 if (!noAppendersWarningShown)
935 {
936 #if defined(Q_OS_ANDROID)
937 __android_ write(ANDROID_LOG_WARN, "Logger", "No appenders registered with logger");
938 #else
939 std::cerr << "No appenders registered with logger" << std::endl;
940 #endif
941 noAppendersWarningShown = true;
942 }
943 }
944 }
945
946 // local logger instances send category messages to the global instance
947 if (!logCategory.isNull() && !isGlobalInstance)
948 globalInstance()->write(timeStamp, logLevel, file, line, function, logCategory.toLatin1(), message, true);
949
950 if (!wasWritten && !fromLocalInstance)
951 {
952 // Fallback
953 #if defined(Q_OS_ANDROID)
954 QString result = QString(QLatin1String("<%2> %3")).arg(AbstractStringAppender::stripFunctionName(function)).arg(message);
955 __android_log_write(AndroidAppender::androidLogPriority(logLevel), "Logger", qPrintable(result));
956 #else
957 QString result = QString(QLatin1String("[%1] <%2> %3")).arg(levelToString(logLevel), -7)
958 .arg(AbstractStringAppender::stripFunctionName(function)).arg(message);
959 std::cerr << qPrintable(result) << std::endl;
960 #endif
961 }
962
963 if (logLevel == Logger::Fatal)
964 abort();
965 }
966
967
968 //! Writes the log record
969 /**
970 * Writes the log records with the supplied arguments to all the registered appenders.
971 *
972 * \note It is not recommended to call this function directly. Instead of this you can just call one of the macros
973 * (dTrace, dTrac, dInfo, dWarning, dError, dFatal) that will supply all the needed
974 * information to this function.
975 *
976 * \param timeStamp - the time stamp of the record
977 * \param logLevel - the log level of the record
978 * \param file - the name of the source file that requested the log record
979 * \param line - the line of the code of source file that requested the log record
980 * \param function - name of the function that requested the log record
981 * \param category - logging category (0 for default category)
982 * \param message - log message
983 *
984 * \note Recording of the log record using the Logger::Fatal log level will lead to calling the STL abort()
985 * function, which will interrupt the running of your software and begin the writing of the core dump.
986 *
987 * \sa LogLevel
988 * \sa dTrace, dDebug, dInfo, dWarning, dError, dFatal
989 * \sa AbstractAppender
990 */
991 void Logger::write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
992 const QString& message)
993 {
994 write(timeStamp, logLevel, file, line, function, category, message, /* fromLocalInstance = */ false);
995 }
996
997 /**
998 * This is the overloaded function provided for the convinience. It behaves similar to the above function.
999 *
1000 * This function uses the current timestamp obtained with \c QDateTime::currentDateTime().
1001 *
1002 * \sa write()
1003 */
1004 void Logger::write(LogLevel logLevel, const char* file, int line, const char* function, const char* category,
1005 const QString& message)
1006 {
1007 write(QDateTime::currentDateTime(), logLevel, file, line, function, category, message);
1008 }
1009
1010
1011 /**
1012 * This is the overloaded function provided for the convinience. It behaves similar to the above function.
1013 *
1014 * This function doesn't accept any log message as argument. It returns the \c QDebug object that can be written
1015 * using the stream functions. For example, you may like to write:
1016 * \code
1017 * dDebug() << "This is the size" << size << "of the element" << elementName;
1018 * \endcode
1019 * instead of writing
1020 * \code
1021 * dDebug(QString(QLatin1String("This is the size %1x%2 of the element %3"))
1022 * .arg(size.x()).arg(size.y()).arg(elementName));
1023 * \endcode
1024 *
1025 * Please consider reading the Qt Reference Documentation for the description of the QDebug class usage syntax.
1026 *
1027 * \note This overload is definitely more pleasant to use than the first write() overload, but it behaves definitely
1028 * slower than all the above overloads.
1029 *
1030 * \sa write()
1031 */
1032 QDebug Logger::write(LogLevel logLevel, const char* file, int line, const char* function, const char* category)
1033 {
1034 Q_D(Logger);
1035
1036 d->logDevice->lock(logLevel, file, line, function, category);
1037 return QDebug(d->logDevice);
1038 }
1039
1040
1041 //! Writes the assertion
1042 /**
1043 * This function writes the assertion record using the write() function.
1044 *
1045 * The assertion record is always written using the Logger::Fatal log level which leads to the abortation of the
1046 * program and generation of the core dump (if supported).
1047 *
1048 * The message written to the appenders will be identical to the \c condition argument prefixed with the
1049 * <tt>ASSERT:</tt> notification.
1050 *
1051 * \note It is not recommended to call this function directly. Instead of this you can just call the LOG_ASSERT
1052 * macro that will supply all the needed information to this function.
1053 *
1054 * \sa LOG_ASSERT
1055 * \sa write()
1056 */
1057 void Logger::writeAssert(const char* file, int line, const char* function, const char* condition)
1058 {
1059 write(Logger::Fatal, file, line, function, 0, QString("ASSERT: \"%1\"").arg(condition));
1060 }
1061
1062
1063 Logger* loggerInstance()
1064 {
1065 return Logger::globalInstance();
1066 }
1067
1068
1069
1070 void LoggerTimingHelper::start(const char* msg, ...)
1071 {
1072 va_list va;
1073 va_start(va, msg);
1074 m_block = QString().vsprintf(msg, va);
1075 va_end(va);
1076
1077 m_time.start();
1078 }
1079
1080
1081 void LoggerTimingHelper::start(const QString& block)
1082 {
1083 m_block = block;
1084 m_time.start();
1085 }
1086
1087 LoggerTimingHelper::~LoggerTimingHelper()
1088 {
1089 QString message;
1090 if (m_block.isEmpty())
1091 message = QString(QLatin1String("Function %1 finished in ")).arg(AbstractStringAppender::stripFunctionName(m_function));
1092 else
1093 message = QString(QLatin1String("\"%1\" finished in ")).arg(m_block);
1094
1095 int elapsed = m_time.elapsed();
1096 if (elapsed >= 10000)
1097 message += QString(QLatin1String("%1 s.")).arg(elapsed / 1000);
1098 else
1099 message += QString(QLatin1String("%1 ms.")).arg(elapsed);
1100
1101 m_logger->write(m_logLevel, m_file, m_line, m_function, 0, message);
1102 }
1103
1104
1105 void CuteMessageLogger::write(const char* msg, ...) const
1106 {
1107 va_list va;
1108 va_start(va, msg);
1109 m_l->write(m_level, m_file, m_line, m_function, m_category, QString().vsprintf(msg, va));
1110 va_end(va);
1111 }
1112
1113
1114 void CuteMessageLogger::write(const QString& msg) const
1115 {
1116 m_l->write(m_level, m_file, m_line, m_function, m_category, msg);
1117 }
1118
1119
1120 QDebug CuteMessageLogger::write() const
1121 {
1122 return m_l->write(m_level, m_file, m_line, m_function, m_category);
1123 }
1124
1125 DUTIL_END_NAMESPACE
0 /*
1 Copyright (c) 2012 Boris Moiseev (cyberbobs at gmail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 #ifndef LOGGER_H
14 #define LOGGER_H
15
16 // Qt
17 #include <QString>
18 #include <QDebug>
19 #include <QDateTime>
20
21 // Local
22 #include "CuteLogger_global.h"
23
24 DUTIL_BEGIN_NAMESPACE
25
26 class AbstractAppender;
27 class Logger;
28 CUTELOGGERSHARED_EXPORT Logger* loggerInstance();
29 #define logger loggerInstance()
30
31
32 #define dTrace CuteMessageLogger(loggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO).write
33 #define dDebug CuteMessageLogger(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO).write
34 #define dInfo CuteMessageLogger(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO).write
35 #define dWarning CuteMessageLogger(loggerInstance(), Logger::Warning, __FILE__, __LINE__, Q_FUNC_INFO).write
36 #define dError CuteMessageLogger(loggerInstance(), Logger::Error, __FILE__, __LINE__, Q_FUNC_INFO).write
37 #define dFatal CuteMessageLogger(loggerInstance(), Logger::Fatal, __FILE__, __LINE__, Q_FUNC_INFO).write
38
39 #define dCTrace(category) CuteMessageLogger(loggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
40 #define dCDebug(category) CuteMessageLogger(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
41 #define dCInfo(category) CuteMessageLogger(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
42 #define dCWarning(category) CuteMessageLogger(loggerInstance(), Logger::Warning, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
43 #define dCError(category) CuteMessageLogger(loggerInstance(), Logger::Error, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
44 #define dCFatal(category) CuteMessageLogger(loggerInstance(), Logger::Fatal, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
45
46 #define dTraceTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
47 #define dDebugTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
48 #define dInfoTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
49
50 #define dAssert(cond) ((!(cond)) ? loggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, #cond) : qt_noop())
51 #define dAssertX(cond, msg) ((!(cond)) ? loggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, msg) : qt_noop())
52
53 #define dCategory(category) \
54 private:\
55 Logger* loggerInstance()\
56 {\
57 static Logger customLoggerInstance(category);\
58 return &customLoggerInstance;\
59 }\
60
61 #define dGlobalCategory(category) \
62 private:\
63 Logger* loggerInstance()\
64 {\
65 static Logger customLoggerInstance(category);\
66 customLoggerInstance.logToGlobalInstance(category, true);\
67 return &customLoggerInstance;\
68 }\
69
70
71 class LoggerPrivate;
72 class CUTELOGGERSHARED_EXPORT Logger
73 {
74 Q_DISABLE_COPY(Logger)
75
76 public:
77 Logger();
78 Logger(const QString& defaultCategory);
79 ~Logger();
80
81 //! Describes the possible severity levels of the log records
82 enum LogLevel
83 {
84 Trace, //!< Trace level. Can be used for mostly unneeded records used for internal code tracing.
85 Debug, //!< Debug level. Useful for non-necessary records used for the debugging of the software.
86 Info, //!< Info level. Can be used for informational records, which may be interesting for not only developers.
87 Warning, //!< Warning. May be used to log some non-fatal warnings detected by your application.
88 Error, //!< Error. May be used for a big problems making your application work wrong but not crashing.
89 Fatal //!< Fatal. Used for unrecoverable errors, crashes the application right after the log record is written.
90 };
91
92 static QString levelToString(LogLevel logLevel);
93 static LogLevel levelFromString(const QString& s);
94
95 static Logger* globalInstance();
96
97 void registerAppender(AbstractAppender* appender);
98 void registerCategoryAppender(const QString& category, AbstractAppender* appender);
99
100 void logToGlobalInstance(const QString& category, bool logToGlobal = false);
101
102 void setDefaultCategory(const QString& category);
103 QString defaultCategory() const;
104
105 void write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
106 const QString& message);
107 void write(LogLevel logLevel, const char* file, int line, const char* function, const char* category, const QString& message);
108 QDebug write(LogLevel logLevel, const char* file, int line, const char* function, const char* category);
109
110 void writeAssert(const char* file, int line, const char* function, const char* condition);
111
112 private:
113 void write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
114 const QString& message, bool fromLocalInstance);
115 Q_DECLARE_PRIVATE(Logger)
116 LoggerPrivate* d_ptr;
117 };
118
119
120 class CUTELOGGERSHARED_EXPORT CuteMessageLogger
121 {
122 Q_DISABLE_COPY(CuteMessageLogger)
123
124 public:
125 Q_DECL_CONSTEXPR CuteMessageLogger(Logger* l, Logger::LogLevel level, const char* file, int line, const char* function)
126 : m_l(l),
127 m_level(level),
128 m_file(file),
129 m_line(line),
130 m_function(function),
131 m_category(0)
132 {}
133
134 Q_DECL_CONSTEXPR CuteMessageLogger(Logger* l, Logger::LogLevel level, const char* file, int line, const char* function, const char* category)
135 : m_l(l),
136 m_level(level),
137 m_file(file),
138 m_line(line),
139 m_function(function),
140 m_category(category)
141 {}
142
143 void write(const char* msg, ...) const
144 #if defined(Q_CC_GNU) && !defined(__INSURE__)
145 # if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
146 __attribute__ ((format (gnu_printf, 2, 3)))
147 # else
148 __attribute__ ((format (printf, 2, 3)))
149 # endif
150 #endif
151 ;
152
153 void write(const QString& msg) const;
154
155 QDebug write() const;
156
157 private:
158 Logger* m_l;
159 Logger::LogLevel m_level;
160 const char* m_file;
161 int m_line;
162 const char* m_function;
163 const char* m_category;
164 };
165
166
167 class CUTELOGGERSHARED_EXPORT LoggerTimingHelper
168 {
169 Q_DISABLE_COPY(LoggerTimingHelper)
170
171 public:
172 inline explicit LoggerTimingHelper(Logger* l, Logger::LogLevel logLevel, const char* file, int line,
173 const char* function)
174 : m_logger(l),
175 m_logLevel(logLevel),
176 m_file(file),
177 m_line(line),
178 m_function(function)
179 {}
180
181 void start(const char* msg, ...)
182 #if defined(Q_CC_GNU) && !defined(__INSURE__)
183 # if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
184 __attribute__ ((format (gnu_printf, 2, 3)))
185 # else
186 __attribute__ ((format (printf, 2, 3)))
187 # endif
188 #endif
189 ;
190
191 void start(const QString& msg = QString());
192
193 ~LoggerTimingHelper();
194
195 private:
196 Logger* m_logger;
197 QTime m_time;
198 Logger::LogLevel m_logLevel;
199 const char* m_file;
200 int m_line;
201 const char* m_function;
202 QString m_block;
203 };
204
205 DUTIL_END_NAMESPACE
206
207 #endif // LOGGER_H
0 /*
1 Copyright (c) 2010 Karl-Heinz Reichel (khreichel at googlemail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13 // Local
14 #include "OutputDebugAppender.h"
15
16 // STL
17 #include <windows.h>
18
19 DUTIL_BEGIN_NAMESPACE
20
21 /**
22 * \class OutputDebugAppender
23 *
24 * \brief Appender that writes the log records to the Microsoft Debug Log
25 */
26
27
28 //! Writes the log record to the windows debug log.
29 /**
30 * \sa AbstractStringAppender::format()
31 */
32 void OutputDebugAppender::append(const QDateTime& timeStamp,
33 Logger::LogLevel logLevel,
34 const char* file,
35 int line,
36 const char* function,
37 const QString& category,
38 const QString& message)
39 {
40 QString s = formattedString(timeStamp, logLevel, file, line, function, category, message);
41 OutputDebugStringW((LPCWSTR) s.utf16());
42 }
43
44 DUTIL_END_NAMESPACE
0 /*
1 Copyright (c) 2010 Karl-Heinz Reichel (khreichel at googlemail dot com)
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License version 2.1
5 as published by the Free Software Foundation and appearing in the file
6 LICENSE.LGPL included in the packaging of this file.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU Lesser General Public License for more details.
12 */
13
14 #ifndef OUTPUTDEBUGAPPENDER_H
15 #define OUTPUTDEBUGAPPENDER_H
16
17 #include "CuteLogger_global.h"
18 #include <AbstractStringAppender.h>
19
20 DUTIL_BEGIN_NAMESPACE
21
22 class CUTELOGGERSHARED_EXPORT OutputDebugAppender : public AbstractStringAppender
23 {
24 protected:
25 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
26 const char* function, const QString& category, const QString& message);
27 };
28
29 DUTIL_END_NAMESPACE
30
31 #endif // OUTPUTDEBUGAPPENDER_H
0 # Deepin Tool Kit Log
1
2 DLog is the log module of deepin tool kit for Qt/C++
3
4 # Install
5
6 ````
7 mkdir build && cd build
8 qmake ..
9 sudo make install
10 ````
11
12 # Usage
13
14 Just add pkgconfig in .pro file
15
16 ````
17 unix {
18 CONFIG+=link_pkgconfig
19 PKGCONFIG+=dtklog
20 }
21 ````
22
23 # Example
24
25 ````
26 #include <QCoreApplication>
27
28 #include <DLog>
29
30 using namespace Dtk::Log;
31
32 int main(int argc, char* argv[])
33 {
34 QCoreApplication app(argc, argv);
35
36 /* 1 you can use standrd deepin application log format */
37 // 1.1 log to console
38 DLogManager::instance()->registerAppender(true);
39 dInfoTime();
40 /* 1.2 log to standrd deepin user cache path: ~/.cache/{organ}/{appname}/ */
41 // app.setOrganizationName("dtk-test"); // must set
42 // app.setApplicationName("dlog-example"); // must set
43 // dInfo()<< "LogFile:" << DLogManager::instance()->getlogFilePath();
44 // DLogManager::instance()->registerAppender(false);
45
46 /* 2 Register your own logger format;*/
47 // ConsoleAppender* consoleAppender = new ConsoleAppender;
48 // consoleAppender->setFormat("[%{type:-7}] <%{Function}> %{message}\n");
49 // logger->registerAppender(consoleAppender);
50
51 dInfo("Starting the application");
52 int result = 1;
53 dWarning() << "Something went wrong." << "Result code is" << result;
54 return result;
55 }
56 ````
57
58 You can get full example from:
59
60 [dlog-example](https://github.com/deepin-tool-kit/dtk-example/tree/master/dlog-example)
61
62 # Document
63
64 ````
65 doxygen -g dlog
66 doxygen -w html
67 firefox html/index
68 ````
0 #include <QDateTime>
1 #include <QDir>
2 #include <QFileInfo>
3
4 #include "RollingFileAppender.h"
5
6 DUTIL_BEGIN_NAMESPACE
7
8 RollingFileAppender::RollingFileAppender(const QString& fileName)
9 : FileAppender(fileName),
10 m_logFilesLimit(0)
11 {}
12
13
14 void RollingFileAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
15 const char* function, const QString& category, const QString& message)
16 {
17 if (!m_rollOverTime.isNull() && QDateTime::currentDateTime() > m_rollOverTime)
18 rollOver();
19
20 FileAppender::append(timeStamp, logLevel, file, line, function, category, message);
21 }
22
23
24 RollingFileAppender::DatePattern RollingFileAppender::datePattern() const
25 {
26 QMutexLocker locker(&m_rollingMutex);
27 return m_frequency;
28 }
29
30
31 QString RollingFileAppender::datePatternString() const
32 {
33 QMutexLocker locker(&m_rollingMutex);
34 return m_datePatternString;
35 }
36
37
38 void RollingFileAppender::setDatePattern(DatePattern datePattern)
39 {
40 switch (datePattern)
41 {
42 case MinutelyRollover:
43 setDatePatternString(QLatin1String("'.'yyyy-MM-dd-hh-mm"));
44 break;
45 case HourlyRollover:
46 setDatePatternString(QLatin1String("'.'yyyy-MM-dd-hh"));
47 break;
48 case HalfDailyRollover:
49 setDatePatternString(QLatin1String("'.'yyyy-MM-dd-a"));
50 break;
51 case DailyRollover:
52 setDatePatternString(QLatin1String("'.'yyyy-MM-dd"));
53 break;
54 case WeeklyRollover:
55 setDatePatternString(QLatin1String("'.'yyyy-ww"));
56 break;
57 case MonthlyRollover:
58 setDatePatternString(QLatin1String("'.'yyyy-MM"));
59 break;
60 default:
61 Q_ASSERT_X(false, "DailyRollingFileAppender::setDatePattern()", "Invalid datePattern constant");
62 setDatePattern(DailyRollover);
63 };
64
65 QMutexLocker locker(&m_rollingMutex);
66 m_frequency = datePattern;
67
68 computeRollOverTime();
69 }
70
71
72 void RollingFileAppender::setDatePattern(const QString& datePattern)
73 {
74 setDatePatternString(datePattern);
75 computeFrequency();
76
77 computeRollOverTime();
78 }
79
80
81 void RollingFileAppender::setDatePatternString(const QString& datePatternString)
82 {
83 QMutexLocker locker(&m_rollingMutex);
84 m_datePatternString = datePatternString;
85 }
86
87
88 void RollingFileAppender::computeFrequency()
89 {
90 QMutexLocker locker(&m_rollingMutex);
91
92 const QDateTime startTime(QDate(1999, 1, 1), QTime(0, 0));
93 const QString startString = startTime.toString(m_datePatternString);
94
95 if (startString != startTime.addSecs(60).toString(m_datePatternString))
96 m_frequency = MinutelyRollover;
97 else if (startString != startTime.addSecs(60 * 60).toString(m_datePatternString))
98 m_frequency = HourlyRollover;
99 else if (startString != startTime.addSecs(60 * 60 * 12).toString(m_datePatternString))
100 m_frequency = HalfDailyRollover;
101 else if (startString != startTime.addDays(1).toString(m_datePatternString))
102 m_frequency = DailyRollover;
103 else if (startString != startTime.addDays(7).toString(m_datePatternString))
104 m_frequency = WeeklyRollover;
105 else if (startString != startTime.addMonths(1).toString(m_datePatternString))
106 m_frequency = MonthlyRollover;
107 else
108 {
109 Q_ASSERT_X(false, "DailyRollingFileAppender::computeFrequency", "The pattern '%1' does not specify a frequency");
110 return;
111 }
112 }
113
114
115 void RollingFileAppender::removeOldFiles()
116 {
117 if (m_logFilesLimit <= 1)
118 return;
119
120 QFileInfo fileInfo(fileName());
121 QDir logDirectory(fileInfo.absoluteDir());
122 logDirectory.setFilter(QDir::Files);
123 logDirectory.setNameFilters(QStringList() << fileInfo.fileName() + "*");
124 QFileInfoList logFiles = logDirectory.entryInfoList();
125
126 QMap<QDateTime, QString> fileDates;
127 for (int i = 0; i < logFiles.length(); ++i)
128 {
129 QString name = logFiles[i].fileName();
130 QString suffix = name.mid(name.indexOf(fileInfo.fileName()) + fileInfo.fileName().length());
131 QDateTime fileDateTime = QDateTime::fromString(suffix, datePatternString());
132
133 if (fileDateTime.isValid())
134 fileDates.insert(fileDateTime, logFiles[i].absoluteFilePath());
135 }
136
137 QList<QString> fileDateNames = fileDates.values();
138 for (int i = 0; i < fileDateNames.length() - m_logFilesLimit + 1; ++i)
139 QFile::remove(fileDateNames[i]);
140 }
141
142
143 void RollingFileAppender::computeRollOverTime()
144 {
145 Q_ASSERT_X(!m_datePatternString.isEmpty(), "DailyRollingFileAppender::computeRollOverTime()", "No active date pattern");
146
147 QDateTime now = QDateTime::currentDateTime();
148 QDate nowDate = now.date();
149 QTime nowTime = now.time();
150 QDateTime start;
151
152 switch (m_frequency)
153 {
154 case MinutelyRollover:
155 {
156 start = QDateTime(nowDate, QTime(nowTime.hour(), nowTime.minute(), 0, 0));
157 m_rollOverTime = start.addSecs(60);
158 }
159 break;
160 case HourlyRollover:
161 {
162 start = QDateTime(nowDate, QTime(nowTime.hour(), 0, 0, 0));
163 m_rollOverTime = start.addSecs(60*60);
164 }
165 break;
166 case HalfDailyRollover:
167 {
168 int hour = nowTime.hour();
169 if (hour >= 12)
170 hour = 12;
171 else
172 hour = 0;
173 start = QDateTime(nowDate, QTime(hour, 0, 0, 0));
174 m_rollOverTime = start.addSecs(60*60*12);
175 }
176 break;
177 case DailyRollover:
178 {
179 start = QDateTime(nowDate, QTime(0, 0, 0, 0));
180 m_rollOverTime = start.addDays(1);
181 }
182 break;
183 case WeeklyRollover:
184 {
185 // Qt numbers the week days 1..7. The week starts on Monday.
186 // Change it to being numbered 0..6, starting with Sunday.
187 int day = nowDate.dayOfWeek();
188 if (day == Qt::Sunday)
189 day = 0;
190 start = QDateTime(nowDate, QTime(0, 0, 0, 0)).addDays(-1 * day);
191 m_rollOverTime = start.addDays(7);
192 }
193 break;
194 case MonthlyRollover:
195 {
196 start = QDateTime(QDate(nowDate.year(), nowDate.month(), 1), QTime(0, 0, 0, 0));
197 m_rollOverTime = start.addMonths(1);
198 }
199 break;
200 default:
201 Q_ASSERT_X(false, "DailyRollingFileAppender::computeInterval()", "Invalid datePattern constant");
202 m_rollOverTime = QDateTime::fromTime_t(0);
203 }
204
205 m_rollOverSuffix = start.toString(m_datePatternString);
206 Q_ASSERT_X(now.toString(m_datePatternString) == m_rollOverSuffix,
207 "DailyRollingFileAppender::computeRollOverTime()", "File name changes within interval");
208 Q_ASSERT_X(m_rollOverSuffix != m_rollOverTime.toString(m_datePatternString),
209 "DailyRollingFileAppender::computeRollOverTime()", "File name does not change with rollover");
210 }
211
212
213 void RollingFileAppender::rollOver()
214 {
215 Q_ASSERT_X(!m_datePatternString.isEmpty(), "DailyRollingFileAppender::rollOver()", "No active date pattern");
216
217 QString rollOverSuffix = m_rollOverSuffix;
218 computeRollOverTime();
219 if (rollOverSuffix == m_rollOverSuffix)
220 return;
221
222 closeFile();
223
224 QString targetFileName = fileName() + rollOverSuffix;
225 QFile f(targetFileName);
226 if (f.exists() && !f.remove())
227 return;
228 f.setFileName(fileName());
229 if (!f.rename(targetFileName))
230 return;
231
232 openFile();
233 removeOldFiles();
234 }
235
236
237 void RollingFileAppender::setLogFilesLimit(int limit)
238 {
239 QMutexLocker locker(&m_rollingMutex);
240 m_logFilesLimit = limit;
241 }
242
243
244 int RollingFileAppender::logFilesLimit() const
245 {
246 QMutexLocker locker(&m_rollingMutex);
247 return m_logFilesLimit;
248 }
249
250 DUTIL_END_NAMESPACE
0 #ifndef ROLLINGFILEAPPENDER_H
1 #define ROLLINGFILEAPPENDER_H
2
3 #include <QDateTime>
4
5 #include <FileAppender.h>
6
7 DUTIL_BEGIN_NAMESPACE
8
9 /*!
10 * \brief The RollingFileAppender class extends FileAppender so that the underlying file is rolled over at a user chosen frequency.
11 *
12 * The class is based on Log4Qt.DailyRollingFileAppender class (http://log4qt.sourceforge.net/)
13 * and has the same date pattern format.
14 *
15 * For example, if the fileName is set to /foo/bar and the DatePattern set to the daily rollover ('.'yyyy-MM-dd'.log'), on 2014-02-16 at midnight,
16 * the logging file /foo/bar.log will be copied to /foo/bar.2014-02-16.log and logging for 2014-02-17 will continue in /foo/bar
17 * until it rolls over the next day.
18 *
19 * The logFilesLimit parameter is used to automatically delete the oldest log files in the directory during rollover
20 * (so no more than logFilesLimit recent log files exist in the directory at any moment).
21 * \sa setDatePattern(DatePattern), setLogFilesLimit(int)
22 */
23 class CUTELOGGERSHARED_EXPORT RollingFileAppender : public FileAppender
24 {
25 public:
26 /*!
27 * The enum DatePattern defines constants for date patterns.
28 * \sa setDatePattern(DatePattern)
29 */
30 enum DatePattern
31 {
32 /*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */
33 MinutelyRollover = 0,
34 /*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */
35 HourlyRollover,
36 /*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */
37 HalfDailyRollover,
38 /*! The daily date pattern string is "'.'yyyy-MM-dd". */
39 DailyRollover,
40 /*! The weekly date pattern string is "'.'yyyy-ww". */
41 WeeklyRollover,
42 /*! The monthly date pattern string is "'.'yyyy-MM". */
43 MonthlyRollover
44 };
45 Q_ENUMS(DatePattern)
46
47 RollingFileAppender(const QString& fileName = QString());
48
49 DatePattern datePattern() const;
50 void setDatePattern(DatePattern datePattern);
51 void setDatePattern(const QString& datePattern);
52
53 QString datePatternString() const;
54
55 void setLogFilesLimit(int limit);
56 int logFilesLimit() const;
57
58 protected:
59 virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line,
60 const char* function, const QString& category, const QString& message);
61
62 private:
63 void rollOver();
64 void computeRollOverTime();
65 void computeFrequency();
66 void removeOldFiles();
67 void setDatePatternString(const QString& datePatternString);
68
69 QString m_datePatternString;
70 DatePattern m_frequency;
71
72 QDateTime m_rollOverTime;
73 QString m_rollOverSuffix;
74 int m_logFilesLimit;
75 mutable QMutex m_rollingMutex;
76 };
77
78 DUTIL_END_NAMESPACE
79
80 #endif // ROLLINGFILEAPPENDER_H
0 INCLUDEPATH += $$PWD
1
2 HEADERS += \
3 $$PWD/RollingFileAppender.h \
4 $$PWD/Logger.h \
5 $$PWD/FileAppender.h \
6 $$PWD/CuteLogger_global.h \
7 $$PWD/ConsoleAppender.h \
8 $$PWD/AbstractStringAppender.h \
9 $$PWD/AbstractAppender.h \
10 $$PWD/LogManager.h
11
12 SOURCES += \
13 $$PWD/RollingFileAppender.cpp \
14 $$PWD/Logger.cpp \
15 $$PWD/FileAppender.cpp \
16 $$PWD/ConsoleAppender.cpp \
17 $$PWD/AbstractStringAppender.cpp \
18 $$PWD/AbstractAppender.cpp \
19 $$PWD/LogManager.cpp
20
21 win32 {
22 SOURCES += $$PWD/OutputDebugAppender.cpp
23 HEADERS += $$PWD/OutputDebugAppender.h
24 }
0 include(cutelogger.pri)
1
2 HEADERS += DLog
0 DCOMMON_DIR = $$PWD/../common
1 include($$DCOMMON_DIR/lib.pri)
2 include(dlog/dlog.pri)
3
4 QT -= gui
5
6 TARGET = dtkutil
7
8 DEFINES += LIBDTKUTIL_LIBRARY
9
10 HEADERS += \
11 DLog
12
13 includes.path = $${DTK_INCLUDEPATH}/DUtil
14 includes.files += \
15 $$system($$DCOMMON_DIR/trheader.sh $$PWD/dlog/DLog) \
16 $$PWD/dlog/DLog
17
18 QMAKE_PKGCONFIG_NAME = DTK_UTIL
19 QMAKE_PKGCONFIG_DESCRIPTION = Deepin Tool Kit Util Module
20 QMAKE_PKGCONFIG_INCDIR = $$includes.path
2020
2121 #define DUI_DECL_DEPRECATED Q_DECL_DEPRECATED
2222
23 #ifndef DTK_NAMESPACE
2324 #define DTK_NAMESPACE Dtk
25 #endif
26
2427 #define DWIDGET_NAMESPACE Widget
28 #define DTK_WIDGET_NAMESPACE DTK_NAMESPACE::Widget
2529
2630 #if !defined(DWIDGET_NAMESPACE)
27 # define DWIDGET_NAMESPACE_BEGIN
28 # define DWIDGET_NAMESPACE_END
29 # define USE_NAMESPACE_DWIDGET
31 # define DWIDGET_BEGIN_NAMESPACE
32 # define DWIDGET_END_NAMESPACE
33 # define DWIDGET_USE_NAMESPACE
3034 #else
31 # define DWIDGET_NAMESPACE_BEGIN namespace DTK_NAMESPACE { namespace DWIDGET_NAMESPACE {
32 # define DWIDGET_NAMESPACE_END }}
33 # define USE_NAMESPACE_DWIDGET using namespace DTK_NAMESPACE::DWIDGET_NAMESPACE;
35 # define DWIDGET_BEGIN_NAMESPACE namespace DTK_NAMESPACE { namespace DWIDGET_NAMESPACE {
36 # define DWIDGET_END_NAMESPACE }}
37 # define DWIDGET_USE_NAMESPACE using namespace DTK_WIDGET_NAMESPACE;
3438 #endif
3539
3640 #define D_THEME_INIT_WIDGET(className, propertys...) \
1111 #include "anchors.h"
1212 #include "denhancedwidget.h"
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 class AnchorsBasePrivate
1717 {
10841084 QRect::setRight(arg);
10851085 }
10861086
1087 DWIDGET_NAMESPACE_END
1087 DWIDGET_END_NAMESPACE
1818
1919 #include "libdui_global.h"
2020
21 DWIDGET_NAMESPACE_BEGIN
21 DWIDGET_BEGIN_NAMESPACE
2222
2323 class AnchorsBase;
2424 struct AnchorInfo {
285285 T *m_widget;
286286 };
287287
288 DWIDGET_NAMESPACE_END
288 DWIDGET_END_NAMESPACE
289289
290290 #endif // ANCHORS_H
88
99 #include "dabstractcomboboxdelegate.h"
1010
11 DWIDGET_NAMESPACE_BEGIN
11 DWIDGET_BEGIN_NAMESPACE
1212
1313 DAbstractComboBoxDelegate::DAbstractComboBoxDelegate(QObject *parent) : QStyledItemDelegate(parent)
1414 {
4141 editor->setGeometry(option.rect);
4242 }
4343
44 DWIDGET_NAMESPACE_END
44 DWIDGET_END_NAMESPACE
1515
1616 #include "dcombobox.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DAbstractComboBoxDelegate : public QStyledItemDelegate
2121 {
2828
2929 };
3030
31 DWIDGET_NAMESPACE_END
31 DWIDGET_END_NAMESPACE
3232
3333 #endif // DABSTRACTCOMBOBOXDELEGATE_H
1919 #include "dabstractdialog.h"
2020 #include "private/dabstractdialogprivate_p.h"
2121
22 DWIDGET_NAMESPACE_BEGIN
22 DWIDGET_BEGIN_NAMESPACE
2323
2424 DAbstractDialogPrivate::DAbstractDialogPrivate(DAbstractDialog *qq):
2525 DObjectPrivate(qq)
215215 dd.init();
216216 }
217217
218 DWIDGET_NAMESPACE_END
218 DWIDGET_END_NAMESPACE
1919 class QPushButton;
2020 class QResizeEvent;
2121
22 DWIDGET_NAMESPACE_BEGIN
22 DWIDGET_BEGIN_NAMESPACE
2323
2424 class DAbstractDialogPrivate;
2525 class DAbstractDialog : public QDialog, public DObject
7171 D_DECLARE_PRIVATE(DAbstractDialog)
7272 };
7373
74 DWIDGET_NAMESPACE_END
74 DWIDGET_END_NAMESPACE
7575
7676 #endif // DABSTRACTDIALOG_H
1212 #include "dthememanager.h"
1313 #include "private/dthemehelper.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DApplication::DApplication(int &argc, char **argv) :
1818 QApplication(argc, argv)
3131 themeManager->setTheme(theme);
3232 }
3333
34 DWIDGET_NAMESPACE_END
34 DWIDGET_END_NAMESPACE
1313
1414 #include "libdui_global.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 class LIBDUISHARED_EXPORT DApplication : public QApplication
1919 {
2525 void setTheme(const QString & theme);
2626 };
2727
28 DWIDGET_NAMESPACE_END
28 DWIDGET_END_NAMESPACE
2929
3030 #endif // DAPPLICATION_H
99 #include "darrowbutton.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 ArrowButtonIcon::ArrowButtonIcon(QWidget *parent) :
1515 QLabel(parent)
172172 m_pressLabel->setButtonState(state);
173173 }
174174
175 DWIDGET_NAMESPACE_END
175 DWIDGET_END_NAMESPACE
1919 #include "libdui_global.h"
2020 #include "dconstants.h"
2121
22 DWIDGET_NAMESPACE_BEGIN
22 DWIDGET_BEGIN_NAMESPACE
2323
2424 class ArrowButtonIcon : public QLabel
2525 {
8787 ArrowButtonState m_buttonState = ArrowStateNormal;
8888 };
8989
90 DWIDGET_NAMESPACE_END
90 DWIDGET_END_NAMESPACE
9191
9292 #endif // DARROWBUTTON_H
1111
1212 #include <QResizeEvent>
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 ArrowHeaderLine::ArrowHeaderLine(QWidget *parent) :
1717 DHeaderLine(parent)
8282 DBaseExpand::resizeEvent(e);
8383 }
8484
85 DWIDGET_NAMESPACE_END
85 DWIDGET_END_NAMESPACE
1717 #include "dbaseline.h"
1818 #include "dheaderline.h"
1919
20 DWIDGET_NAMESPACE_BEGIN
20 DWIDGET_BEGIN_NAMESPACE
2121
2222 class ArrowHeaderLine : public DHeaderLine
2323 {
5454 ArrowHeaderLine *m_headerLine = NULL;
5555 };
5656
57 DWIDGET_NAMESPACE_END
57 DWIDGET_END_NAMESPACE
5858
5959 #endif // DARROWLINEEXPAND_H
1414 #endif
1515 #include <QApplication>
1616
17 USE_NAMESPACE_DWIDGET
17 DWIDGET_USE_NAMESPACE
1818
1919 DArrowRectangle::DArrowRectangle(ArrowDirection direction, QWidget * parent) :
2020 QWidget(parent),m_arrowDirection(direction)
2323 #include "dthememanager.h"
2424 #include "dgraphicsgloweffect.h"
2525
26 DWIDGET_NAMESPACE_BEGIN
26 DWIDGET_BEGIN_NAMESPACE
2727
2828 class LIBDUISHARED_EXPORT DArrowRectangle : public QWidget
2929 {
122122 QWidget *m_content = NULL;
123123 };
124124
125 DWIDGET_NAMESPACE_END
125 DWIDGET_END_NAMESPACE
126126
127127 #endif // DARROWRECTANGLE_H
99 #include "dbasebutton.h"
1010 #include "dthememanager.h"
1111
12 USE_NAMESPACE_DWIDGET
12 DWIDGET_USE_NAMESPACE
1313
1414 DBaseButton::DBaseButton(QWidget *parent) :
1515 QPushButton(parent)
1414 #include <QPushButton>
1515 #include "libdui_global.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DBaseButton : public QPushButton
2020 {
2828 void initInsideFrame();
2929 };
3030
31 DWIDGET_NAMESPACE_END
31 DWIDGET_END_NAMESPACE
3232
3333 #endif // DBASEBUTTON_H
1212
1313 #include <QResizeEvent>
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DBaseExpand::DBaseExpand(QWidget *parent) : QWidget(parent)
1818 {
174174 }
175175
176176
177 DWIDGET_NAMESPACE_END
177 DWIDGET_END_NAMESPACE
1818 #include "dseparatorhorizontal.h"
1919 #include "dconstants.h"
2020
21 DWIDGET_NAMESPACE_BEGIN
21 DWIDGET_BEGIN_NAMESPACE
2222
2323 class ContentLoader : public QFrame
2424 {
6565 bool m_expand = false;
6666 };
6767
68 DWIDGET_NAMESPACE_END
68 DWIDGET_END_NAMESPACE
6969
7070 #endif // DBASEEXPAND_H
99 #include "dbaseline.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DBaseLine::DBaseLine(QWidget *parent) : QLabel(parent)
1515 {
8484 return m_rightMargin;
8585 }
8686
87 DWIDGET_NAMESPACE_END
87 DWIDGET_END_NAMESPACE
1616 #include "libdui_global.h"
1717 #include "dconstants.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class LIBDUISHARED_EXPORT DBaseLine : public QLabel
2222 {
4444 int m_rightMargin = HEADER_RIGHT_MARGIN;
4545 };
4646
47 DWIDGET_NAMESPACE_END
47 DWIDGET_END_NAMESPACE
4848
4949 #endif // DBASELINE_H
2323 #include "dboxwidget.h"
2424 #include "private/dboxwidget_p.h"
2525
26 DWIDGET_NAMESPACE_BEGIN
26 DWIDGET_BEGIN_NAMESPACE
2727
2828 DBoxWidgetPrivate::DBoxWidgetPrivate(DBoxWidget *qq):
2929 DObjectPrivate(qq),
139139
140140 }
141141
142 DWIDGET_NAMESPACE_END
142 DWIDGET_END_NAMESPACE
1414
1515 #include "dobject.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DBoxWidgetPrivate;
2020 class DBoxWidget : public QFrame, public DObject
6161 explicit DVBoxWidget(QWidget *parent = 0);
6262 };
6363
64 DWIDGET_NAMESPACE_END
64 DWIDGET_END_NAMESPACE
6565
6666 #endif // DBOXWIDGET_H
1818 #include <QLabel>
1919 #include <QDebug>
2020
21 DWIDGET_NAMESPACE_BEGIN
21 DWIDGET_BEGIN_NAMESPACE
2222
2323 #include "dwindowclosebutton.h"
2424
432432
433433 }
434434
435 DWIDGET_NAMESPACE_END
435 DWIDGET_END_NAMESPACE
2121 class QLabel;
2222
2323
24 DWIDGET_NAMESPACE_BEGIN
24 DWIDGET_BEGIN_NAMESPACE
2525
2626
2727 class ImageButton: public QPushButton
138138 void clearData();
139139 };
140140
141 DWIDGET_NAMESPACE_END
141 DWIDGET_END_NAMESPACE
142142
143143 #endif // DBUTTONGRID_H
8181 }
8282
8383
84 DWIDGET_NAMESPACE_BEGIN
84 DWIDGET_BEGIN_NAMESPACE
8585
8686 DButtonList::DButtonList(QWidget *parent) : QListWidget(parent)
8787 {
217217 }
218218
219219
220 DWIDGET_NAMESPACE_END
220 DWIDGET_END_NAMESPACE
4747 };
4848
4949
50 DWIDGET_NAMESPACE_BEGIN
50 DWIDGET_BEGIN_NAMESPACE
5151
5252 class LIBDUISHARED_EXPORT DButtonList : public QListWidget
5353 {
9090 };
9191
9292
93 DWIDGET_NAMESPACE_END
93 DWIDGET_END_NAMESPACE
9494
9595 #endif // DBUTTONLIST_H
1616 #include <QResizeEvent>
1717 #include <QDebug>
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 DCalendar::DCalendar(QWidget *parent) : QWidget(parent)
2222 {
272272 m_viewCurrent = m_viewRight;
273273 }
274274
275 DWIDGET_NAMESPACE_END
275 DWIDGET_END_NAMESPACE
2323 class CaLunarDayInfo;
2424 class CalendarView;
2525
26 DWIDGET_NAMESPACE_BEGIN
26 DWIDGET_BEGIN_NAMESPACE
2727
2828 class LIBDUISHARED_EXPORT DCalendar : public QWidget
2929 {
9494 QDate m_showDate;
9595 };
9696
97 DWIDGET_NAMESPACE_END
97 DWIDGET_END_NAMESPACE
9898
9999 #endif // CALENDARWIDGET_H
99 #include "dcheckbox.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DCheckBox::DCheckBox(QWidget *parent) :
1515 QCheckBox(parent)
2323 D_THEME_INIT_WIDGET(DCheckBox)
2424 }
2525
26 DWIDGET_NAMESPACE_END
26 DWIDGET_END_NAMESPACE
1313
1414 #include "libdui_global.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 class DCheckBox : public QCheckBox
1919 {
2323 explicit DCheckBox(const QString &text, QWidget *parent=0);
2424 };
2525
26 DWIDGET_NAMESPACE_END
26 DWIDGET_END_NAMESPACE
2727
2828 #endif // DCHECKBOX_H
1414 #include <QDebug>
1515 #include <QVBoxLayout>
1616
17 USE_NAMESPACE_DWIDGET
17 DWIDGET_USE_NAMESPACE
1818
1919 DCircleProgressPrivate::DCircleProgressPrivate(DCircleProgress *q)
2020 : DObjectPrivate(q)
1717 #include <QLabel>
1818 #include <QPixmap>
1919
20 DWIDGET_NAMESPACE_BEGIN
20 DWIDGET_BEGIN_NAMESPACE
2121
2222 class DCircleProgressPrivate;
2323 class LIBDUISHARED_EXPORT DCircleProgress : public QWidget, public DObject
6666 D_DECLARE_PRIVATE(DCircleProgress)
6767 };
6868
69 DWIDGET_NAMESPACE_END
69 DWIDGET_END_NAMESPACE
7070
7171 #endif // DCIRCLEPROGRESS_H
99 #include "dcolorcombobox.h"
1010 #include "private/dcombobox_p.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 class ColorDelegateItem : public DComboBoxItem
1515 {
173173 emit currentColorChange(QColor(colorObj["itemColor"].toString()));
174174 }
175175
176 DWIDGET_NAMESPACE_END
176 DWIDGET_END_NAMESPACE
177177
178178 #include "dcolorcombobox.moc"
2525 #include "dcombobox.h"
2626 #include "dabstractcomboboxdelegate.h"
2727
28 DWIDGET_NAMESPACE_BEGIN
28 DWIDGET_BEGIN_NAMESPACE
2929
3030 class DColorComboBoxPrivate;
3131 class LIBDUISHARED_EXPORT DColorComboBox : public DComboBox
4646 D_DECLARE_PRIVATE(DColorComboBox)
4747 };
4848
49 DWIDGET_NAMESPACE_END
49 DWIDGET_END_NAMESPACE
5050
5151 #endif // DCOLORCOMBOBOX_H
1313 #include <QPainter>
1414 #include <QMouseEvent>
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 DColorPicker::DColorPicker(int row, int column, int cellSize,
1919 int spacing, int margin,
295295 (m_row-1)*(m_cellSize+m_spacing)+m_cellSize+m_margin*2);
296296 }
297297
298 DWIDGET_NAMESPACE_END
298 DWIDGET_END_NAMESPACE
1414 #include <QColor>
1515 #include "libdui_global.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DColorPicker : public QFrame
2020 {
9797 QColor m_selectedBorderColor;
9898 };
9999
100 DWIDGET_NAMESPACE_END
100 DWIDGET_END_NAMESPACE
101101
102102 #endif // DCOLORPICKER_H
1616 #include "dcombobox.h"
1717 #include "dthememanager.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 DComboBoxPrivate::DComboBoxPrivate(DComboBox *parent) :
2222 DObjectPrivate(parent)
364364 emit focusChanged(false);
365365 }
366366
367 DWIDGET_NAMESPACE_END
367 DWIDGET_END_NAMESPACE
368368
369369 #include "moc_dcombobox.cpp"
2222 #include "dconstants.h"
2323 #include "dcomboboxmodel.h"
2424
25 DWIDGET_NAMESPACE_BEGIN
25 DWIDGET_BEGIN_NAMESPACE
2626
2727 class DComboBoxPrivate;
2828
7272 Q_PRIVATE_SLOT(d_func(), void _q_slotCurrentIndexChange(int index))
7373 };
7474
75 DWIDGET_NAMESPACE_END
75 DWIDGET_END_NAMESPACE
7676
7777 #endif // DCOMBOBOX_H
88
99 #include "dcomboboxmodel.h"
1010
11 USE_NAMESPACE_DWIDGET
11 DWIDGET_USE_NAMESPACE
1212
1313 DComboBoxModel::DComboBoxModel(QObject *parent) : QAbstractItemModel(parent)
1414 {
1818
1919 #include "libdui_global.h"
2020
21 DWIDGET_NAMESPACE_BEGIN
21 DWIDGET_BEGIN_NAMESPACE
2222
2323 class LIBDUISHARED_EXPORT DComboBoxModel : public QAbstractItemModel
2424 {
4848 QJsonArray m_dataArray;
4949 };
5050
51 DWIDGET_NAMESPACE_END
51 DWIDGET_END_NAMESPACE
5252
5353 #endif // DCOMBOBOXSIMPLEMODEL_H
1919
2020 #include "libdui_global.h"
2121
22 DWIDGET_NAMESPACE_BEGIN
22 DWIDGET_BEGIN_NAMESPACE
2323 //basis width and height
2424 const int BUTTON_HEIGHT = 22;
2525 const int EXPAND_HEADER_HEIGHT = 30;
3636 const int IMAGE_BUTTON_WIDTH = 24;
3737 const int FONT_SIZE = 12;
3838 const int NORMAL_RADIUS = 3;
39 DWIDGET_NAMESPACE_END
39 DWIDGET_END_NAMESPACE
4040
4141 #endif //DCONSTANTS_H
2424 #include "dthememanager.h"
2525 #include "dboxwidget.h"
2626
27 DWIDGET_NAMESPACE_BEGIN
27 DWIDGET_BEGIN_NAMESPACE
2828
2929 DDialogPrivate::DDialogPrivate(DDialog *qq) :
3030 DAbstractDialogPrivate(qq)
642642 emit closed();
643643 }
644644
645 DWIDGET_NAMESPACE_END
645 DWIDGET_END_NAMESPACE
646646
647647 #include "moc_ddialog.cpp"
1919 class QCloseEvent;
2020 class QVBoxLayout;
2121
22 DWIDGET_NAMESPACE_BEGIN
22 DWIDGET_BEGIN_NAMESPACE
2323
2424 class DDialogPrivate;
2525 class DDialog : public DAbstractDialog
107107 Q_PRIVATE_SLOT(d_func(), void _q_defaultButtonTriggered())
108108 };
109109
110 DWIDGET_NAMESPACE_END
110 DWIDGET_END_NAMESPACE
111111
112112 #endif // DDIALOG_H
1111
1212 #include "denhancedwidget.h"
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 class DEnhancedWidgetPrivate
1717 {
155155 }
156156 }
157157
158 DWIDGET_NAMESPACE_END
158 DWIDGET_END_NAMESPACE
1313
1414 #include "libdui_global.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 class DEnhancedWidgetPrivate;
1919 class DEnhancedWidget: public QObject
5555 Q_DECLARE_PRIVATE(DEnhancedWidget)
5656 };
5757
58 DWIDGET_NAMESPACE_END
58 DWIDGET_END_NAMESPACE
5959
6060 #endif // DENHANCEDWIDGET_H
88
99 #include "dexpandgroup.h"
1010
11 USE_NAMESPACE_DWIDGET
11 DWIDGET_USE_NAMESPACE
1212
1313 DExpandGroup::DExpandGroup(QObject *parent) : QObject(parent)
1414 {
1616 #include "libdui_global.h"
1717 #include "dbaseexpand.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class LIBDUISHARED_EXPORT DExpandGroup : public QObject
2222 {
4141 QMap<int, DBaseExpand *> m_checkedMap;
4242 };
4343
44 DWIDGET_NAMESPACE_END
44 DWIDGET_END_NAMESPACE
4545
4646 #endif // EXPANDGROUP_H
1515 #include <QScreen>
1616 #include <QGuiApplication>
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 DFileChooserEdit::DFileChooserEdit(QWidget *parent)
2121 : DLineEdit(*new DFileChooserEditPrivate(this), parent)
9191 q->dialogClosed(code);
9292 }
9393
94 DWIDGET_NAMESPACE_END
94 DWIDGET_END_NAMESPACE
9595
9696 #include "moc_dfilechooseredit.cpp"
1111
1212 #include "dlineedit.h"
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 class DFileChooserEditPrivate;
1717 class LIBDUISHARED_EXPORT DFileChooserEdit : public DLineEdit
4646 Q_PRIVATE_SLOT(d_func(), void _q_showFileChooserDialog())
4747 };
4848
49 DWIDGET_NAMESPACE_END
49 DWIDGET_END_NAMESPACE
5050
5151 #endif // DFILECHOOSEREDIT_H
1212 #include "dflowlayout.h"
1313 #include "private/dflowlayout_p.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DFlowLayoutPrivate::DFlowLayoutPrivate(DFlowLayout *qq) :
1818 DObjectPrivate(qq)
384384 invalidate();
385385 }
386386
387 DWIDGET_NAMESPACE_END
387 DWIDGET_END_NAMESPACE
1515
1616 #include "dobject.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DFlowLayoutPrivate;
2121 class DFlowLayout : public QLayout, public DObject
7878 D_DECLARE_PRIVATE(DFlowLayout)
7979 };
8080
81 DWIDGET_NAMESPACE_END
81 DWIDGET_END_NAMESPACE
8282
8383 #endif // DFLOWLAYOUT_H
1111 #include "dfontcombobox.h"
1212 #include "private/dcombobox_p.h"
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 class FontDelegateItem : public DComboBoxItem
1717 {
110110 emit currentFontNameChange(nameObj["itemFont"].toString());
111111 }
112112
113 DWIDGET_NAMESPACE_END
113 DWIDGET_END_NAMESPACE
114114
115115 #include "dfontcombobox.moc"
2424 #include "dcomboboxmodel.h"
2525 #include "dabstractcomboboxdelegate.h"
2626
27 DWIDGET_NAMESPACE_BEGIN
27 DWIDGET_BEGIN_NAMESPACE
2828
2929 class LIBDUISHARED_EXPORT DFontComboBox : public DComboBox
3030 {
4040 void onCurrentIndexChange(int index);
4141 };
4242
43 DWIDGET_NAMESPACE_END
43 DWIDGET_END_NAMESPACE
4444
4545 #endif // DFONTCOMBOBOX_H
88
99 #include "dgraphicsgloweffect.h"
1010
11 USE_NAMESPACE_DWIDGET
11 DWIDGET_USE_NAMESPACE
1212
1313 DGraphicsGlowEffect::DGraphicsGlowEffect(QObject *parent) :
1414 QGraphicsEffect(parent),
1515
1616 #include "libdui_global.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class LIBDUISHARED_EXPORT DGraphicsGlowEffect : public QGraphicsEffect
2121 {
4949 QColor m_color;
5050 };
5151
52 DWIDGET_NAMESPACE_END
52 DWIDGET_END_NAMESPACE
5353
5454 #endif // DGRAPHICSGLOWEFFECT_H
99 #include "dheaderline.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DHeaderLine::DHeaderLine(QWidget *parent) : DBaseLine(parent)
1515 {
3333 setFixedHeight(CONTENT_HEADER_HEIGHT);
3434 }
3535
36 DWIDGET_NAMESPACE_END
36 DWIDGET_END_NAMESPACE
1515 #include "libdui_global.h"
1616 #include "dbaseline.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class LIBDUISHARED_EXPORT DHeaderLine : public DBaseLine
2121 {
3333 QLabel *m_titleLabel = NULL;
3434 };
3535
36 DWIDGET_NAMESPACE_END
36 DWIDGET_END_NAMESPACE
3737
3838 #endif // DHEADERLINE_H
1111
1212 #include "libdui_global.h"
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 namespace DIALOG {
1717 const int DEFAULT_WIDTH = 380;
3131 const int BUTTON_LAYOUT_RIGHT_MARGIN = 2;
3232 }
3333
34 DWIDGET_NAMESPACE_END
34 DWIDGET_END_NAMESPACE
3535
3636 #endif // BUTTON_CONSTANTS_H
3737
1313 #include <QMouseEvent>
1414 #include <QEvent>
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 DImageButton::DImageButton(QWidget *parent)
1919 : QLabel(parent)
193193 return m_state;
194194 }
195195
196 DWIDGET_NAMESPACE_END
196 DWIDGET_END_NAMESPACE
1616
1717 #include "libdui_global.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class LIBDUISHARED_EXPORT DImageButton : public QLabel
2222 {
8181 QString m_checkedPic;
8282 };
8383
84 DWIDGET_NAMESPACE_END
84 DWIDGET_END_NAMESPACE
8585
8686 #endif // DIMAGEBUTTON_H
1616 #include "dlabel.h"
1717 #include "dpasswordedit.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 DInputDialogPrivate::DInputDialogPrivate(DInputDialog *qq) :
2222 DDialogPrivate(qq)
472472 return dialog.doubleValue();
473473 }
474474
475 DWIDGET_NAMESPACE_END
475 DWIDGET_END_NAMESPACE
1515 #include "dlineedit.h"
1616 #include "dobject.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DInputDialogPrivate;
2121 class DInputDialog : public DDialog
148148 D_DECLARE_PRIVATE(DInputDialog)
149149 };
150150
151 DWIDGET_NAMESPACE_END
151 DWIDGET_END_NAMESPACE
152152
153153 #endif // DINPUTDIALOG_H
1717 #include "dipv4lineedit.h"
1818 #include "private/dipv4lineedit_p.h"
1919
20 DWIDGET_NAMESPACE_BEGIN
20 DWIDGET_BEGIN_NAMESPACE
2121
2222 #define RX_PATTERN_IP "^(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)?$"
2323
407407
408408 #include "moc_dipv4lineedit.cpp"
409409
410 DWIDGET_NAMESPACE_END
410 DWIDGET_END_NAMESPACE
1111
1212 #include "dlineedit.h"
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 class DIpv4LineEditPrivate;
1717 class DIpv4LineEdit : public DLineEdit
5555 Q_PRIVATE_SLOT(d_func(), void _q_setIpLineEditText(const QString &))
5656 };
5757
58 DWIDGET_NAMESPACE_END
58 DWIDGET_END_NAMESPACE
5959
6060 #endif // DIPV4LINEEDIT_H
99 #include "dlabel.h"
1010 #include "dthememanager.h"
1111
12 USE_NAMESPACE_DWIDGET
12 DWIDGET_USE_NAMESPACE
1313
1414 DLabel::DLabel(QWidget *parent, Qt::WindowFlags f)
1515 : QLabel(parent, f)
1414
1515 #include "libdui_global.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DLabel : public QLabel
2020 {
2525 DLabel(const QString & text, QWidget * parent = 0, Qt::WindowFlags f = 0);
2626 };
2727
28 DWIDGET_NAMESPACE_END
28 DWIDGET_END_NAMESPACE
2929
3030 #endif // DLABEL_H
1414 #include <QDebug>
1515 #include <QResizeEvent>
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 DLineEdit::DLineEdit(QWidget *parent)
2020 : QLineEdit(parent),
164164 m_insideFrame->setFixedWidth(size.width());
165165 }
166166
167 DWIDGET_NAMESPACE_END
167 DWIDGET_END_NAMESPACE
168168
169169 #include "moc_dlineedit.cpp"
1414 #include "libdui_global.h"
1515 #include "dobject.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DLineEditPrivate;
2020 class LIBDUISHARED_EXPORT DLineEdit : public QLineEdit, public DObject
6161 Q_PRIVATE_SLOT(d_func(), void _q_resizeInsideFrame(const QSize &))
6262 };
6363
64 DWIDGET_NAMESPACE_END
64 DWIDGET_END_NAMESPACE
6565
6666 #endif // DLINEEDIT_H
99 #include "dlinkbutton.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DLinkButton::DLinkButton(const QString &text, QWidget *parent) :
1515 QPushButton(text, parent)
1717 D_THEME_INIT_WIDGET(DLinkButton);
1818 }
1919
20 DWIDGET_NAMESPACE_END
20 DWIDGET_END_NAMESPACE
1313
1414 #include "libdui_global.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 class LIBDUISHARED_EXPORT DLinkButton : public QPushButton
1919 {
2323 DLinkButton(const QString & text = QString(), QWidget * parent = 0);
2424 };
2525
26 DWIDGET_NAMESPACE_END
26 DWIDGET_END_NAMESPACE
2727
2828 #endif // DLINKBUTTON_H
1515 #include "private/dlistview_p.h"
1616 #include "dflowlayout.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DListItemCreator
2121 {
833833
834834 #include "moc_dlistview.cpp"
835835
836 DWIDGET_NAMESPACE_END
836 DWIDGET_END_NAMESPACE
1414
1515 #include "dobject.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DVariantListModel : public QAbstractListModel
2020 {
146146 Q_PRIVATE_SLOT(d_func(), void _q_onItemPaint(const QStyleOptionViewItem&, const QModelIndex&))
147147 };
148148
149 DWIDGET_NAMESPACE_END
149 DWIDGET_END_NAMESPACE
150150
151151 #endif // DLISTVIEW_H
1616 #include "dlistwidget.h"
1717 #include "private/dlistwidget_p.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 DListWidgetPrivate::DListWidgetPrivate(DListWidget *qq):
2222 DScrollAreaPrivate(qq),
540540 d_func()->init();
541541 }
542542
543 DWIDGET_NAMESPACE_END
543 DWIDGET_END_NAMESPACE
1515 #include "dscrollarea.h"
1616 #include "libdui_global.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DListWidgetPrivate;
2121 class DListWidget : public DScrollArea
112112 D_DECLARE_PRIVATE(DListWidget)
113113 };
114114
115 DWIDGET_NAMESPACE_END
115 DWIDGET_END_NAMESPACE
116116
117117 #endif // DLISTWIDGET_H
1313 #include "private/dloadingindicator_p.h"
1414 #include "dthememanager.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 DLoadingIndicatorPrivate::DLoadingIndicatorPrivate(DLoadingIndicator *qq) :
1919 DObjectPrivate(qq)
280280 }
281281
282282
283 DWIDGET_NAMESPACE_END
283 DWIDGET_END_NAMESPACE
2424 #include "libdui_global.h"
2525 #include "dobject.h"
2626
27 DWIDGET_NAMESPACE_BEGIN
27 DWIDGET_BEGIN_NAMESPACE
2828
2929 class DLoadingIndicatorPrivate;
3030 class LIBDUISHARED_EXPORT DLoadingIndicator : public QGraphicsView, public DObject
8888 D_DECLARE_PRIVATE(DLoadingIndicator)
8989 };
9090
91 DWIDGET_NAMESPACE_END
91 DWIDGET_END_NAMESPACE
9292
9393 #endif // DLOADINGINDICATOR_H
99 #include "dobject.h"
1010 #include "private/dobject_p.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DObjectPrivate::DObjectPrivate(DObject *qq)
1515 : q_ptr(qq)
3333
3434 }
3535
36 DWIDGET_NAMESPACE_END
36 DWIDGET_END_NAMESPACE
1313
1414 #include "libdui_global.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 #define D_DECLARE_PRIVATE(Class) Q_DECLARE_PRIVATE_D(qGetPtrHelper(d_d_ptr),Class)
1919 #define D_DECLARE_PUBLIC(Class) Q_DECLARE_PUBLIC(Class)
3636 D_DECLARE_PRIVATE(DObject)
3737 };
3838
39 DWIDGET_NAMESPACE_END
39 DWIDGET_END_NAMESPACE
4040
4141 #endif // DOBJECT_H
1414 #include <QDebug>
1515 #include <QResizeEvent>
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 DOptionPrivate::DOptionPrivate(DOption *q) :
2020 DObjectPrivate(q)
202202 d->sizeChanged(e);
203203 }
204204
205 DWIDGET_NAMESPACE_END
205 DWIDGET_END_NAMESPACE
206206
207207 #include "moc_doption.cpp"
1515 #include <QFrame>
1616 #include <QHBoxLayout>
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DOptionPrivate;
2121 class LIBDUISHARED_EXPORT DOption : public QFrame, public DObject
5252 void checkedIconChanged(const QString checkedIcon) const;
5353 };
5454
55 DWIDGET_NAMESPACE_END
55 DWIDGET_END_NAMESPACE
5656
5757 #endif // DOPTION_H
1414
1515 #include <QDebug>
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 DOptionListPrivate::DOptionListPrivate(DOptionList *q) :
2020 DObjectPrivate(q)
132132 d->setCurrentSelected(value);
133133 }
134134
135 DWIDGET_NAMESPACE_END
135 DWIDGET_END_NAMESPACE
136136
137137 #include "moc_doptionlist.cpp"
1515
1616 #include <QListWidget>
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DOptionListPrivate;
2121 class LIBDUISHARED_EXPORT DOptionList : public QListWidget, public DObject
3737 D_PRIVATE_SLOT(void _q_currentItemChanged(QListWidgetItem*,QListWidgetItem*))
3838 };
3939
40 DWIDGET_NAMESPACE_END
40 DWIDGET_END_NAMESPACE
4141
4242 #endif // DOPTIONLIST_H
1212
1313 #include <QDebug>
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DPasswordEdit::DPasswordEdit(QWidget *parent)
1818 : DLineEdit(*new DPasswordEditPrivate(this), parent)
6262 q->setEchoMode(q->Normal);
6363 }
6464
65 DWIDGET_NAMESPACE_END
65 DWIDGET_END_NAMESPACE
6666
6767 #include "moc_dpasswordedit.cpp"
6868
1111
1212 #include "dlineedit.h"
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 class DPasswordEditPrivate;
1717 class LIBDUISHARED_EXPORT DPasswordEdit : public DLineEdit
3131 Q_PRIVATE_SLOT(d_func(), void _q_toggleEchoMode())
3232 };
3333
34 DWIDGET_NAMESPACE_END
34 DWIDGET_END_NAMESPACE
3535
3636 #endif // DPASSWORDEDIT_H
1111
1212 #include <QGraphicsPixmapItem>
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 DPictureSequenceViewPrivate::DPictureSequenceViewPrivate(DPictureSequenceView *q) :
1717 DObjectPrivate(q)
145145 d->setSingleShot(singleShot);
146146 }
147147
148 DWIDGET_NAMESPACE_END
148 DWIDGET_END_NAMESPACE
149149
150150 #include "moc_dpicturesequenceview.cpp"
1414
1515 #include <QGraphicsView>
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DPictureSequenceViewPrivate;
2020 class DPictureSequenceView : public QGraphicsView, public DObject
4242 void playEnd() const;
4343 };
4444
45 DWIDGET_NAMESPACE_END
45 DWIDGET_END_NAMESPACE
4646
4747 #endif // DPICTURESEQUENCEVIEW_H
1717 #include "dscrollbar.h"
1818 #include "private/dscrollarea_p.h"
1919
20 DWIDGET_NAMESPACE_BEGIN
20 DWIDGET_BEGIN_NAMESPACE
2121
2222 DScrollAreaPrivate::DScrollAreaPrivate(DScrollArea *qq):
2323 DObjectPrivate(qq),
162162 d_func()->init();
163163 }
164164
165 DWIDGET_NAMESPACE_END
165 DWIDGET_END_NAMESPACE
1414 #include "libdui_global.h"
1515 #include "dobject.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DScrollBar;
2020 class DScrollAreaPrivate;
4646 D_DECLARE_PRIVATE(DScrollArea)
4747 };
4848
49 DWIDGET_NAMESPACE_END
49 DWIDGET_END_NAMESPACE
5050
5151 #endif // DSCROLLAREA_H
99 #include "dscrollbar.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DScrollBar::DScrollBar(QWidget *parent) : QScrollBar(parent)
1515 {
1717 }
1818
1919
20 DWIDGET_NAMESPACE_END
20 DWIDGET_END_NAMESPACE
1313
1414 #include "libdui_global.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 class LIBDUISHARED_EXPORT DScrollBar : public QScrollBar
1919 {
2626 public slots:
2727 };
2828
29 DWIDGET_NAMESPACE_END
29 DWIDGET_END_NAMESPACE
3030
3131 #endif // DSCROLLBAR_H
1717 #include <QResizeEvent>
1818 #include <QTimer>
1919
20 USE_NAMESPACE_DWIDGET
20 DWIDGET_USE_NAMESPACE
2121
2222 DSearchEdit::DSearchEdit(QWidget *parent)
2323 : QFrame(parent)
1717 #include "libdui_global.h"
1818 #include "dimagebutton.h"
1919
20 DWIDGET_NAMESPACE_BEGIN
20 DWIDGET_BEGIN_NAMESPACE
2121
2222 class LIBDUISHARED_EXPORT DSearchEdit : public QFrame
2323 {
6666 QEasingCurve m_hideCurve = QEasingCurve::InCubic;
6767 };
6868
69 DWIDGET_NAMESPACE_END
69 DWIDGET_END_NAMESPACE
7070
7171 #endif // DSEARCHEDIT_H
1313 #include <QApplication>
1414 #include "dthememanager.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 DSegmentedHighlight::DSegmentedHighlight(QWidget *parent) :
1919 QToolButton(parent)
289289 }
290290 }
291291
292 DWIDGET_NAMESPACE_END
292 DWIDGET_END_NAMESPACE
1717 #include <QEasingCurve>
1818 #include "libdui_global.h"
1919
20 DWIDGET_NAMESPACE_BEGIN
20 DWIDGET_BEGIN_NAMESPACE
2121
2222 class DSegmentedHighlight : public QToolButton
2323 {
8585 void animationDurationChanged(int animationDuration);
8686 };
8787
88 DWIDGET_NAMESPACE_END
88 DWIDGET_END_NAMESPACE
8989 #endif // DSEGMENTEDCONTROL_H
99 #include "dseparatorhorizontal.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DSeparatorHorizontal::DSeparatorHorizontal(QWidget *parent) : QWidget(parent)
1515 {
3535 this->setLayout(mainLayout);
3636 }
3737
38 DWIDGET_NAMESPACE_END
38 DWIDGET_END_NAMESPACE
1414
1515 #include "libdui_global.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DSeparatorHorizontal : public QWidget
2020 {
2727 QWidget *m_bottomRec = NULL;
2828 };
2929
30 DWIDGET_NAMESPACE_END
30 DWIDGET_END_NAMESPACE
3131
3232 #endif // DSEPARATORHORIZONTAL_H
99 #include "dseparatorvertical.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DSeparatorVertical::DSeparatorVertical(QWidget *parent) : QWidget(parent)
1515 {
3535 this->setLayout(mainLayout);
3636 }
3737
38 DWIDGET_NAMESPACE_END
38 DWIDGET_END_NAMESPACE
1414
1515 #include "libdui_global.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DSeparatorVertical : public QWidget
2020 {
2727 QWidget *m_rightRec = NULL;
2828 };
2929
30 DWIDGET_NAMESPACE_END
30 DWIDGET_END_NAMESPACE
3131
3232 #endif // DSEPARATORVERTICAL_H
1616
1717 #include <cctype>
1818
19 USE_NAMESPACE_DWIDGET
19 DWIDGET_USE_NAMESPACE
2020
2121 // static const varibles
2222 const QString DShortcutEdit::DefaultTips = tr("请输入新的快捷键");
1818
1919 #include "libdui_global.h"
2020
21 DWIDGET_NAMESPACE_BEGIN
21 DWIDGET_BEGIN_NAMESPACE
2222
2323 class DShortcutEditLabel;
2424 class LIBDUISHARED_EXPORT DShortcutEdit : public QFrame
9696 EchoState m_state = Normal;
9797 };
9898
99 DWIDGET_NAMESPACE_END
99 DWIDGET_END_NAMESPACE
100100
101101 #endif // DSHORTCUTEDIT_H
99 #include "dsimplecombobox.h"
1010 #include "private/dcombobox_p.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 class SimpleDelegateItem : public DComboBoxItem
1515 {
102102 emit currentTextChanged(nameObj["itemText"].toString());
103103 }
104104
105 DWIDGET_NAMESPACE_END
105 DWIDGET_END_NAMESPACE
106106
107107 #include "dsimplecombobox.moc"
1616 #include "dabstractcomboboxdelegate.h"
1717 #include "dcombobox.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class LIBDUISHARED_EXPORT DSimpleComboBox : public DComboBox
2222 {
3434 Q_SLOT void onCurrentIndexChange(int index);
3535 };
3636
37 DWIDGET_NAMESPACE_END
37 DWIDGET_END_NAMESPACE
3838
3939 #endif // DSIMPLECOMBOBOX_H
1616 #include "dslider.h"
1717 #include "dthememanager.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 static const int CustomDrawingLeftPadding = 10;
2222 static const int CustomDrawingRightPadding = 10;
453453 sliderMax - sliderMin, opt.upsideDown);
454454 }
455455
456 DWIDGET_NAMESPACE_END
456 DWIDGET_END_NAMESPACE
1313
1414 #include "libdui_global.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 class DSliderPrivate;
1919 class LIBDUISHARED_EXPORT DSlider : public QSlider
8383 Q_DISABLE_COPY(DSlider)
8484 };
8585
86 DWIDGET_NAMESPACE_END
86 DWIDGET_END_NAMESPACE
8787
8888 #endif // DSLIDER_H
1616 #include "private/dspinbox_p.h"
1717 #include "dimagebutton.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 DImageButton* DSpinBox_getButton(const QString &image_name)
2222 {
222222 d_func()->_q_resizeInsideFrame(e->size());
223223 }
224224
225 DWIDGET_NAMESPACE_END
225 DWIDGET_END_NAMESPACE
1414 #include "libdui_global.h"
1515 #include "dobject.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DSpinBoxPrivate;
2020 class DSpinBox : public QSpinBox, public DObject
7777 double m_defaultValue;
7878 };
7979
80 DWIDGET_NAMESPACE_END
80 DWIDGET_END_NAMESPACE
8181
8282 #endif // DSPINBOX_H
1212 #include "dstackwidget.h"
1313 #include "private/dstackwidget_p.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DAbstractStackWidgetTransitionPrivate::DAbstractStackWidgetTransitionPrivate(DAbstractStackWidgetTransition *qq):
1818 DObjectPrivate(qq),
367367 d_func()->init();
368368 }
369369
370 DWIDGET_NAMESPACE_END
370 DWIDGET_END_NAMESPACE
1515 #include "dobject.h"
1616 #include "libdui_global.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DStackWidget;
2121 class DAbstractStackWidgetTransitionPrivate;
136136 D_DECLARE_PRIVATE(DStackWidget)
137137 };
138138
139 DWIDGET_NAMESPACE_END
139 DWIDGET_END_NAMESPACE
140140
141141 #endif // DSTACKWIDGET_H
1313 #include <QDebug>
1414 #include "dthememanager.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 DSwitchButton::DSwitchButton(QWidget *parent) :
1919 QFrame(parent),
192192 }
193193 }
194194
195 DWIDGET_NAMESPACE_END
195 DWIDGET_END_NAMESPACE
1515 #include <QUrl>
1616 #include "libdui_global.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DSwitchButton : public QFrame
2121 {
7474 QString m_enabledImageSource;
7575 };
7676
77 DWIDGET_NAMESPACE_END
77 DWIDGET_END_NAMESPACE
7878 #endif // DSWITCHBUTTON_H
7979
1111
1212 #include <QResizeEvent>
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 SwitchHeaderLine::SwitchHeaderLine(QWidget *parent) :
1717 DHeaderLine(parent)
7171 DBaseExpand::resizeEvent(e);
7272 }
7373
74 DWIDGET_NAMESPACE_END
74 DWIDGET_END_NAMESPACE
1616 #include "dswitchbutton.h"
1717 #include "dheaderline.h"
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class SwitchHeaderLine : public DHeaderLine
2222 {
5555 SwitchHeaderLine *m_headerLine = NULL;
5656 };
5757
58 DWIDGET_NAMESPACE_END
58 DWIDGET_END_NAMESPACE
5959
6060 #endif // DSWITCHLINEEXPAND_H
99 #include "dtextbutton.h"
1010 #include "dthememanager.h"
1111
12 DWIDGET_NAMESPACE_BEGIN
12 DWIDGET_BEGIN_NAMESPACE
1313
1414 DTextButton::DTextButton(const QString & text, QWidget * parent) :
1515 QPushButton(text, parent)
2222
2323 }
2424
25 DWIDGET_NAMESPACE_END
25 DWIDGET_END_NAMESPACE
1414
1515 #include "libdui_global.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DTextButton : public QPushButton
2020 {
2424 ~DTextButton();
2525 };
2626
27 DWIDGET_NAMESPACE_END
27 DWIDGET_END_NAMESPACE
2828
2929 #endif // DTEXTBUTTON_H
1313 #include "dapplication.h"
1414 #include "private/dthemehelper.h"
1515
16 DWIDGET_NAMESPACE_BEGIN
16 DWIDGET_BEGIN_NAMESPACE
1717
1818 class DThemeManagerPrivate : public DThemeManager
1919 {
7171 }
7272
7373
74 DWIDGET_NAMESPACE_END
74 DWIDGET_END_NAMESPACE
1515
1616 #include "libdui_global.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DThemeManager : public QObject
2121 {
4141 QString m_theme;
4242 };
4343
44 DWIDGET_NAMESPACE_END
44 DWIDGET_END_NAMESPACE
4545
4646 #endif // DTHEMEMANAGER_H
1212
1313 #include "dwindowclosebutton.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DWindowCloseButton::DWindowCloseButton(QWidget * parent) :
1818 DImageButton(parent)
5656 this->setPressPic(m_pressedImage);
5757 }
5858
59 DWIDGET_NAMESPACE_END
59 DWIDGET_END_NAMESPACE
6060
6161
1414
1515 #include "dimagebutton.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DWindowCloseButton : public DImageButton
2020 {
4141 QString m_pressedImage;
4242 };
4343
44 DWIDGET_NAMESPACE_END
44 DWIDGET_END_NAMESPACE
4545
4646 #endif // DWINDOWCLOSEBUTTON_H
1212
1313 #include "dwindowmaxbutton.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DWindowMaxButton::DWindowMaxButton(QWidget * parent) :
1818 DImageButton(parent)
5656 this->setPressPic(m_pressedImage);
5757 }
5858
59 DWIDGET_NAMESPACE_END
59 DWIDGET_END_NAMESPACE
6060
6161
1414
1515 #include "dimagebutton.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DWindowMaxButton : public DImageButton
2020 {
4141 QString m_pressedImage;
4242 };
4343
44 DWIDGET_NAMESPACE_END
44 DWIDGET_END_NAMESPACE
4545
4646 #endif // DWINDOWMAXBUTTON_H
1414
1515 #include "dwindowminbutton.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 DWindowMinButton::DWindowMinButton(QWidget * parent) :
2020 DImageButton(parent)
5858 this->setPressPic(m_pressedImage);
5959 }
6060
61 DWIDGET_NAMESPACE_END
61 DWIDGET_END_NAMESPACE
1111
1212 #include "dimagebutton.h"
1313
14 DWIDGET_NAMESPACE_BEGIN
14 DWIDGET_BEGIN_NAMESPACE
1515
1616 class LIBDUISHARED_EXPORT DWindowMinButton : public DImageButton
1717 {
3838 QString m_pressedImage;
3939 };
4040
41 DWIDGET_NAMESPACE_END
41 DWIDGET_END_NAMESPACE
4242
4343 #endif // DWINDOWMINBUTTON_H
1212
1313 #include "dwindowoptionbutton.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DWindowOptionButton::DWindowOptionButton(QWidget * parent) :
1818 DImageButton(parent)
5656 this->setPressPic(m_pressedImage);
5757 }
5858
59 DWIDGET_NAMESPACE_END
59 DWIDGET_END_NAMESPACE
6060
6161
1414
1515 #include "dimagebutton.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DWindowOptionButton : public DImageButton
2020 {
4141 QString m_pressedImage;
4242 };
4343
44 DWIDGET_NAMESPACE_END
44 DWIDGET_END_NAMESPACE
4545
4646 #endif // DWINDOWOPTIONBUTTON_H
1212
1313 #include "dwindowrestorebutton.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 DWindowRestoreButton::DWindowRestoreButton(QWidget * parent) :
1818 DImageButton(parent)
5656 this->setPressPic(m_pressedImage);
5757 }
5858
59 DWIDGET_NAMESPACE_END
59 DWIDGET_END_NAMESPACE
6060
6161
1414
1515 #include "dimagebutton.h"
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class LIBDUISHARED_EXPORT DWindowRestoreButton : public DImageButton
2020 {
4141 QString m_pressedImage;
4242 };
4343
44 DWIDGET_NAMESPACE_END
44 DWIDGET_END_NAMESPACE
4545
4646 #endif // DWINDOWRESTOREBUTTON_H
1414
1515 class QBoxLayout;
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DAbstractDialogPrivate : public DObjectPrivate
2020 {
3838 Q_DECLARE_PUBLIC(DAbstractDialog)
3939 };
4040
41 DWIDGET_NAMESPACE_END
41 DWIDGET_END_NAMESPACE
4242
4343 #endif // DABSTRACTDIALOG_P_H
4444
1414
1515 class QBoxLayout;
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DBoxWidgetPrivate : public DObjectPrivate
2020 {
2727 Q_DECLARE_PUBLIC(DBoxWidget)
2828 };
2929
30 DWIDGET_NAMESPACE_END
30 DWIDGET_END_NAMESPACE
3131
3232 #endif // DBOXWIDGET_P_H
3333
1616
1717 #include <QPainter>
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class DCircleProgressPrivate : public DObjectPrivate
2222 {
4141 QColor m_backgroundColor = Qt::darkCyan;
4242 };
4343
44 DWIDGET_NAMESPACE_END
44 DWIDGET_END_NAMESPACE
4545
4646 #endif // DCIRCLEPROGRESS_P_H
1212 #include "dobject_p.h"
1313 #include "dcombobox.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 class DComboBoxItem;
1818
7575 bool m_hovered = false;
7676 };
7777
78 DWIDGET_NAMESPACE_END
78 DWIDGET_END_NAMESPACE
7979
8080 #endif // DCOMBOBOX_P_H
8181
1616
1717 class QHBoxLayout;
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class DVBoxWidget;
2222 class DHBoxWidget;
5959 Q_DECLARE_PUBLIC(DDialog)
6060 };
6161
62 DWIDGET_NAMESPACE_END
62 DWIDGET_END_NAMESPACE
6363
6464 #endif // DDIALOG_P_H
6565
1515 #include "dfilechooseredit.h"
1616 #include "dimagebutton.h"
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DFileChooserEditPrivate : DLineEditPrivate
2121 {
3232 DFileChooserEdit::DialogDisplayPosition dialogDisplayPosition = DFileChooserEdit::FoloowParentWindow;
3333 };
3434
35 DWIDGET_NAMESPACE_END
35 DWIDGET_END_NAMESPACE
3636
3737 #endif // DFILECHOOSEREDIT_P_H
3838
1414
1515 class QLayoutItem;
1616
17 DWIDGET_NAMESPACE_BEGIN
17 DWIDGET_BEGIN_NAMESPACE
1818
1919 class DFlowLayoutPrivate : public DObjectPrivate
2020 {
3131 D_DECLARE_PUBLIC(DFlowLayout)
3232 };
3333
34 DWIDGET_NAMESPACE_END
34 DWIDGET_END_NAMESPACE
3535
3636 #endif // DFLOWLAYOUT_P_H
3737
1212 #include "dinputdialog.h"
1313 #include "ddialog_p.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 class DLabel;
1818 class DLineEdit;
3737 D_DECLARE_PUBLIC(DInputDialog)
3838 };
3939
40 DWIDGET_NAMESPACE_END
40 DWIDGET_END_NAMESPACE
4141
4242 #endif // DINPUTDIALOG_P_H
4343
1212 #include "dlineedit_p.h"
1313 #include "dipv4lineedit.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 class DIpv4LineEditPrivate : public DLineEditPrivate
1818 {
3636 D_DECLARE_PUBLIC(DIpv4LineEdit)
3737 };
3838
39 DWIDGET_NAMESPACE_END
39 DWIDGET_END_NAMESPACE
4040
4141 #endif // DIPV4LINEEDIT_P_H
4242
1515
1616 #include <QHBoxLayout>
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DLineEditPrivate : public DObjectPrivate
2121 {
3838 QHBoxLayout *m_centeralHLayout;
3939 };
4040
41 DWIDGET_NAMESPACE_END
41 DWIDGET_END_NAMESPACE
4242
4343 #endif // DLINEEDIT_P_H
4444
1212 #include "dobject_p.h"
1313 #include "dlistview.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 class DListItemCreator;
1818 class DBoxWidget;
5858 D_DECLARE_PUBLIC(DListView)
5959 };
6060
61 DWIDGET_NAMESPACE_END
61 DWIDGET_END_NAMESPACE
6262
6363 #endif // DLISTVIEW_P_H
6464
1515
1616 class QVBoxLayout;
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DListWidgetPrivate : public DScrollAreaPrivate
2121 {
4242 D_DECLARE_PUBLIC(DListWidget)
4343 };
4444
45 DWIDGET_NAMESPACE_END
45 DWIDGET_END_NAMESPACE
4646
4747 #endif // DLISTWIDGET_P_H
4848
1212 #include "dloadingindicator.h"
1313 #include "dobject_p.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 class DLoadingIndicatorPrivate : public DObjectPrivate
1818 {
3030 D_DECLARE_PUBLIC(DLoadingIndicator)
3131 };
3232
33 DWIDGET_NAMESPACE_END
33 DWIDGET_END_NAMESPACE
3434
3535 #endif // DLOADINGINDICATOR_P
3636
1212 #include "libdui_global.h"
1313 #include "dobject.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 class DObjectPrivate
1818 {
2727 Q_DECLARE_PUBLIC(DObject)
2828 };
2929
30 DWIDGET_NAMESPACE_END
30 DWIDGET_END_NAMESPACE
3131
3232 #endif // DOBJECT_P_H
3333
1616 #include <QHBoxLayout>
1717 #include <QListWidgetItem>
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class DOptionPrivate : public DObjectPrivate
2222 {
5656 QHBoxLayout *m_layout;
5757 };
5858
59 DWIDGET_NAMESPACE_END
59 DWIDGET_END_NAMESPACE
6060
6161 #endif // DOPTION_P_H
6262
1616 #include <QList>
1717 #include <QListWidgetItem>
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class DOptionListPrivate : public DObjectPrivate
2222 {
3838 QMap<QListWidgetItem *, DOption *> m_optionList;
3939 };
4040
41 DWIDGET_NAMESPACE_END
41 DWIDGET_END_NAMESPACE
4242
4343 #endif // DOPTIONLIST_P_H
1212 #include "dlineedit_p.h"
1313 #include "dpasswordedit.h"
1414
15 DWIDGET_NAMESPACE_BEGIN
15 DWIDGET_BEGIN_NAMESPACE
1616
1717 class DPasswordEditPrivate : DLineEditPrivate
1818 {
2727 Q_DECLARE_PUBLIC(DPasswordEdit)
2828 };
2929
30 DWIDGET_NAMESPACE_END
30 DWIDGET_END_NAMESPACE
3131
3232 #endif // DPASSWORDEDIT_P_H
3333
1616 #include <QGraphicsScene>
1717 #include <QTimer>
1818
19 DWIDGET_NAMESPACE_BEGIN
19 DWIDGET_BEGIN_NAMESPACE
2020
2121 class DPictureSequenceViewPrivate : public DObjectPrivate
2222 {
5252 QList<QGraphicsPixmapItem *> m_pictureList;
5353 };
5454
55 DWIDGET_NAMESPACE_END
55 DWIDGET_END_NAMESPACE
5656
5757 #endif // DPICTURESEQUENCEVIEW_P_H
5858
1515
1616 class QPropertyAnimation;
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DScrollAreaPrivate : public DObjectPrivate
2121 {
3535 D_DECLARE_PUBLIC(DScrollArea)
3636 };
3737
38 DWIDGET_NAMESPACE_END
38 DWIDGET_END_NAMESPACE
3939
4040 #endif // DSCROLLAREA_P_H
1515 class QFrame;
1616 class QLabel;
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DImageButton;
2121 class DSpinBoxPrivate : public DObjectPrivate
4848 D_DECLARE_PUBLIC(DDoubleSpinBox)
4949 };
5050
51 DWIDGET_NAMESPACE_END
51 DWIDGET_END_NAMESPACE
5252
5353 #endif // DSPINBOX_P_H
5454
1515
1616 class QStackedLayout;
1717
18 DWIDGET_NAMESPACE_BEGIN
18 DWIDGET_BEGIN_NAMESPACE
1919
2020 class DAbstractStackWidgetTransitionPrivate : public DObjectPrivate
2121 {
4747 D_DECLARE_PUBLIC(DStackWidget)
4848 };
4949
50 DWIDGET_NAMESPACE_END
50 DWIDGET_END_NAMESPACE
5151
5252 #endif // DSTACKWIDGET_P
5353